thinkphp3.2.5的一个伪0day
文章首发于先知社区:https://xz.aliyun.com/t/14575
前言
话还要从一次渗透测试任务说起,根据目标指纹在github上找到了某套基于thinkphp3的代码,登录口的代码大概长这样子:
1 |
|
可以看到这里直接将POST数组传入了where(
函数,这种操作是不是很眼熟呀?Laraval有过这种问题,貌似CI还是YII也有过(不记得了)
分析代码
忽略可能导致的业务逻辑漏洞,这里极有可能存在sql注入问题,直接使用tp3.2.5的代码做为演示,跟入代码到ThinkPHP/Library/Think/Model.class.php
这里将传入的$_POST
数组最终存放到了$this->options['where']
就结束了,返回Model类
之后会进入到增删该查的sql语句构建代码中,示例代码用的是find(
,跟入代码:
上图红框的位置判断了find(
数组参数的键,也就是对之前sqli注入的修复
蓝色箭头是对$this->options['where']
(这里也就是$_POST
数组),根据数据表中的的字段类型进行相应的强制转化
这里值得注意的是,只针对数据表里有的字段进行类型转化,如果传入xxx=123
之类的并不会被删除过滤,但后面会怎么处理呢?
回到蓝色箭头后面红色箭头处的函数select(
,一直跟入src/ThinkPHP/Library/Think/Db/Driver.class.php
1 | Think\Db\Driver->select |
最终来到Think\Db\Driver->parseWhere(
传入的部分$_POST
数组现在是$where
,可以看到箭头处中对以_
为前缀的键有特殊处理,跟进parseThinkWhere(
方法
这里声明了三种键值的不同处理方式,最终成为sql的where语句,这三种方式均可被利用,这里展示利用_string
和_complex
进行sql注入
剩下_query
有兴趣的师傅可尝试利用
1 | _query=updatexml(0,concat(0x7e,user()),0)=1 |
参考
https://www.leavesongs.com/PENETRATION/cachet-from-laravel-sqli-to-bug-bounty.html