网站地图    收藏   

主页 > 入门引导 > 黑客攻防 >

ThinkPHP一处过滤不当造成SQL注入漏洞及解决方案 - 网站安全 - 自学php网

来源:未知    时间:2015-04-15 13:08 作者:xxadmin 阅读:

[导读] 问题出现在session,Thinkphp支持更换session handle。 handle中包括Db和Memcache,如下配置即可使用 数据库 作为session的存储器: 设置了选项后,在数据库里插入这个表(前缀think_可以自己定义...

问题出现在session,Thinkphp支持更换session handle。

QQ20150308-1@2x.png


handle中包括Db和Memcache,如下配置即可使用数据库作为session的存储器:

QQ20150308-2@2x.png


设置了选项后,在数据库里插入这个表(前缀think_可以自己定义):

/**
 * 数据库方式Session驱动
 *    CREATE TABLE think_session (
 *      session_id varchar(255) NOT NULL,
 *      session_expire int(11) NOT NULL,
 *      session_data blob,
 *      UNIQUE KEY `session_id` (`session_id`)
 *    );
 */



这都是官方给出的(包含在文档和代码注释中)一些配置方法,不多说了。

配置好了以后我写了个小example:

<?php
namespace Home\Controller;
use Think\Controller;
class AdminController extends Controller {
function __construct(){
Controller::__construct();
session(array('name'=>'session_id','expire'=>3600));
}

    public function index(){
    $admin = session("admin");
    if(!empty($admin)){
    $this->show("欢迎登录,{$admin}",'utf-8');
    }else{
    $this->show('你没有登录,请登录','utf-8');
    }
    }

    public function login(){
    session("admin", I('get.username'));
    $this->show('登录成功','utf-8');
    }
}



很普通一个过程,在login方法中登录,记录用户输入的用户名I('get.username')作为$_SESSION['admin'],在index方法中判断session中是否存在admin,不存在则要求其登录。

看到/ThinkPHP/Think/Session/Driver/Db.class.php 

/**
     * 写入Session 
     * @access public 
     * @param string $sessID 
     * @param String $sessData  
     */
   public function write($sessID,$sessData) { 
       $hander = is_array($this->hander)?$this->hander[0]:$this->hander;
       $expire = time() + $this->lifeTime; 
       mysql_query("REPLACE INTO  ".$this->sessionTable." (  session_id, session_expire, session_data)  VALUES( '$sessID', '$expire',  '$sessData')",$hander); 
       if(mysql_affected_rows($hander)) 
           return true; 
       return false; 
   }



实际上thinkphp将Db类中的open/close/read/write/destroy/gc用session_set_save_handler注册成为了session的handle。

write是设置session时的回调函数,其中$sessData就是当前session经过serialize的值。我们看到这里直接将$sessData拼接入SQL语句了,并没有转义。

所以造成了一个SQL注入。只要设置时session的值用户能够控制,比如用户名、昵称什么的,就能够产生SQL注入。

上述example脚本,访问http://10.211.55.3/thinkphp/index.php/home/admin/login?username=aaaaa%27aaaaaa
 

QQ20150308-3@2x.png



查看执行的SQL语句:
 

QQ20150308-4@2x.png



单引号已经带入了。

进行延时注入:

 

QQ20150308-5@2x.png


 

QQ20150308-6@2x.png





最后说一下,既然框架给开发者提供了自定义driver,那么这就作为框架的一部分进行维护,同样是不能草率的。不要因为不是默认使用的功能,就不去重视。

另外,内核部分的代码还使用SQL拼接这种方式去执行SQL语句,感觉不太合适。

解决方案:

且不论是否会产生sql注入,这里只要session的值中含有单引号,这个session就直接设置不了了,直接影响框架功能。所以需要在插入之前进行转义:

/**
     * 写入Session 
     * @access public 
     * @param string $sessID 
     * @param String $sessData  
     */
   public function write($sessID,$sessData) { 
       $hander = is_array($this->hander)?$this->hander[0]:$this->hander;
       $expire = time() + $this->lifeTime; 
       $sessData = addslashes($sessData);
       mysql_query("REPLACE INTO  ".$this->sessionTable." (  session_id, session_expire, session_data)  VALUES( '$sessID', '$expire',  '$sessData')",$hander); 
       if(mysql_affected_rows($hander)) 
           return true; 
       return false; 
   }

自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号-1@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com

添加评论