ThinkPHP一处XSS漏洞(需要特定环境触发)

时间:2015-1-6    作者:admin    分类: 技术交流


代码出现在I方法中

关于I的方法,我就不多介绍了,具体可以参考官方手册,下面贴出部分关键代码

文件位置:/ThinkPHP/Common/functions.php

function I($name,$default='',$filter=null,$datas=null) {

    if(strpos($name,'.')) { // 指定参数来源

        list($method,$name) =   explode('.',$name,2);

    }else{ // 默认为自动判断

        $method =   'param';

    }

    switch(strtolower($method)) {

        case 'get'     :   $input =& $_GET;break;

        case 'post'    :   $input =& $_POST;break;

        case 'put'     :   parse_str(file_get_contents('php://input'), $input);break;

        case 'param'   :

            switch($_SERVER['REQUEST_METHOD']) {

                case 'POST':

                    $input  =  $_POST;

                    break;

                case 'PUT':

                    parse_str(file_get_contents('php://input'), $input);

                    break;

                default:

                    $input  =  $_GET;

            }

            break;

        case 'path'    :   

            $input  =   array();

            if(!empty($_SERVER['PATH_INFO'])){

                $depr   =   C('URL_PATHINFO_DEPR');

                $input  =   explode($depr,trim($_SERVER['PATH_INFO'],$depr));            

            }

            break;

        case 'request' :   $input =& $_REQUEST;   break;

        case 'session' :   $input =& $_SESSION;   break;

        case 'cookie'  :   $input =& $_COOKIE;    break;

        case 'server'  :   $input =& $_SERVER;    break;

        case 'globals' :   $input =& $GLOBALS;    break;

        case 'data'    :   $input =& $datas;      break;

        default:

            return NULL;

    }

    if(''==$name) { // 获取全部变量

        $data       =   $input;

        array_walk_recursive($data,'filter_exp');

        $filters    =   isset($filter)?$filter:C('DEFAULT_FILTER');  //默认会用htmlspecialchars过滤

        if($filters) {

            if(is_string($filters)){

                $filters    =   explode(',',$filters);

            }

            foreach($filters as $filter){

                $data   =   array_map_recursive($filter,$data); // 参数过滤

            }

        }

    }elseif(isset($input[$name])) { // 取值操作

        $data       =   $input[$name];

        is_array($data) && array_walk_recursive($data,'filter_exp');

        $filters    =   isset($filter)?$filter:C('DEFAULT_FILTER');

        if($filters) {

            if(is_string($filters)){

                $filters    =   explode(',',$filters);

            }elseif(is_int($filters)){

                $filters    =   array($filters);

            }

            foreach($filters as $filter){

                if(function_exists($filter)) {

                    //进入这里如果是数组会有TP自己的回调函数对数据进行处理,如果不是会直接用htmlspecialchars过滤

                    $data   =   is_array($data)?array_map_recursive($filter,$data):$filter($data); // 参数过滤

                }else{

                    $data   =   filter_var($data,is_int($filter)?$filter:filter_id($filter));

                    if(false === $data) {

                        return   isset($default)?$default:NULL;

                    }

                }

            }

        }

    }else{ // 变量默认值

        $data       =    isset($default)?$default:NULL;

    }

    return $data;

}



关键就看对数据处理的这句

//这里如果是数组会有TP自己的函数对数据进行处理,如果不是会直接用htmlspecialchars过滤

$data=is_array($data)?array_map_recursive($filter,$data):$filter($data);

代码跟进看下array_map_recursiv这个函数是怎么对数据进行处理的

function array_map_recursive($filter, $data) {

     $result = array();

     foreach ($data as $key => $val) {

         $result[$key] = is_array($val)

             ? array_map_recursive($filter, $val)

             : call_user_func($filter, $val);

     }

     return $result;

 }



以上的代码作用是递归过滤数组的值,并没有对索引进行处理,到这里应该明白了吧,所以只要是I方法获取的post、get、cookie...等,只要是数组,都可以造成XSS,特定的环境甚至触发sql注入


cookie测试

cookie.png





post测试

post.png


post2.jpg



其他的就不测试了,同一个函数封装的,肯定都存在问题

标签: xss ThinkPHP