记一次ThinkPHP源码审计

一、写在前面

周末闲得蛋疼,审了一套朋友给的系统,过程挺有意思的,开始的时候觉得基于TP3.0二次开发的系统应该是蛮简单的,毕竟TP爆了很多漏洞。后来发现开发做了不少安全措施。因此记录一下这次审计,当时自己学习的记录吧。

二、后台注入

最开始的时候,因为快吃饭了,就用RIPS扫了扫(事实证明,没有什么毛用)。说是扫到了一个对象注入,然后就看了看代码,大致如下:

讲真,这里一眼就能看出来是有个注入的,最简单的方式就是$_REQUEST['_where']经过base64_decode()->unserialize()是字符串,直接就可以注入了。
但是这里到底有没有对象注入呢?我的理解是反序列化导致的对象注入,至少得有对应的魔术方法__wakeup或者__destruct,并且在魔术方法中有敏感的操作。不仅如此,有时候可能还需要构造POP链,具体参照:这篇文章
因此,我搜索了一下对应的两个魔术方法,全文都没有定义,基本上是无解了。
因为后台的漏洞一般都是比较鸡肋的,因此放弃后台漏洞的挖掘,转而移步前台。

二、前台注入

低版本的TP在这里一定是有漏洞的,至于为什么可以看这篇文章。然后,我们就可以构造userid[0]=exp&userid[1]=xxxx'or 1=1#之类的语句了,事实上这套系统被修改过了,尝试的过程中发现被一个叫checkPost的函数过滤了,如下所示:

也就是说,ThinkPHP中的exp等那一波漏洞都不能用了。这就很尴尬了,而且前台可以输入的地方真的不多。
没办法,挨着看有点受不了,就开始搜索$_GET$_POST以及$_REQUEST之类的全局变量,其实除了这三种方法获取输入,系统还使用了I方法(我特么真的是服了,I方法是TP-3.1.3之后才添加的,这里系统显示的是TP-3.0)。
果不其然,发现了唯一一处字符串拼接的地方

问题到这里就解决了,其实它还用到了I方法获取输入,参考这里。我看了看,这个完全是TP-3.2的东西啊,最开始应该早就走了弯路。好吧,没有发现字符串拼接的地方。

三、逻辑漏洞

朋友告诉我,这套系统注册的功能关闭了,虽然是前台注入,还是很鸡肋啊。掩面哭泣啊,这种MVC的框架,一般验证登录状态都在父类中做好了。
无奈,看了很久登录验证的问题,没有绕过去。也就是说,没有登录无法绕过又没有账号是没法注入的。似乎到现在已经陷入了僵局,此时我看了看网站目录,我发现网站还有个应用Install
如果能够重装也是极好的,因此看了看代码

下面是控制器的代码

只要我们传递step=done就可以绕过构造器了。接着看敏感函数,发现了一个比较有意思的函数create_admin,通常在安装程序的时候会有创建管理员这一步,这里居然属性设置为了public,二话不说,添加一个管理员账号。

四、命令执行

现在已经拥有后台权限、并且后台可以添加前台用户来进行SQL注入。因此现在更加关注的写文件、代码执行、命令执行等等。所以就搜索了一下关键函数,发现一处比较关键的。

看了下关键函数adminshow,其实就是查看配置文件而已。它检查ADMIN_SHOW这个字段中是否含有cliSwitch的值,我看了看,默认是没有的;如果有,就会造成字符串拼接导致命令执行漏洞。

接下来搜索ADMIN_SHOW,查看是否有设置这个配置文件的地方,果然有。

在这个控制器下面,就可以设置ADMIN_SHOW这个键的配置参数了。

五、全局过滤

我发现,在执行命令的时候发现有些参数被过滤了。它配置了DEFAULT_FILTERhtmlspecialchars默认过滤了一些字符。因此,在命令拼接的时候可以使用|或者||,在写文件的时候可以使用wget或者bitsadmin之类的命令

此条目发表在代码审计分类目录,贴了, , 标签。将固定链接加入收藏夹。

1 则回应给 记一次ThinkPHP源码审计

  1. Pingback引用通告: SecWiki周刊(第171期) |

发表评论

电子邮件地址不会被公开。 必填项已用*标注