[NSSCTF 2022 Spring Recruit]babyphp

题目源码

php 复制代码
<?php
highlight_file(__FILE__);
include_once('flag.php');
if(isset($_POST['a'])&&!preg_match('/[0-9]/',$_POST['a'])&&intval($_POST['a'])){
    if(isset($_POST['b1'])&&$_POST['b2']){
        if($_POST['b1']!=$_POST['b2']&&md5($_POST['b1'])===md5($_POST['b2'])){
            if($_POST['c1']!=$_POST['c2']&&is_string($_POST['c1'])&&is_string($_POST['c2'])&&md5($_POST['c1'])==md5($_POST['c2'])){
                echo $flag;
            }else{
                echo "yee";
            }
        }else{
            echo "nop";
        }
    }else{
        echo "go on";
    }
}else{
    echo "let's get some php";
}
?>

核心思路

这道题通过三层条件验证,利用PHP在处理不同类型数据时的特性来绕过限制:

  1. 第一层:利用数组绕过正则和intval检查

  2. 第二层:利用数组使md5()返回NULL,通过严格比较

  3. 第三层:利用MD5弱比较碰撞(0e开头字符串)

逐层分析

第一关:参数 a 的绕过

php 复制代码
if(isset($_POST['a'])&&!preg_match('/[0-9]/',$_POST['a'])&&intval($_POST['a']))

限制条件:

  • a 参数必须存在

  • 不能包含任何数字字符(0-9)

  • intval($_POST['a']) 必须返回真值(非0)

绕过方法:

当 $_POST['a'] 是数组时:

  • isset($_POST['a']) → true ✓

  • preg_match('/[0-9]/', $_POST['a']) → 因为期望参数2是字符串但收到数组,返回 false 并产生警告,!false → true ✓

  • intval($_POST['a']) → 对数组类型调用 intval() 返回 1(非0值)→ true ✓

Payload: a[]=1

第二关:参数 b1 和 b2 的绕过

php 复制代码
if(isset($_POST['b1'])&&$_POST['b2']){
    if($_POST['b1']!=$_POST['b2']&&md5($_POST['b1'])===md5($_POST['b2'])){

限制条件:

  • b1 和 b2 必须存在且非空

  • b1 和 b2 的值必须不相等(!=)

  • 两者的 MD5 值必须完全相等(=== 严格比较)

绕过方法:

同样使用数组类型:

  • isset($_POST['b1']) && $_POST['b2'] → 两个数组都存在,条件成立 ✓

  • $_POST['b1'] != $_POST['b2'] → 两个不同的数组,比较结果为 true ✓

  • md5($_POST['b1']) === md5($_POST['b2']) →

    • md5() 函数处理数组时返回 NULL

    • NULL === NULL → true ✓

为什么要用 b1 和 b2 作为数组?

如果用字符串寻找MD5碰撞,需要找到两个不同的字符串具有完全相同的MD5值(哈希碰撞),这在计算上非常困难。而利用PHP的类型特性,可以轻松绕过。

Payload: b1[]=240610708&b2[]=QNKCDZO

注意: 这里数组的值可以任意,只要两个数组不同即可。

第三关:参数 c1 和 c2 的绕过

php 复制代码
if($_POST['c1']!=$_POST['c2']&&is_string($_POST['c1'])&&is_string($_POST['c2'])&&md5($_POST['c1'])==md5($_POST['c2']))

限制条件:

  • c1 和 c2 必须存在且不相等

  • c1 和 c2 必须是字符串类型

  • 两者的 MD5 值使用弱比较(==)相等

绕过方法:

使用两个字符串,它们的MD5值都以 0e 开头(科学计数法表示的数字0)。

在PHP的弱比较(==)中:

  • 0e123456 会被解释为 0 × 10^123456 = 0

  • 0e789012 同样等于 0

  • 因此 0 == 0 成立 ✓

经典的MD5碰撞对:

  • QNKCDZO → MD5: 0e830400451993494058024219903391

  • s878926199a → MD5: 0e545993274517709034328855841020

两者都以 0e 开头,在弱比较时都等于0。

Payload: c1=QNKCDZO&c2=s878926199a

完整PayloadPOST

php 复制代码
a[]=1&b1[]=240610708&b2[]=QNKCDZO&c1=QNKCDZO&c2=s878926199a

得到flag

NSSCTF{cffb2f7e-e90f-450a-bda0-d1d36c101cc1}

相关推荐
代码什么用3 小时前
Java Web 21-22
java·开发语言·web
努力搬砖的小H4 小时前
FPGA应用技巧之AXI4-FULL-MASTER IP FDMA(Fast Direct Memory)详细介绍
经验分享·fpga开发·fdma·axi总线·米联客
德思特4 小时前
2026射频微波系列直播开讲!| 射频设备、标准与方案落地全景解析
经验分享·无线通信·射频微波
Experience-摆渡5 小时前
REA:把逆向工程接给 AI Agent 的 MCP 服务器
经验分享
衫水5 小时前
红利类ETF定投与止盈策略表
经验分享
上海光华专利事务所5 小时前
【专利视点】食品领域应对《专利法》第五条的专利申请撰写策略——兼论普通食品、保健食品与药品的安全性、功能表述
经验分享
易知微EasyV数据可视化14 小时前
UE5中添加 PNG/TIF 到 Cesium 地球表面方案
经验分享·ue5·数字孪生
上海广测检测科技有限公司17 小时前
标签打印机CE与台湾BSMI+NCC双轨认证详解:多射频模块与电气安全叠加路径
经验分享
hengdonghui19 小时前
Writeup 4 N1BOOK afr_2
ctf·目录穿越
Go Work21 小时前
2026 Cadence SPB 24.1中文版安装图文详解(附安装包)
经验分享·笔记