青岑CTF之 EZPHP系列
2026/6/10 14:13:53 网站建设 项目流程

EZPHP

<?phpshow_source(__FILE__);include("flag.php");$a=@$_GET['a'];$b=@$_GET['b'];if($aand$a==0){if(is_numeric($b)){exit("nono");}else{if($b>2026){echo$flag;}}}else{exit("no");}?>

在 PHP 8.0 之前的版本中,当一个不以数字开头的字符串与整数进行==比较时,PHP 会尝试将字符串转换为数字。因为字符串无法转换,就会被当成0处理。

  • 如果传入a=abc
    • if("abc")成立(非空字符串为真)。
    • "abc" == 0成立(“abc” 转换成数字是 0,0 == 0为真)。

参数b同样利用 PHP 的弱类型特性。当一个以数字开头但包含字母的字符串与数字进行比较时,PHP 会截取前面部分作为数字来计算。

  • 如果传入b=2027a
    • is_numeric("2027a")false(因为包含字母 ‘a’,不是纯数字)。
    • "2027a" > 2026时,PHP 会将"2027a"隐式转换为2027,此时2027 > 2026成立。

Payload 建议:&b=2027a(数字部分大于2026,后面随便跟一个字母即可)。

EZPHP_1

<?phpshow_source(__FILE__);include("flag.php");if(!isset($_GET['qc'])||$_GET['qc']==='')exit("no");$qc=(array)json_decode($_GET['qc'],true);$key=array_search("QCCTF",$qc);if($key===1){echo$flag;}else{exit("no");}?>

这里调用array_search()没有传入第三个参数true。这意味着它使用的是松散比较 (==)。 它会遍历$qc数组,拿每一个“值”去和字符串"QCCTF"==比较,一旦匹配成功,就返回对应的“键(Key)”。 我们需要让array_search()返回的键名严格等于整数1

在 PHP 中(无论 PHP 7 还是 PHP 8),布尔值true与任何非空字符串做==比较,结果都是true。因为这里用了json_decode()函数,json_decode()是一个极其严格的“翻译官”。如果传入的字符串不符合 JSON 的语法规范,它就会直接罢工,返回null。因此构造payload:

?qc={"1":true} //or ?qc={"1":"QCCTF"}

EZPHP_2

<?phpshow_source(__FILE__);include("flag.php");if(!isset($_GET['qc'])||$_GET['qc']==='')exit("no");$qc=(array)json_decode($_GET['qc'],true);if(!isset($qc["n"])||!is_array($qc["n"])||empty($qc["n"]))die("no");if(array_search("QCCTF",$qc)===false)die("no...");if(array_search("QCyyds",$qc["n"])===false)die("no...");foreach($qc["n"]as$val){if($val==="QCyyds")die("no......");}echo$flag;

这题可以说是上一道的升级版了

if(!isset($qc["n"])||!is_array($qc["n"])||empty($qc["n"]))die("no");

要求:传入的 JSON 必须包含一个名为"n"的键,且这个键的值必须是一个非空的数组

if(array_search("QCCTF",$qc)===false)die("no...");

要求:$qc的第一层级(Top-level)的值里面,必须有一个能和"QCCTF"产生松散匹配(==)。

if(array_search("QCyyds",$qc["n"])===false)die("no...");// 第三关foreach($qc["n"]as$val){// 第四关if($val==="QCyyds")die("no......");}
  • 要求:$qc["n"]这个子数组里,必须通过array_search找到"QCyyds"(使用==松散比较)。
  • 要求:紧接着遍历这个子数组,里面绝对不能出现严格等于"QCyyds"的值(使用===严格比较)。

这就形成了一个经典的 CTF 悖论:> 既要在数组里“找到”这个字符串,又“不能真的把这个字符串放进去”。 依旧用布尔值true构造payload:

?qc={"n":[true],"1":"QCCTF"}

EZPHP_3

<?phpheader('Content-type:text/html;charset=utf-8');error_reporting(0);highlight_file(__FILE__);include_once('flag.php');if(isset($_GET['qc'])&&preg_match('/^Welcome to QingCen 2026!$/i',$_GET['qc'])&&$_GET['qc']!=='Welcome to QingCen 2026!'){if(intval($_GET['lover'])<2025&&intval($_GET['lover']+3)>2026){if(isset($_POST['Q'])&&$_POST['C']){$array1=(string)$_POST['Q'];$array2=(string)$_POST['C'];if(sha1($array1)===sha1($array2)){if(isset($_POST['ZJZ_QingCen.2026'])&&$_POST['ZJZ_QingCen.2026']==="Happy to see you!"){echo$flag;}else{echo"再绕最后一步吧";}}else{echo"好哩,快拿到flag啦";}}else{echo"这里绕不过去,QingCen可不答应了哈";}}else{echo"嘿嘿嘿,你别急啊";}}else{echo"不会吧不会吧,不会第一步就卡住了吧,ZJZ会瞧不起你的!";

这道题和我之前做的一道题很像:极客大挑战2023-web-easy_php-CSDN博客,只是在intval函数的处理上有所不同:

虽然在旧版 PHP 中,科学计数法结合intval和加法会发生奇妙的类型转换(intval('1e8')=1'1e8'+3=100000003),但在PHP 8.0 及以上版本中,PHP 增强了类型的严格性。将包含字母的字符串(即使是科学计数法格式)直接进行数学加法运算(+ 3),可能会导致异常或被严格判定从而返回 False。

这道题不需要用科学计数法去绕,直接传一个最普通的数字就可以完美满足条件,比如传2024甚至是2024.5

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询