文章目录
  1. 1. 反思
  2. 2. 参考资料

漏洞很老了。整理一下。补丁地址

代码修复的方式为:

/trunk/ThinkPHP/Lib/Core/Dispatcher.class.php 
125  -   $res = preg_replace('@(w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2";', implode($depr,$paths)); 
125  +   $res = preg_replace('@(w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']=\'\\2\';', implode($depr,$paths)); 

这里导致代码执行的原因有两个,一是preg_replace使用了e修饰符,这样$var[\'\\1\']="\\2"; 会被当做php代码执行。而双引号的变量会被解析,导致了代码执行。

关键代码为:

$depr = C('URL_PATHINFO_DEPR');
        // 分析PATHINFO信息
        self::getPathInfo();
        if(!self::routerCheck()){   // 检测路由规则 如果没有则按默认规则调度URL
            $paths = explode($depr,trim($_SERVER['PATH_INFO'],'/'));
            $var  =  array();
            if (C('APP_GROUP_LIST') && !isset($_GET[C('VAR_GROUP')])){
                $var[C('VAR_GROUP')] = in_array(strtolower($paths[0]),explode(',',strtolower(C('APP_GROUP_LIST'))))? array_shift($paths) : '';
                if(C('APP_GROUP_DENY') && in_array(strtolower($var[C('VAR_GROUP')]),explode(',',strtolower(C('APP_GROUP_DENY'))))) {
                    // 禁止直接访问分组
                    exit;
                }
            }
            if(!isset($_GET[C('VAR_MODULE')])) {// 还没有定义模块名称
                $var[C('VAR_MODULE')]  =   array_shift($paths);
            }
            $var[C('VAR_ACTION')]  =   array_shift($paths);
            // 解析剩余的URL参数
            $res = preg_replace('@(\w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']=strip_tags(\'\\2\');', implode($depr,$paths));
            $_GET   =  array_merge($var,$_GET);
        }

反思

深入理解漏洞原型,理清复杂逻辑

参考资料

Thinkphp 3.0-3.1版代码执行

文章目录
  1. 1. 反思
  2. 2. 参考资料