青岑CTF之 EZPHP系列 EZPHP?phpshow_source(__FILE__);include(flag.php);$a$_GET[a];$b$_GET[b];if($aand$a0){if(is_numeric($b)){exit(nono);}else{if($b2026){echo$flag;}}}else{exit(no);}?在 PHP 8.0 之前的版本中当一个不以数字开头的字符串与整数进行比较时PHP 会尝试将字符串转换为数字。因为字符串无法转换就会被当成0处理。如果传入aabcif(abc)成立非空字符串为真。abc 0成立“abc” 转换成数字是 00 0为真。参数b同样利用 PHP 的弱类型特性。当一个以数字开头但包含字母的字符串与数字进行比较时PHP 会截取前面部分作为数字来计算。如果传入b2027ais_numeric(2027a)为false因为包含字母 ‘a’不是纯数字。2027a 2026时PHP 会将2027a隐式转换为2027此时2027 2026成立。Payload 建议b2027a数字部分大于2026后面随便跟一个字母即可。EZPHP_1?phpshow_source(__FILE__);include(flag.php);if(!isset($_GET[qc])||$_GET[qc])exit(no);$qc(array)json_decode($_GET[qc],true);$keyarray_search(QCCTF,$qc);if($key1){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($valQCyyds)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($valQCyyds)die(no......);}要求在$qc[n]这个子数组里必须通过array_search找到QCyyds使用松散比较。要求紧接着遍历这个子数组里面绝对不能出现严格等于QCyyds的值使用严格比较。这就形成了一个经典的 CTF 悖论 既要在数组里“找到”这个字符串又“不能真的把这个字符串放进去”。 依旧用布尔值true构造payload:?qc{n:[true],1:QCCTF}EZPHP_3?phpheader(Content-type:text/html;charsetutf-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])2025intval($_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)11e83100000003但在PHP 8.0 及以上版本中PHP 增强了类型的严格性。将包含字母的字符串即使是科学计数法格式直接进行数学加法运算 3可能会导致异常或被严格判定从而返回 False。这道题不需要用科学计数法去绕直接传一个最普通的数字就可以完美满足条件比如传2024甚至是2024.5