thinkphp3.2漏洞updatexml攻击

lys2018年04月28日 0条评论

thinkphp3.2漏洞,updatexml攻击


http://localhost/thinkphp_lang/?id[0]=bind&id[1]=0 and updatexml(1,concat(0x7,user(),0x7e),1)

控制器中的代码是这样写

class IndexController extends Controller {
    public function index(){

       $content = I('content',123);
       $id = I('id');
       var_dump($id);
       $zhi = M('json_test')->where(['id'=>$id])->save(['content'=>$content]);
       var_dump($zhi);
    }
}

如下报错:

image.png

修复方法:

   image.png

重点是$this->parseSet这个方法的

原先是

/**
 * set分析
 * @access protected
 * @param array $data
 * @return string
 */
protected function parseSet($data) {
    foreach ($data as $key=>$val){
        if(is_array($val) && 'exp' == $val[0]){
            $set[]  =   $this->parseKey($key).'='.$val[1];
        }elseif(is_null($val)){
            $set[]  =   $this->parseKey($key).'=NULL';
        }elseif(is_scalar($val)) {// 过滤非标量数据
            if(0===strpos($val,':') && in_array($val,array_keys($this->bind)) ){
                $set[]  =   $this->parseKey($key).'='.$this->escapeString($val);
            }else{
                $name   =   count($this->bind);
                $set[]  =   $this->parseKey($key).'=:'.$name;
                $this->bindParam($name,$val);
            }
        }
    }
    return ' SET '.implode(',',$set);
}

将其改为

/**
     * set分析
     * @access protected
     * @param array $data
     * @return string
     */
    protected function parseSet($data) {
        foreach ($data as $key => $val) {
            if (isset($val[0]) && 'exp' == $val[0]) {
                $set[] = $this->parseKey($key) . '=' . $val[1];
            } elseif (is_null($val)) {
                $set[] = $this->parseKey($key) . '=NULL';
            } elseif (is_scalar($val)) {
                // 过滤非标量数据
                if (0 === strpos($val, ':') && in_array($val, array_keys($this->bind))) {
                    $set[] = $this->parseKey($key) . '=' . $val;
                } else {
                    $name  = count($this->bind);
                    $set[] = $this->parseKey($key) . '=:' . $key . '_' . $name;
                    $this->bindParam($key . '_' . $name, $val);
                }
            }
        }
        return ' SET ' . implode(',', $set);
    }

还要改的地方如下的

找到ThinkPHP/Library/Think/Db/Driver/Mysql.class.php文件

搜索

function parseKey

/**
 * 字段和表名处理
 * @access protected
 * @param string $key
 * @return string
 */
protected function parseKey(&$key) {
    $key   =  trim($key);
    if(!is_numeric($key) && !preg_match('/[,\'\"\*\(\)`.\s]/',$key)) {
       $key = '`'.$key.'`';
    }
    return $key;
}

改为

/**
 * 字段和表名处理
 * @access protected
 * @param string $key
 * @return string
 */
protected function parseKey($key)
{
    $key = trim($key);
    if (!is_numeric($key) && !preg_match('/[,\'\"\*\(\)`.\s]/', $key)) {
        $key = '`' . $key . '`';
    }
    return $key;
}

这样其实还是会暴露漏洞

http://localhost/thinkphp_lang/?id[0]=bind&id[1]=content_0 and updatexml(1,concat(0x7,(select authentication_string from mysql.user where User='mysql.sys' limit 1),0x7e),1)

这样依然报错异常信息

解决方法:

修改框架内核 ThinkPHP/Conf/debug.php文件中

将DB_DEBUG设置为false

这样才能避免错误暴露mysql错误