前言
总觉得作一些专题性的总结会比四处看题来的有效果吧?XD
eval()执行代码
说起RCE
,eval函数自然是应该排在首位,一句话木马就经常用它吧,CMS
出现它,只要参数可控就很可能存在代码执行的可能性。PHP
手册对该函数做出如下定义,其中关键点是该字符串必须是合法的 PHP 代码,且必须以分号结尾。这对构造payload
是非常关键的一点。
定义和用法
eval() 函数把字符串按照 PHP 代码来计算。
该字符串必须是合法的 PHP 代码,且必须以分号结尾。
如果没有在代码字符串中调用 return 语句,则返回 NULL。如果代码中存在解析错误,则 eval() 函数返回 false
下图可以看出,进过各种闭合后,得到了一个符合PHP语法
的语句,于是phpinfo
就被执行了。
assert()的代码执行
这个函数和eval
有些不一样。assert
把整个字符串参数当php代码执行,eval
把合法的php代码执行
还是太菜了,试了半天没有试出这两个的函数的区别。通过构造闭合都成功了执行了phpinfo()
还行吧。
php
还支持一种非常酷炫的函数调用方式
注意到这边是没用;
,但是在eval
中,如果没有封号语句是不执行,这也就是assert
的语法规范并不明显。在平时写一句话木马中,常用的应该是assert
,原因是多数系统会选择禁用掉eval
函数。而assert
常常用来作为判断一个表达式是否存在时有很大的便利。
preg_replace修正符的命令执行
preg_replace
函数主要用来执行正则表达式的搜索和替换,如php手册
介绍如下。
preg_replace
(PHP 4, PHP 5, PHP 7)
preg_replace — 执行一个正则表达式的搜索和替换
说明
mixed preg_replace ( mixed
$pattern
, mixed$replacement
, mixed$subject
[, int$limit
= -1 [, int&$count
]] )搜索
subject
中匹配pattern
的部分, 以replacement
进行替换。
第一个参数$pattern
:搜索的模式,可以是一个字符串或者字符串数组,可以加\e
修正符。
第二个参数$replacement
:要替换的字符。
第三个参数$subject
:需要被处理的字符串。
问题出在第一个参数的\e
修正符上。当加上了\e
修正符号时,$replacement
会被当做php代码片段执行。这个环境需要在php5.4
下。php7.0
完全放弃了该函数,php5.5的后续版本
会爆出提示,要求preg_replace_callback()
来代替该函数。
create_function()
这个函数可以方便的创建一个简单的函数。但是再参数可控的情况下,可能出现执行任意代码的漏洞。之前博客也写过这个相关的了,贴上链接,这里就不赘述。
https://zhhhy.github.io/2018/10/14/RCE/
array_map
先看看php手册
上的定义和用法
定义和用法
array_map() 函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。
回调函数接受的参数数目应该和传递给 array_map() 函数的数组数目一致。
语法
1
2 > array_map(myfunction,array1,array2,array3...
>
很明显吧。可以很简单粗暴的理解成调用一个函数,函数的参数是数组里的值。并且,函数的参数个数要和数组中元素数量相等。
call_user_func()/call_user_func_array()
这两个函数的基本原理和array_map
基本一致,都是调用assert
函数,再传参。导致的任意代码执行。例子就参考array_map()
的吧。
总结一下
除去几个原本就能执行系统命令函数,剩下的其实就是通过各种方式去调用这些函数。在系统命令禁用了这些函数的时候,就需要想各种办法绕过了。绕过方式千奇百怪,真的是一个考验脑洞的事情。不过万变不离其宗,防御手段只要将本质问题给修补了,也就无法绕过了。