[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}

相关推荐
dfbz1234563 小时前
长沙中秋礼品市场数据分析:文创属性如何驱动复购率和口碑传播
大数据·经验分享·数据挖掘·数据分析
杨连江4 小时前
永磁同步电机FOC控制核心算法与工程实现研究
经验分享
Seraphina364 小时前
记一次实验:利用缓存服务器规范化技术进行网页缓存欺骗
经验分享·笔记·网络安全·缓存
虹科数字化与AR4 小时前
工业AR设备采购指南:从参数到场景的全面评估框架
经验分享
0xBADCODE5 小时前
动态DEX加载+反射+DES硬编码密钥:安卓三层逆向实战
android·java·python·安全·网络安全·逆向·ctf
梦075 小时前
实操手册-OpenClaw长任务超时无响应的解决
经验分享·openclaw
数智启示录6 小时前
Apache Doris 4.0.8 一致性实战(第 3 篇):Checkpoint 一直成功,Exactly-Once 为什么仍可能是假的
大数据·经验分享·面试·flink
luj_17687 小时前
毒素驱动的生物自毁机制探析
服务器·c语言·开发语言·经验分享·算法
数智启示录7 小时前
Apache Doris 4.0.8 CDC 正确性(第 9 篇):Flink Checkpoint 一直成功,表里为什么仍是旧数据
大数据·数据库·经验分享·面试·flink