ThinkPHP SQL注入漏洞(CVE-2021-44350)分析

师傅们情人节快乐~来一起分析个洞八

0x01漏洞描述

顶想信息科技 ThinkPHP是中国顶想信息科技公司的一套基于PHP的、开源的、轻量级Web应用程序开发框架。

ThinkPHP 5.0.x <=5.1.22 存在SQL注入漏洞,该漏洞源于通过Builder.php中的parseOrder函数。

0x02影响版本

ThinkPHP 5.0.x <=5.1.22

0x03环境搭建

Test on ThinkPHP-5.0.5,其完整版的源码:http://www.thinkphp.cn/donate/download/id/870.html

PHPstorm + Xdebug配置

具体配置过程不做详细说明,最后效果大概如下:

phpinfo页面中

数据库配置

在框架源码中的database.php数据库配置文件中添加相关的数据库信息,这里以连接mysql默认已有的数据库为例

tp5源码配置

由于是tp5框架问题,所以可以在Index.php访问页面中修改成以下代码

0x04漏洞分析

Index.php文件中断点逐步跟进即可~
访问页面在url传入以下参数及值

?test[user^updatexml(1,concat(0x7,user(),0x7e),1)%23]=1

先看到input()中对接收http请求服务在Request.php进行了简单的判断和处理,并且从中可得到我们所构造的恶意键值对

接着返回到Index.php文件的第二个断点,helper.php中的db()函数对数据库进行connect连接操作,接着到Query.php文件的where()函数,这边也是没有任何的问题

紧接着来到order()函数中,可以看到我们的$field数据内容是直接存储到了$this->options['order']当中

接着调用最后的find()函数以在数据库做sql语句的执行,先是利用parseExpress()函数提取sql语句中的关键字等操作

接着Query.php中的$sql = $this->builder->select($options);会调用Builder.php中的Select()函数生成Sql语句,关键在于该方法中对$options中的order键值对做了parseOrder()函数的过滤

public function select($options = [])
{
$sql = str_replace(
['%TABLE%', '%DISTINCT%', '%FIELD%', '%JOIN%', '%WHERE%', '%GROUP%', '%HAVING%', '%ORDER%', '%LIMIT%', '%UNION%', '%LOCK%', '%COMMENT%', '%FORCE%'],
[
$this->parseTable($options['table'], $options),
$this->parseDistinct($options['distinct']),
$this->parseField($options['field'], $options),
$this->parseJoin($options['join'], $options),
$this->parseWhere($options['where'], $options),
$this->parseGroup($options['group']),
$this->parseHaving($options['having']),
$this->parseOrder($options['order'], $options),
$this->parseLimit($options['limit']),
$this->parseUnion($options['union']),
$this->parseLock($options['lock']),
$this->parseComment($options['comment']),
$this->parseForce($options['force']),
], $this->selectSql);
return $sql;
}

parseOrder()函数中,将$key$options参数传入parseKey()函数过滤$key

parseKey()函数中未对key中做任何消除敏感字符的过滤、检测,即照常返回原来的key值

所以在parseOrder()函数中将直接返回以下内容

将得到最终所要执行的sql语句

在事件回调代码块中对以上得到的sql语句,来到Connection.php中的query()函数进行sql语句的查询

$result = $this->query($sql, $bind, $options['master'], $options['fetch_pdo']);

最后在此处触发了错误的sql注入

在此处将返回我们成功注入sql的报错信息

调用链如下:

helper#db --> 连接数据库
Query#where --> 匹配where关键字
Query#order --> 匹配order关键字
Query#find,Builer#select --> 生成sql查询语句
Builer#parseOrder --> 过滤$options中的order键值对
Mysql#parseKey --> 过滤order中的key值
Query#query,Connection#Query --> 执行sql语句
PDOException#getLastsql --> 返回报错信息

0x05总结一下

(仅个人理解)就是在键值对中的构造恶意sql语句到key即键中,接着在生成sql查询语句过程中未对order(包括其他关键字)中的key做敏感字符串的过滤,导致将key值内容拼接进sql语句中,达到sql注入的目的

  • 发表于 2022-03-15 09:22:25
  • 阅读 ( 9215 )
  • 分类:漏洞分析

0 条评论

请先 登录 后评论
w1nk1
w1nk1

12 篇文章

站长统计