BUUCTF WarmUp CVE-2018-12613

2019-06-15  本文已影响0人  Visianlee

source.php

 <?php
    highlight_file(__FILE__);
    class emmm //waf
    {
        public static function checkFile(&$page)
//<?php $a =& $b ?> 这意味着 $a 和 $b 指向了同一个变量。 注: $a 和 $b 在这里是完全相同的,这并不是 $a 指向了 $b 或者相反,而是 $a 和 $b 指向了同一个地方。 
        {
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
            if (! isset($page) || !is_string($page)) {
                echo "you can't see it";
                return false;
            }

            if (in_array($page, $whitelist)) {//in_array() 函数搜索数组中是否存在指定的值。从后查找前。
                return true;
            }

            $_page = mb_substr(//echo mb_substr("菜鸟教程", 0, 2); 输出:菜鸟
                $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;
            }
            echo "you can't see it";
            return false;
        }
    }

    if (! empty($_REQUEST['file'])//PHP $_REQUEST 用于收集HTML表单提交的数据。$_REQUEST 变量包含了 $_GET, $_POST 以及 $_COOKIE 的内容
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])//可以不用实例化对象直接使用emmm::checkFile($_REQUEST['file'])获得checkFile($_REQUEST['file'])的值
    ) {
        include $_REQUEST['file'];
        exit;
    } else {
        echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
    }  
?>

这里参考文章分析一波.

漏洞原理

一个攻击者可以在服务器上包含(查看和潜在执行)文件的漏洞被发现。该漏洞来自一部分代码,其中页面在phpMyAdmin中被重定向和加载,以及对白名单页面进行不正确的测试。攻击者必须经过身份验证,但在这些情况下除外:
cfg ['AllowArbitraryServer'] = true:攻击者可以指定他/她已经控制的任何主机,并在phpMyAdmin上执行任意代码(可以进行远程访问) cfg ['ServerDefault'] = 0:这会绕过登录并在没有任何身份验证的情况下运行易受攻击的代码。如果有多台已配置的服务器,你可以配置cfg['ServerDefault'] 为其中之一,phpmyadmin会自动连接,如果配置为0,将会显示一个没有登录的服务器列表。如果你只有一个服务器设置,cfg['ServerDefault'] 必须配置为那台服务器。

漏洞形成的原因

if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])
    ) {
        include $_REQUEST['file'];
        exit;
    } else {
        echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
    }  

if区间一共有4个判断:

1、是否存在file参数
2、file参数是否为字符串
3、emmm类的checkFile方法判断
如果通过判断则包含参数所指定的文件

首先找到Core类的checkFile函数:

class emmm //waf
    {
        public static function checkFile(&$page)
//<?php $a =& $b ?> 这意味着 $a 和 $b 指向了同一个变量。 注: $a 和 $b 在这里是完全相同的,这并不是 $a 指向了 $b 或者相反,而是 $a 和 $b 指向了同一个地方。 
        {
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
            if (! isset($page) || !is_string($page)) {
                echo "you can't see it";
                return false;
            }

            if (in_array($page, $whitelist)) {//in_array() 函数搜索数组中是否存在指定的值。从后查找前。
                return true;
            }

            $_page = mb_substr(//echo mb_substr("菜鸟教程", 0, 2); 输出:菜鸟
                $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;
            }
            echo "you can't see it";
            return false;
        }
    }

checkPageValidity函数里又是4个判断:

1、如果page没有被定义过或者page不为字符串则return false

2、page存在whitelist中的某个值则返回true

3、_page存在whitelist中的某个值则返回true

4、经过urldecode函数解码后的_page存在whitelist中的某个值则返回true
我们来逐行分析:
$whitelist定义了两个可以被包含的文件名

if (in_array($page, $whitelist)) {//in_array() 函数搜索数组中是否存在指定的值。从后查找前。
                return true;
            }

第二个if直接跳过我们来看第三个if区间,如果page如果等于whilelist的某个值则return真。
phpmyadmin的开发团队考虑的很全面,想到了会存在file的值后面再跟参数的情况,于是有了第三个判断:

 $_page = mb_substr(//echo mb_substr("菜鸟教程", 0, 2); 输出:菜鸟
                $page,
                0,
                mb_strpos($page . '?', '?')//查找字符串在另一个字符串中首次出现的位置
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }

_page为以?分割然后取出前面的字符串再判断值是否存在与whilelist某个数组中。

这个判断的作用是,如果file值带有参数的情况下,phpmyadmin也能正确的包含文件。
也正是因为phpmyadmin团队考虑的太全面了,才会出现此漏洞......

$_page = urldecode($page);
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }
            echo "you can't see it";
            return false;
        }

后面又将$page参数用urlencode解码再进行以?分割取出前面的值做判断。

我们构造payload:
file=source.php?/../../../../../../ffffllllaaaagggg,目录穿越,当然还要把?进行两次url编码,所以最后的payload为file=source.php%253f/../../../../../../ffffllllaaaagggg,首先,第一次验证肯定过不了,第二次截取完也过不了,第三次,经过url解码之后,我们构造的payload就变成了source.php?/../../../../../../ffffllllaaaagggg,很显然,它是截取?前面的进行校验,我们这的source.php在白名单中,所以返回true,最后通过目录穿越的到ffffllllaaaagggg里面的内容,也就是flag。

参考:
https://blog.csdn.net/qq_42967398/article/details/91127332

https://blog.csdn.net/qq_37433000/article/details/91126718

https://www.jianshu.com/p/0d75017c154f

https://www.cnblogs.com/leixiao-/p/10265150.html

上一篇下一篇

猜你喜欢

热点阅读