Thinkphp 3.2.3 parseWhere设计缺陷导致update/delete注入 分析

Posted litlife

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Thinkphp 3.2.3 parseWhere设计缺陷导致update/delete注入 分析相关的知识,希望对你有一定的参考价值。

目录

分析

首先看一下控制器,功能是根据用户传来的id,修改对应用户的密码。

技术图片

13行把用户传来的id参数送入where()作为SQL语句中的WHERE语句,将pwd参数送入save()作为UPDATE语句。
这里我们假设请求id参数为array("bind","aaa"),pwd参数为bbb。

其中11行12行的意思是获取id、pwd参数,并通过I函数进行过滤。我们跟进一下I()

技术图片

技术图片

技术图片

可以看到,这里首先对参数进行htmlspecialchars过滤,然后在最后调用think_filter()函数进行过滤,跟进一下这个函数

技术图片

可以看到,这里通过匹配参数中的一些关键字,并在其后加上空格。
到这里I函数就结束了。

回到控制器继续往下走,首先进入where()

技术图片

技术图片

可以看到由于$where是数组、$parser是null,所以三个if都不满足,直接到1813行,接下来就是将$this->options[‘where‘]与$where拼接到一起,用于最终拼凑成一条完整的SQL语句。

继续跟进就到save函数了。

技术图片

由于$data非空,到409行。这里主要对比$data与数据库中的表中的各个字段的数据类型是否一致,如果不一致则会进行一些强制转换或是直接报错【TODO】。
然后到416行调用了_parseOptions(),这里用于解析出表名、where中的字段名等【TODO】。

下面直接跳到最后,调用update函数准备执行SQL语句

技术图片

跟进update,直接进入899行

技术图片

跟进parseWhere

其中在536行调用了parseWhereItem,跟进

技术图片

可以看到,这里直接拼接了$key和$val[1]到$whereStr中

技术图片

最后可以看到,$whereStr="`id` = :aaa",其中aaa就是我们一开始传入的id=array(‘bind‘, ‘aaa‘)数组中的第二项。由于后来直接被拼接到SQL语句中,因此这个里存在注入。

技术图片

http://127.0.0.1/thinkphp/thinkphp_3.2.3_full/index.php/home/index/sqli1?id[0]=bind&id[1]=0%20and%20(updatexml(1,concat(0x7e,user(),0x7e),1))&pwd=bbb

总结

本质原因是框架处理pdo时,将用户可控的字符串作为了占位符,导致sql注入在预处理之前就已经形成了,而所谓的过滤bind只是治标不治本而已(没做过开发,也有可能这本来就是一种写法?)。也有可能就是本来入口也就不多吧【TODO】。

哎,好菜。
01点46分

以上是关于Thinkphp 3.2.3 parseWhere设计缺陷导致update/delete注入 分析的主要内容,如果未能解决你的问题,请参考以下文章

thinkphp 杂项(3.2.3)

ThinkPHP 3.2.3 Widget 扩展的使用

ThinkPHP 3.2.3 数据缓存与静态缓存

ThinkPHP 3.2.3 视图模型的使用

ThinkPHP 3.2.3 URL 路由的使用

ThinkPHP 3.2.3 关联模型的使用