yichen115
BUUCTF 的第一题,上来就给搞懵了。。 。这要是我自己做出来的,岂不是相当于挖了一个 CVE ?(菜鸡这样安慰自己)
 
问题在 index.php 的 55~63 行
// If we have a valid target, let\'s load that script instead
if (! empty($_REQUEST[\'target\'])
    && is_string($_REQUEST[\'target\'])
    && ! preg_match(\'/^index/\', $_REQUEST[\'target\'])
    && ! in_array($_REQUEST[\'target\'], $target_blacklist)
    && Core::checkPageValidity($_REQUEST[\'target\'])
) {
    include $_REQUEST[\'target\'];
    exit;
}

 

 
对于传递的参数有 5 个条件,如果满足就 include 包含参数
1.不为空
2.是字符串
3.不以 index 开头
4.不能出现在:$target_blacklist 中
5.Core 类的 checkPageValidity 方法判断
 
前三个基本忽略,第四个发现
/index.php
//line 50-52
$target_blacklist = array (
    \'import.php\', \'export.php\'
);

 

也就是 target 不能是 import.php 和 export.php
 
 
最后是 Core 类 checkPageValidity 函数判断
//443-478
public static function checkPageValidity(&$page, array $whitelist = [])
{
    if (empty($whitelist)) {
        $whitelist = self::$goto_whitelist;
    }
    if (! isset($page) || !is_string($page)) {
        return false;
    }
    if (in_array($page, $whitelist)) {
        return true;
    }
    $_page = mb_substr(
        $page,
        0,
        mb_strpos($page . \'?\', \'?\')
    );
    if (in_array($_page, $whitelist)) {
        return true;
    }
    $_page = urldecode($page);
    
    $_page = mb_substr(
        $_page,
        0,
        mb_strpos($_page . \'?\', \'?\')
    );
    if (in_array($_page, $whitelist)) {
        return true;
    }
    return false;
}

 

函数里又是五个判断:
1.$whitelist 为空则引用静态声明:$goto_whitelist
2.如果 $page 没有被定义不是字符串则返回 false
3.如果 $page 存在 $whitepage 则返回 true
4.如果 $_page 存在 $whitelist 则返回 true($_page是取出$page问号前面的东西)
5.经过 url 解码后 $_Page 存在 $whitelist 中则返回 true
 
当 index.php 调用 checkPageValidity 时并没有传 $whitelist 的值,所以会进入 self::$goto_whitelist;
public static $goto_whitelist = array(
        \'db_datadict.php\',
        \'db_sql.php\',
        \'db_events.php\',
        \'db_export.php\',
        \'db_importdocsql.php\',
        \'db_multi_table_query.php\',
        \'db_structure.php\',
......
        \'user_password.php\',
    );

 

 
在 $goto_whitelist 中定义了可以被包含的文件名(很多,少些一部分)
 
第二个满足,直接跳过,第三个:
$_page = mb_substr(
    $page,
    0,
    mb_strpos($page . \'?\', \'?\')
);
if (in_array($_page, $whitelist)) {
    return true;
}

 

 
如果 $page 等于 $goto_whitelist 某个值,则 return true
这里考虑到 target 后面再跟参数的情况将 $_page 以?分割,然后去前面的字符再判断是否存在于 $goto_whitelist 中
还考虑到 url 编码的情况如果未成功下一步 url 解码
 
 
传入二次编码的内容就会让 checkPageValidity 后返回 true
 
比如传入:?target=db_datadict.php%253f
服务器自动解码一次是 ?target=db_datadict.php%3f
在经过 checkPageValidity 函数解码变成:?target=db_datadict.php?
这便符合了 ? 前面内容在白名单里会返回 true,但是 index.php 中的 $_REQUEST[\'target\'] 仍然是 db_datadict.php%3f,而且会被包含,通过目录穿越就会造成任意文件包含漏洞
 
 

分类:

技术点:

相关文章:

  • 2021-07-21
  • 2021-12-16
  • 2022-01-04
  • 2022-12-23
  • 2021-06-09
  • 2021-07-05
猜你喜欢
  • 2021-06-18
  • 2021-09-08
  • 2021-07-19
  • 2021-07-07
  • 2021-03-30
  • 2022-12-23
  • 2022-02-28
相关资源
相似解决方案