看到信安之路发了一篇关于某 CMS 的审计,之前对这个 CMS 也算是有一点了解吧,看到里面的一处 RCE 提起了我一点兴趣,于是有了下文。
受限的代码执行
如下,一处刺眼的 eval 代码。
这个利用点在信安之路上一篇文章已经有分析到了,所以不做过多流程上的分析,只关注如何 Bypass,完成 RCE。问题的关键是要绕过 danger_key 的处理,具体的代码如下
比较棘手的是 $type 值写死传入为 1,所以单双引号都会被实体编码,这导致就算我们传入的函数也难以传入一个字符串作为函数参数。再看下面被过滤的函数,虽然过滤了很多常用的函数,但只要是参数类型为 callback 的函数都可以作为绕过的方法。所以最先需要解决的是如何突破单双引号的限制,完成字符串的传入。
寻找输入可控的地方
问题一:输入点有哪些?
一开始总是受于思维的限制,老是认为输入点就是 GPC,可真的是这样吗?并非如此,HTTP 传输的数据不只是 GPC,而是整个协议的格式,如下图,除了 GPC 之外,HTTP 头部都是我们可控的。而且这里并不会被过滤函数处理,是理想的控制输入的地方。
![从受限的代码执行到任意代码执行 从受限的代码执行到任意代码执行]()
问题二:那控制了输入,那如何把控制的输入获取到并传入我们想要执行的函数里呢?
我已经可以通过上面受限的代码执行来执行一些函数,于是我的思路是寻找一个函数可以返回头部信息,而这个函数的要求是不需要参数。可往往不需要参数的函数返回大多是个数组,不过这没关系,在 PHP5.4 版本就新增支持对函数返回数组的成员访问解析的特性,例如 foo()[0]
。翻了翻手册发现了一个函数满足我的要求。
但我忽略的一个点,get 被替换成 * 所以会导致执行不成功。
![从受限的代码执行到任意代码执行 从受限的代码执行到任意代码执行]()
这个好解决手册的下一句就是
此函数是 apache_request_headers() 的别名。请阅读 apache_request_headers() 文档获得更多信息。
所以直接使用 apache_request_headers() 的效果是一样的。
问题三:apache_request_headers 返回的数组下标为字符串,而 POST 不可以输入字符串怎么办?
学习一门语言或多或少都会学习数组的切割操作,所以 array_slice 可以切割获得任意一个元素的值。
到此,我们可以控制输入,同时绕过了过滤,并且把输入作为参数带入到想要执行的函数里。我选了 array_filter 函数来执行任意代码。
最后的效果就是如下:
![从受限的代码执行到任意代码执行 从受限的代码执行到任意代码执行]()
最后
还是蛮有意思的一个绕过,加深理解了一切输入皆有害!花了一两个小时绕这个,还是蛮有趣的。文章没写太细,更多细节就留给各位调试啦。
![从受限的代码执行到任意代码执行 从受限的代码执行到任意代码执行]()
本文始发于微信公众号(信安之路):从受限的代码执行到任意代码执行
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论