前言
漏洞复现
搭建好数据库,以我自己的配置为例。数据库为tptest,表名为user,其中有两个字段id和username
thinkphp官网下载5.0.15版本: http://www.thinkphp.cn/down/1125.html 。修改数据库配置信息 application/database.php。在 application/config.php 中打开调试和trace,app_debug
和app_trace
均为true。在 application/index/controller/Index.php 中Index类中添加方法:
访问:
漏洞分析
通过input获取到参数后,username
变量情况如下:
跟入insert,thinkphp/library/think/db/Query.php:2078
接下去执行:
跟入 thinkphp/library/think/db/Builder.php:720:
跟入parseData
至 thinkphp/library/think/db/Builder.php:101 ,相关变量信息已经注释添加。
|
|
可以看出$val
是数组,且根据$val[0]
值为inc
,会通过switch语句进入到下面这条:
跟入此处的parseKey
,即thinkphp/library/think/db/builder/Mysql.php:90
此处并未对传入的$key
进行更多的过滤与检查,最后返回的仍然是1 and (updatexml(1,concat(0x7,user(),0x7e),1))
回到parseData
,floatval($val[2])
返回1,这也正是我们要传入username[2]=1
的原因。将其与前面经过parseKey
的结果进行拼接后返回给result
回到 thinkphp/library/think/db/Query.ph 的 insert 中:
漏洞修复
官方commit: https://github.com/top-think/framework/commit/363fd4d90312f2cfa427535b7ea01a097ca8db1b
在进行dec
和inc
操作之前对$val[1]
的值进行了再次确认。