• 技术文章 >后端开发 >php教程

    对于ThinkPHP框架早期版本的一个SQL注入漏洞详细分析_PHP

    2016-06-01 11:52:08原创394
    ThinkPHP

    ThinkPHP官网上曾有一段公告指出,在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;
    }
    

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

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    上一篇:PHP中的插件机制原理和实例_PHP 下一篇:PHP的error_reporting错误级别变量对照表_PHP
    20期PHP线上班

    相关文章推荐

    • 【活动】充值PHP中文网VIP即送云服务器• 同时安装sql2000和sql2005,经验点滴_PHP教程• [原创]ajax 实现用户注册功能教程一_PHP教程• 实例解说PHP动态内容的缓冲和压缩_PHP教程• 经验分享:PHP编程的5个良好习惯(一)(1)_PHP教程• 正则表达式系统教程(一)_PHP教程
    1/1

    PHP中文网