php代码之create_function()函数
php代码之create_function()函数
seoraphp代码之create_function()函数
NSS上随机到的一道看题目没什么思路,搜wp看到用到create_function()函数,搜索了解了一下。
create_function()简介
适用 PHP4>4.0.1 PHP 5 PHP7
语法:
1 | create_function(string $args, string $code) |
函数功能:
1 |
|
分析:
create_function() 会创造一个匿名函数 (lambda样式) 此处创建了一个叫 lamvda_1 的函数, 在第一个 echo 中 显示名字, 并在第二个echo 语句中执行了 此函数。
create_function() 函数 会在内部 执行 eval() , 我们发现是执行了 后面的 return 语句,属于create_function() 中的第二个参数 string $code 的位置
因此,上述匿名函数的创建与执行过程等价于:
1 |
|
代码注入实例
0x01
1 |
|
简单看一下php代码,要传入一个GET参数赋值给$sort_by。然后定义$sorter的值是 'strnatcasecmp',这是PHP 的内置比较函数,用于自然排序、忽略大小写。比如传入image1和image10时,他会按照数序大小排列。
之后定义了一个数组,注意这个数字不含键值对,但是后面的代码会假设他是一个“有键的数组”。
在$sort_function部分会通过拼接生成字符串。比如我们输入值为name,就会得到:
1 | return 1 * strnatcasecmp($a["name"], $b["name"]); |
但是如果我们传入恶意参数,比如
1 | ?sort_by=a"]);phpinfo();// |
那最终拼接的字符串就变成:
1 | return 1 * strnatcasecmp($a["a"]);phpinfo();//"], $b["a"]);phpinfo();//"]); |
PHP 会把这段代码交给 create_function 去执行(也就是usort一行),于是这段拼接的字符串被直接“注入”到了函数体里,造成任意代码执行漏洞。
1 | usort($databases, create_function('$a, $b', $sort_function)); |
上面提到,create_function() 会把第二个参数当作 PHP 代码编译成匿名函数。
也就是说,用户可控的 $sort_function 直接被当成php执行。
0x02
1 |
|
我们可以看到,$lambda一行,排序构造部分(也就是之后要生成的匿名函数部分中$c是我们可控的),
payload:
1 | ?c=1));}phpinfo();/* |
0x03(NSSCTF CanCanNeed )
point:反序列化 creat_function函数
1 |
|
分析源代码,我们需要传入一个GET型参数file,参数经过base64解码之后赋值给$file,然后进行反序列化。反序列化过程会触发__destruct()魔术方法,这个魔术方法把$param1赋值给$a,$param2经过过滤之后赋值给$b,之后$a('', $b);
$a('', $b);:
$a 此时是个“可调用”(callable):通常是函数名的字符串、匿名函数(Closure),或者 [$obj, 'method'] 这样的数组。
'' 是传给这个可调用的第一个参数(一个空字符串字面量)。
$b 是第二个参数,值来自上面 $b = $this->param2;。
wp中用到的思路是$param1= "create_function"; $param2="};system(\$_POST[cmd]);//"
通过反序列化实现赋值再通过creat_function匿名函数执行$param2的php代码。
1 |
|
解释一下$param2中{ 的作用:
create_function($args, $code) 内部会 eval 一段模板代码,类似:
1 | eval("function $lambda($args) { $code }"); |
所以第二个参数是用来闭合create_function() 生成的函数体的大括号 {。
references
PHP代码 之create_function()函数_create function-CSDN博客
[NSSCTF第15页(3)_fsctf 2023]cancanneed-CSDN博客


