软件安全赛2026线上初赛by NPUSEC
字数 6442
更新时间 2026-03-19 12:13:29
2026 NPUSEC软件安全赛线上初赛 全赛题详解与教学文档
目录
- Web 题目
1.1. thymeleaf (Web)
1.2. auth (Web) - Pwn 题目
2.1. mailsystem (Pwn) - Reverse Engineering 题目
3.1. re1 (Reverse)
3.2. re2 (Reverse)
3.3. re3 (Reverse) - 密码学 题目
4.1. RSA (密码学) - Misc 题目
5.1. steganography (Misc) - 溯源与反制 题目
6.1. traffic_hunt (溯源反制)
1. Web 题目
1.1. thymeleaf
- 漏洞描述:目标是一个基于Java的Web应用,存在Thymeleaf模板注入漏洞,可用于内存马注入,进而提权读取flag。
- 核心攻击链:
- 伪随机数生成器 (PRNG) 破解:应用在注册用户时,密码由伪随机数生成,攻击者可以注册一个用户,利用返回的密码(PRNG当前状态的一部分),推算出
admin用户的密码。脚本通过计算p & ((1 << 42) - 1)得到随机数种子的高42位,然后在该种子空间上偏移6位,爆破64个候选值,最终获取admin密码:0236506025278727。 - Thymeleaf SSTI 内存马注入:在获取
admin权限后,存在Thymeleaf模板注入点。攻击者构造Spring Expression Language (Spel)表达式,分三步(step1, step2, step3)将恶意字节码(内存马)注入到Java虚拟机中。注入的载荷是经过Base64编码和GZIP压缩的Java类文件,通过SpEL的defineClass方法动态加载并执行。 - 权限提升与Flag读取:初始注入的内存马权限不足,重新注入了一个
Behinder(冰蝎)内存马。通过利用系统已安装的7z工具进行提权,最终执行命令/usr/bin/7z a -bd -ttar -an -so /flag 2>/dev/null | /usr/bin/7z e -bd -ttar -si -so 2>/dev/null读取flag。
- 伪随机数生成器 (PRNG) 破解:应用在注册用户时,密码由伪随机数生成,攻击者可以注册一个用户,利用返回的密码(PRNG当前状态的一部分),推算出
1.2. auth
- 漏洞描述:应用存在SSRF漏洞,结合Redis未授权访问/弱密码以及Python
pickle反序列化漏洞,实现从任意用户到admin的权限提升和远程代码执行。 - 核心攻击链:
- SSRF 与 信息泄露:以普通用户登录后,发现一个SSRF端点。通过该端点外带数据,可以读取到服务器本地的配置文件,例如
app.py,从中获取Redis的初始配置(localhost:6379,密码123456)。 - Redis 弱密码/配置读取:尝试通过SSRF进行HTTP走私(CRLF注入)以直接操作Redis失败(密码错误)。转而利用SSRF读取Redis的默认配置文件
/etc/redis/redis.conf,发现其真实密码为redispass123。 - 权限提升至 Admin:使用获取的密码
redispass123,通过SSRF构造CRLF注入攻击Redis,执行HSET user:11 role admin,将指定用户角色修改为admin。 - Pickle 反序列化 RCE:成为
admin后,访问/admin/online-users端点。该端点会从Redis中读取序列化(pickle)的用户对象并进行反序列化。攻击者可以利用之前的SSRF+Redis通道,将一个恶意的pickle数据写入Redis(如键online_user:11),当admin访问在线用户列表时触发反序列化,执行任意代码。 - XML-RPC 服务调用与Flag读取:在反序列化利用过程中,通过信息收集(如读取
/proc/[pid]/cmdline)发现了另一个服务:一个运行在54321端口的XML-RPC服务(mcp_server)。该服务的execute_command方法可执行命令且无限制。利用获取的token,在反序列化漏洞触发时,通过Python代码调用此XML-RPC服务,执行cat /flag,从而获取flag。
- SSRF 与 信息泄露:以普通用户登录后,发现一个SSRF端点。通过该端点外带数据,可以读取到服务器本地的配置文件,例如
2. Pwn 题目
2.1. mailsystem
- 漏洞描述:一个邮件系统二进制程序,存在堆溢出、格式化字符串漏洞,通过组合利用实现
House of Some攻击,获取shell。 - 核心攻击链:
- 逻辑漏洞绕过与溢出:逆向发现数组索引
j可以等于12,导致可以溢出到BSS段的admin_note变量。通过触发“风控用户”功能,使得一个关键判断条件n7 <= 7成立,从而能够利用上述溢出,将admin的账号和密码字段覆盖为空,实现以空凭据登录admin账户。 - 格式化字符串泄露Libc地址:登录
admin后,可以编辑用户邮箱内容。攻击者将一个用户的邮箱内容设置为stderr文件流指针,然后以另一个用户身份查看该邮件内容,从而泄露_IO_2_1_stderr_在内存中的地址,计算出libc基址。 - House of Some 攻击:利用获得的libc地址,通过堆布局和溢出,构造
House of Some攻击利用链。该攻击通常涉及操控_IO_list_all等结构,最终触发_IO_flush_all_lockp时执行任意代码,获取shell。
- 逻辑漏洞绕过与溢出:逆向发现数组索引
3. Reverse Engineering 题目
3.1. re1
- 解题过程:
- 初步分析:题目提供一个压缩包,内含一个视频文件
video.mp4和一个ELF可执行文件。分析ELF文件,在IDA中发现一段很长的Base64编码数据。 - 提取与解密:解码Base64数据,得到一个
stager.pyc文件。使用在线pyc反编译工具获取其Python源码。分析代码,发现其从video.mp4中解码数据:视频的每一帧被分割为8x8像素块,根据像素块的平均亮度决定为比特0或1,每8个比特组成一个字节,然后与0xAA异或,还原出真正的二进制数据payload.bin。 - 二次逆向:
payload.bin本身是一个ELF文件。用IDA分析,发现程序核心逻辑是输出一系列MD5哈希值。通过动态调试或静态分析,提取出这些MD5值,然后使用在线工具或脚本(如hashcat)进行破解,得到一系列字符,最终拼接为flag:dart{2ab1fb8a-b830-45e7-8830-66c7e3b3e05a}。
- 初步分析:题目提供一个压缩包,内含一个视频文件
3.2. re2
- 解题过程:
- 脱壳:程序为魔改UPX壳。将文件头的
CTF改回UPX后,使用x64dbg手动脱壳。在特定跳转处下硬件断点,找到原始程序入口点(OEP),将内存数据dump下来。 - RC4解密:分析脱壳后的程序,找到一段巨大的Base64字符串,解码后得到另一个程序
download.exe。分析download.exe,定位到核心函数sub_401A10->sub_4018F0->sub_4018B0,识别为RC4加密算法。通过动态调试,可以获取RC4密钥,解密出后续的AES加密代码或数据。 - 魔改AES分析与解密:程序的核心加密是AES-CBC模式,但进行了魔改:修改了Rcon常数,并且调整了轮函数中
MixColumns和AddRoundKey的执行顺序(先AddRoundKey,再MixColumns)。编写逆向的魔改AES解密脚本,使用从内存中提取的密钥(Key)和初始化向量(IV),对密文进行解密,最终得到flag:dart{c3d4f5cc-8aab-46ce-a188-2fc453f3b288}。
- 脱壳:程序为魔改UPX壳。将文件头的
3.3. re3
- 解题过程:
- PyInstaller 解包:
client是一个PyInstaller打包的exe。使用pyinstxtractor等工具解包,得到pyc文件。使用pylingual等反编译工具获取Python源码(注意:pycdc等可能无法正确处理代码混淆)。 - 代码混淆与密钥还原:Python源码经过了自定义的混淆(
_oe函数),涉及Base85解码、按位异或、字符移位等操作。通过分析混淆逻辑,可以还原出用于后续加密的密钥passvkcDKWLAA45o。 - 核心加密分析:实际加密逻辑在
crypt_core.so中。用IDA分析该SO文件,在sub_9820(Python函数包装器)和sub_60B0中识别出SM4国密算法。算法参数(S盒、FK、CK)均为标准值,未修改。 - 流量分析与解密:在提供的网络流量包(pcap)中,找到传输
flag.txt的密文。使用之前还原出的密钥(SM4密钥为密钥的前16字节),用SM4算法(CBC或ECB模式,需根据代码确定)解密密文,即可得到最终的flag。
- PyInstaller 解包:
4. 密码学 题目
4.1. RSA
- 题目结构:本题分为三个关卡(level1, level2, level3),层层递进。
- Level1 解题:
- 本质:伪秘密共享 + 弱RSA密钥集合。多个份额
k_i满足同余方程k_i ≡ S (mod d_i),其中S为共享秘密,d_i为整数。可以使用中国剩余定理(CRT)重构出S。 - RSA攻击:提供了多个(20个)RSA公钥文件(
key-i.pem)和对应的密文。这些RSA公钥存在各种已知弱点:GCD攻击(模数共享质因子)、Fermat分解(素数接近)、Wiener攻击(私钥过小)、小模数、多素数模数等。需要编写脚本自动检测并利用这些弱点,解密出部分AES密钥(密文是AES密钥经RSA加密的结果)。 - 秘密恢复:解密的AES密钥片段对应着秘密共享的份额
k_i。利用CRT恢复出完整的共享秘密S,即Level2的密码:9Zr4M1ThwVCHe4nHnmOcilJ8。
- 本质:伪秘密共享 + 弱RSA密钥集合。多个份额
- Level2 解题:
- 场景:已知部分明文(
m1)及其对应密文(c1),且私钥d较小(或满足某种形式)。 - 攻击:利用已知明文关系
c1^d ≡ m1 (mod n)。通过计算e/n的连分数展开,枚举收敛项的分母q,猜测d = q / g(g为小整数因子),并用pow(c1, d, n) == m1验证。找到正确的d后,利用标准算法(基于k = ed - 1的分解方法)分解模数n,得到p和q。计算sha256(str(p+q).encode()),得到Level3的密码:2aa9c360df99cbb4209e4dbab5a9f9ffd86d34906e3206fecfdabf0bb7aeb5ac。
- 场景:已知部分明文(
- Level3 解题:
- 场景:标准的RSA加密,但额外泄露了一个信息
leak,其计算方式为leak = (S + ((p + q) mod 2^128)) ^ (n mod 2^64),其中S是由p和q的低位通过复杂运算得到的掩码和。 - 攻击 - 低位恢复:
- 纠正运算顺序:Python中
+优先级高于^,所以leak实际是(S + ((p+q) & mask1)) ^ (n & mask2)。 - 计算中间量:令
T = leak ^ (n mod 2^64),则得到T = S + ((p + q) mod 2^128)。 - 逐比特剪枝搜索:从最低位(bit 0)开始,同时枚举
p和q的下一个比特位(0或1,共4种组合)。在每一步k,检查两个约束是否同时满足:- 约束1(模数约束):
(p * q) mod 2^(k+1) == n mod 2^(k+1) - 约束2(泄露约束):
(S + ((p+q) & mask)) mod 2^(k+1) == T mod 2^(k+1)(其中S用当前的p,q低位计算)
- 约束1(模数约束):
- 恢复完整素数:通过上述剪枝搜索,可以高效地恢复出完整的1536位
p和q。
- 纠正运算顺序:Python中
- 解密:使用恢复的
p,q计算私钥d,解密密文c,得到最终的flag:dart{379c9308-e9a8-45a1-bd55-45bbd822e86d}。
- 场景:标准的RSA加密,但额外泄露了一个信息
5. Misc 题目
5.1. steganography
- 解题过程:
- 修复文件头:首先需要将损坏的文件修复为有效的PNG格式。
- LSB隐写提取:对修复后的PNG图片,提取其RGB每个通道最低有效位(LSB),将提取的比特流按8位一组转换为字节,写入文件
lsb_dump.bin。 - CRC32爆破:
lsb_dump.bin内包含多个损坏的ZIP文件(pass*.zip)。这些ZIP文件中某个关键文件(如code.txt)的CRC32校验和已知,但文件内容的前4个字节未知。利用CRC32的线性性质,可以构造方程组,通过已知的CRC值逆推出未知的4字节内容,从而修复ZIP文件。 - 零宽字符隐写:在修复ZIP后得到的文件中,可能包含使用零宽字符(Zero-Width Characters)进行的隐写。通过识别并提取这些不可见字符(如
U+200B,U+200C等),将其映射为比特0和1,进而解码出隐藏的信息。
6. 溯源与反制 题目
6.1. traffic_hunt
- 解题过程:
- WebShell 识别:分析提供的HTTP流量(pcap),发现大量对
favicondemo.ico的POST请求,其请求体和响应体异常,确定为WebShell通信入口。 - 冰蝎流量解密:
- 从第一个POST请求的解码数据中,得到一个Java Class文件,反编译确认是“冰蝎”(Behinder)WebShell的核心类。
- 直接使用Class文件中的默认密钥解密失败。
- 使用工具
CTF-NetA对全流量进行深度分析,发现了Shiro反序列化攻击的流量,并从中解密出了冰蝎通信所使用的新密钥。 - 使用这个新密钥,成功解密了后续所有的冰蝎流量,得到了大量传输的Class文件。
- 文件传输与提取:在解密的冰蝎流量中,发现多个
update请求,其参数blockIndex和content表明攻击者正在分块上传一个文件(名为out)。编写脚本,将所有分块内容按照索引顺序拼接并Base64解码,还原出完整的out文件。 - Python打包文件分析:运行
out文件报错,但提示其为PyInstaller打包的可执行文件。使用pyinstxtractor解包,并对核心pyc文件进行反编译,得到Python源码。 - 木马功能分析:分析源码,
out是一个反弹Shell后门。通信数据使用AES-GCM模式加密。加密数据包的格式为:12字节Nonce + 密文 + 16字节Tag。 - 流量解密与Flag获取:在pcap的TCP流中(非HTTP),找到与
out后门通信的加密数据。使用从Python代码中提取或推导出的AES密钥,按照AES-GCM格式解密这些TCP负载,在解密后的明文通信中,找到攻击者最终执行的命令或返回的结果,其中包含flag:dart{d9850b27-85cb-4777-85e0-df0b78fdb722}。
- WebShell 识别:分析提供的HTTP流量(pcap),发现大量对
相似文章
相似文章