ThinkPHP3.2.3 SQL injection analysis
ThinkPHP3.2.3 SQL injection analysis
S0cke3t漏洞成因
该注入出现在后端对数组型参数处理不当,可绕过参数过滤设置。导致恶意sql语句执行
环境设置
数据库配置
在/application/home/conf/config.php中添加如下代码
1 | <?php |
参数值根据具体情况进行填写
随后在mysql中新建与配置名称相同的数据库,并新建user表在其中添加三个字段id,username,password.并设置id为自增主键,最后在表中插入一条数据。
项目设置
在/Application/Home/Controller/IndexController.class.php文件index()函数中添加如下代码
1 | $id = I('id'); |
在浏览器中访问http://localhost/index.php?m=Home&c=Index&a=index&id=1
,如果出现
则证明设置正常
漏洞分析
将网上公开的poc带入到url中,进行断点调试。poc如下
1 |
|
先来看I函数,首先进行参数来源的判断,默认自动判断为param随后通过$_SERVER['REQUEST_METHOD']
获取参数传递方式
随后调用C函数获取配置文件的DEFAULT_FILTER加载默认filter,然后调用array_map_recursive进行参数过滤
跟进array_map_recursive
依次取出data值,使用call_user_func对data值进行过滤。最后调用thinkphp底层过滤函数think_filter
跟进
可以看到整个过程未对我们的poc产生影响,那么问题应该出现在后续的操作中。继续往下走进入到find函数中
首先对$option也就是我们传入的参数值进行判断,如果为数字或者字符串则使用默认where条件,此处option为数组并不满足条件,继续往下走进行复合主键的查询,由于我们的user表中只有一个主键所以条件也不满足,随后进入到_parseOptions函数进行表达式解析,跟进
此处虽然使用了_parseType对参数进行类型强转,但是根据我们传入的参数列表option[where]
并不满足字段类型检测条件,所以就成功的进行了绕过
继续往下走,在分析完表达式后调用db->select()
跟进
继续调用buildselectsql进行sql语句的解析
继续调用parseSql
此函数负责将%xxxx%的表达式替换为sql语句,其中在进行表达式替换时直接使用的前端传入的option[‘where’],随后在parseWhere中也未进行合法性校验,直接使用了传入的字符串where条件
随后将sql语句带入到db->driver->query()中进行查询
调用堆栈如下