0x01原因
原因是我们下午遇到了preg_replace函数,我们都知道preg_replace函数可能会导致命令执行。现在让我们来看一些情况。
0x02经过
踩坑1:
测试代码如下所示:
foreach($ _ GET as $ regex=$ value){ preg _ replace('/(')。$regex。)/ei ',' strtolow(' 1 ')',$ value);}在测试过程中,发现特殊字符如。当数据通过浏览器传入时,将被转换为。
这涉及到php的一个特性
当php本身解析请求时,如果参数名包含空格等字符。[,等。它们将被转换为_。
?php $ a=$ _ GETvar _ dump($ a);
经过我的模糊,结果如下:
胎面凹坑2:
然后我们知道preg_replace的/e修饰符会将替换参数视为php代码,并将其作为eval函数执行,前提是主题中存在模式匹配。在这种情况下,让我们看一张图片。
在图中,strtolower函数实际上是通过eval执行的。实际实现是:
strtolow(' JUST TEST ');strtolow(' PHPINFO()');strtolow(' { $ { PHPINFO()} } ');代码可以执行的第三个原因是我们使用复杂的(大括号)语法来执行它的代码。
踩坑3:
回到源代码,让我们明白:
foreach($ _ GET as $ regex=$ value){ preg _ replace('/(')。$regex。)/ei ',' strtolow(' 1 ')',$ value);}这里的替换是strtolow(" \1 "),所以请理解 1。
每个这样的引用将被匹配的第n个捕获子组捕获的文本替换。n可以是0-99, 和$0表示完整的模式匹配文本。
假设一个正则表达式如下所示:
preg_replace('/(。*)(?|)' .$key。'=[^] ?()(.*)/i ',' 1$2$4 ',$url。'');这里,$1$2$4相当于上面的124,我们来看看如何选择匹配。
$1 $2 $3 $4'/(.*)(?|)' .$key。'=[^] ?() (.*)/i'0x03解决方案
好了,上面的坑都铺好了,就从这里开始解决吧。
foreach($ _ GET as $ regex=$ value){ preg _ replace('/(')。$regex。)/ei ',' strtolow(' 1 ')',$ value);}我们需要满足这部分代码的几个条件才能达到代码执行的效果:
模式部分的表达式需要在$value 1中命中从数据中取出的数据的复杂(大括号)语法,以确保双引号下的代码执行效果。由于php的特性,url将转换特殊字符,如。 [,_.我们知道$regex和$value是通过get获得的。如果要截取替换部分中通过模式正则匹配1命中的$value中的数据,并携带 $、{、(这里涉及正则表达式的使用。
这里我选择了S,也就是匹配任何非空白字符,所以最终的有效载荷看起来像这样
S *()={ $ { phpinfo()} }
0x04后记
其实还是有一些小问题。我没有在这里写它们,但是您可以看看这个,深入研究preg_replace和代码执行。
摘要
以上就是本文的全部内容。希望本文的内容对大家的学习或工作有一定的参考价值。有问题可以留言交流。谢谢你的支持。