黑帽联盟

 找回密码
 会员注册
查看: 1278|回复: 0
打印 上一主题 下一主题

[系统安全] ThinkPHP框架通杀所有版本的一个SQL注入漏洞详细分析及测试方法

[复制链接]
yun 黑帽联盟官方人员 

920

主题

37

听众

1364

积分

超级版主

Rank: 8Rank: 8

  • TA的每日心情
    奋斗
    2019-10-18 11:20
  • 签到天数: 678 天

    [LV.9]以坛为家II

    下面是摘自thinkphp官方的一个公告,官方直接贴出这些东西是非常不负责的行为,跟上次apache公开的Struts2的代码执行一样的行为,会造成很多用户被黑。建议类似的厂商不要再做这种蠢事。


    ThinkPHP 3.1.3及之前的版本存在一个SQL注入漏洞,漏洞存在于ThinkPHP/Lib/Core/Model.class.php 文件
    根据官方文档对”防止SQL注入”的方法解释(见http://doc.thinkphp.cn/manual/sql_injection.html)

    使用查询条件预处理可以防止SQL注入,没错,当使用如下代码时可以起到效果:
    $Model->where("id=%d and username='%s' and xx='%f'",array($id,$username,$xx))->select();


    或者

    $Model->where("id=%d and username='%s' and xx='%f'",$id,$username,$xx)->select();


    但是,当你使用如下代码时,却没有”防止SQL注入”效果(而官方文档却说可以防止SQL注入):
    $model->query('select * from user where id=%d and status=%s',$id,$status);


    或者

    $model->query('select * from user where id=%d and status=%s',array($id,$status));


    原因:
    ThinkPHP/Lib/Core/Model.class.php 文件里的parseSql函数没有实现SQL过滤.

    原函数:
    protected function parseSql($sql,$parse) {
    // 分析表达式
    if(true === $parse) {
    $options = $this->_parseOptions();
    $sql = $this->db->parseSql($sql,$options);
    }elseif(is_array($parse)){ // SQL预处理
    $sql = vsprintf($sql,$parse);
    }else{
    $sql = strtr($sql,array('__TABLE__'=>$this->getTableName(),'__PREFIX__'=>C('DB_PREFIX')));
    }
    $this->db->setModel($this->name);
    return $sql;
    }


    验证漏洞(举例):
    请求地址:
    http://localhost/Main?id=boo” or 1=”1

    http://localhost/Main?id=boo%22%20or%201=%221

    action代码:
    $model=M('Peipeidui');
    $m=$model->query('select * from peipeidui where name="%s"',$_GET['id']);
    dump($m);exit;
    或者
    $model=M('Peipeidui');
    $m=$model->query('select * from peipeidui where name="%s"',array($_GET['id']));
    dump($m);exit;

    结果:
    表peipeidui所有数据被列出,SQL注入语句起效.

    解决办法:
    将parseSql函数修改为:
    protected function parseSql($sql,$parse) {
    // 分析表达式
    if(true === $parse) {
    $options = $this->_parseOptions();
    $sql = $this->db->parseSql($sql,$options);
    }elseif(is_array($parse)){ // SQL预处理
    $parse = array_map(array($this->db,'escapeString'),$parse);//此行为新增代码
    $sql = vsprintf($sql,$parse);
    }else{
    $sql = strtr($sql,array('__TABLE__'=>$this->getTableName(),'__PREFIX__'=>C('DB_PREFIX')));
    }
    $this->db->setModel($this->name);
    return $sql;
    }


    总结:
    不要过分依赖TP的底层SQL过滤,程序员要做好安全检查
    不建议直接用$_GET,$_POST

    帖子永久地址: 

    黑帽联盟 - 论坛版权1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关
    2、本站所有主题由该帖子作者发表,该帖子作者与黑帽联盟享有帖子相关版权
    3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和黑帽联盟的同意
    4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
    5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
    6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
    7、黑帽联盟管理员和版主有权不事先通知发贴者而删除本文

    您需要登录后才可以回帖 登录 | 会员注册

    发布主题 !fastreply! 收藏帖子 返回列表 搜索
    回顶部