软件安全赛2026线上初赛by NPUSEC
字数 6442
更新时间 2026-03-19 12:13:29

2026 NPUSEC软件安全赛线上初赛 全赛题详解与教学文档

目录

  1. Web 题目
    1.1. thymeleaf (Web)
    1.2. auth (Web)
  2. Pwn 题目
    2.1. mailsystem (Pwn)
  3. Reverse Engineering 题目
    3.1. re1 (Reverse)
    3.2. re2 (Reverse)
    3.3. re3 (Reverse)
  4. 密码学 题目
    4.1. RSA (密码学)
  5. Misc 题目
    5.1. steganography (Misc)
  6. 溯源与反制 题目
    6.1. traffic_hunt (溯源反制)

1. Web 题目

1.1. thymeleaf

  • 漏洞描述:目标是一个基于Java的Web应用,存在Thymeleaf模板注入漏洞,可用于内存马注入,进而提权读取flag。
  • 核心攻击链
    1. 伪随机数生成器 (PRNG) 破解:应用在注册用户时,密码由伪随机数生成,攻击者可以注册一个用户,利用返回的密码(PRNG当前状态的一部分),推算出admin用户的密码。脚本通过计算p & ((1 << 42) - 1)得到随机数种子的高42位,然后在该种子空间上偏移6位,爆破64个候选值,最终获取admin密码:0236506025278727
    2. Thymeleaf SSTI 内存马注入:在获取admin权限后,存在Thymeleaf模板注入点。攻击者构造Spring Expression Language (Spel)表达式,分三步(step1, step2, step3)将恶意字节码(内存马)注入到Java虚拟机中。注入的载荷是经过Base64编码和GZIP压缩的Java类文件,通过SpEL的defineClass方法动态加载并执行。
    3. 权限提升与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。

1.2. auth

  • 漏洞描述:应用存在SSRF漏洞,结合Redis未授权访问/弱密码以及Python pickle反序列化漏洞,实现从任意用户到admin的权限提升和远程代码执行。
  • 核心攻击链
    1. SSRF 与 信息泄露:以普通用户登录后,发现一个SSRF端点。通过该端点外带数据,可以读取到服务器本地的配置文件,例如app.py,从中获取Redis的初始配置(localhost:6379,密码123456)。
    2. Redis 弱密码/配置读取:尝试通过SSRF进行HTTP走私(CRLF注入)以直接操作Redis失败(密码错误)。转而利用SSRF读取Redis的默认配置文件/etc/redis/redis.conf,发现其真实密码为redispass123
    3. 权限提升至 Admin:使用获取的密码redispass123,通过SSRF构造CRLF注入攻击Redis,执行HSET user:11 role admin,将指定用户角色修改为admin
    4. Pickle 反序列化 RCE:成为admin后,访问/admin/online-users端点。该端点会从Redis中读取序列化(pickle)的用户对象并进行反序列化。攻击者可以利用之前的SSRF+Redis通道,将一个恶意的pickle数据写入Redis(如键online_user:11),当admin访问在线用户列表时触发反序列化,执行任意代码。
    5. XML-RPC 服务调用与Flag读取:在反序列化利用过程中,通过信息收集(如读取/proc/[pid]/cmdline)发现了另一个服务:一个运行在54321端口的XML-RPC服务(mcp_server)。该服务的execute_command方法可执行命令且无限制。利用获取的token,在反序列化漏洞触发时,通过Python代码调用此XML-RPC服务,执行cat /flag,从而获取flag。

2. Pwn 题目

2.1. mailsystem

  • 漏洞描述:一个邮件系统二进制程序,存在堆溢出、格式化字符串漏洞,通过组合利用实现House of Some攻击,获取shell。
  • 核心攻击链
    1. 逻辑漏洞绕过与溢出:逆向发现数组索引j可以等于12,导致可以溢出到BSS段的admin_note变量。通过触发“风控用户”功能,使得一个关键判断条件n7 <= 7成立,从而能够利用上述溢出,将admin的账号和密码字段覆盖为空,实现以空凭据登录admin账户。
    2. 格式化字符串泄露Libc地址:登录admin后,可以编辑用户邮箱内容。攻击者将一个用户的邮箱内容设置为stderr文件流指针,然后以另一个用户身份查看该邮件内容,从而泄露_IO_2_1_stderr_在内存中的地址,计算出libc基址。
    3. House of Some 攻击:利用获得的libc地址,通过堆布局和溢出,构造House of Some攻击利用链。该攻击通常涉及操控_IO_list_all等结构,最终触发_IO_flush_all_lockp时执行任意代码,获取shell。

3. Reverse Engineering 题目

3.1. re1

  • 解题过程
    1. 初步分析:题目提供一个压缩包,内含一个视频文件video.mp4和一个ELF可执行文件。分析ELF文件,在IDA中发现一段很长的Base64编码数据。
    2. 提取与解密:解码Base64数据,得到一个stager.pyc文件。使用在线pyc反编译工具获取其Python源码。分析代码,发现其从video.mp4中解码数据:视频的每一帧被分割为8x8像素块,根据像素块的平均亮度决定为比特01,每8个比特组成一个字节,然后与0xAA异或,还原出真正的二进制数据payload.bin
    3. 二次逆向payload.bin本身是一个ELF文件。用IDA分析,发现程序核心逻辑是输出一系列MD5哈希值。通过动态调试或静态分析,提取出这些MD5值,然后使用在线工具或脚本(如hashcat)进行破解,得到一系列字符,最终拼接为flag:dart{2ab1fb8a-b830-45e7-8830-66c7e3b3e05a}

3.2. re2

  • 解题过程
    1. 脱壳:程序为魔改UPX壳。将文件头的CTF改回UPX后,使用x64dbg手动脱壳。在特定跳转处下硬件断点,找到原始程序入口点(OEP),将内存数据dump下来。
    2. RC4解密:分析脱壳后的程序,找到一段巨大的Base64字符串,解码后得到另一个程序download.exe。分析download.exe,定位到核心函数sub_401A10 -> sub_4018F0 -> sub_4018B0,识别为RC4加密算法。通过动态调试,可以获取RC4密钥,解密出后续的AES加密代码或数据。
    3. 魔改AES分析与解密:程序的核心加密是AES-CBC模式,但进行了魔改:修改了Rcon常数,并且调整了轮函数中MixColumnsAddRoundKey的执行顺序(先AddRoundKey,再MixColumns)。编写逆向的魔改AES解密脚本,使用从内存中提取的密钥(Key)和初始化向量(IV),对密文进行解密,最终得到flag:dart{c3d4f5cc-8aab-46ce-a188-2fc453f3b288}

3.3. re3

  • 解题过程
    1. PyInstaller 解包client是一个PyInstaller打包的exe。使用pyinstxtractor等工具解包,得到pyc文件。使用pylingual等反编译工具获取Python源码(注意:pycdc等可能无法正确处理代码混淆)。
    2. 代码混淆与密钥还原:Python源码经过了自定义的混淆(_oe函数),涉及Base85解码、按位异或、字符移位等操作。通过分析混淆逻辑,可以还原出用于后续加密的密钥passvkcDKWLAA45o
    3. 核心加密分析:实际加密逻辑在crypt_core.so中。用IDA分析该SO文件,在sub_9820(Python函数包装器)和sub_60B0中识别出SM4国密算法。算法参数(S盒、FK、CK)均为标准值,未修改。
    4. 流量分析与解密:在提供的网络流量包(pcap)中,找到传输flag.txt的密文。使用之前还原出的密钥(SM4密钥为密钥的前16字节),用SM4算法(CBC或ECB模式,需根据代码确定)解密密文,即可得到最终的flag。

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
  • Level2 解题
    • 场景:已知部分明文(m1)及其对应密文(c1),且私钥d较小(或满足某种形式)。
    • 攻击:利用已知明文关系 c1^d ≡ m1 (mod n)。通过计算e/n的连分数展开,枚举收敛项的分母q,猜测d = q / gg为小整数因子),并用pow(c1, d, n) == m1验证。找到正确的d后,利用标准算法(基于k = ed - 1的分解方法)分解模数n,得到pq。计算sha256(str(p+q).encode()),得到Level3的密码:2aa9c360df99cbb4209e4dbab5a9f9ffd86d34906e3206fecfdabf0bb7aeb5ac
  • Level3 解题
    • 场景:标准的RSA加密,但额外泄露了一个信息leak,其计算方式为 leak = (S + ((p + q) mod 2^128)) ^ (n mod 2^64),其中S是由pq的低位通过复杂运算得到的掩码和。
    • 攻击 - 低位恢复
      1. 纠正运算顺序:Python中+优先级高于^,所以leak实际是 (S + ((p+q) & mask1)) ^ (n & mask2)
      2. 计算中间量:令 T = leak ^ (n mod 2^64),则得到 T = S + ((p + q) mod 2^128)
      3. 逐比特剪枝搜索:从最低位(bit 0)开始,同时枚举pq的下一个比特位(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低位计算)
      4. 恢复完整素数:通过上述剪枝搜索,可以高效地恢复出完整的1536位pq
    • 解密:使用恢复的p,q计算私钥d,解密密文c,得到最终的flag:dart{379c9308-e9a8-45a1-bd55-45bbd822e86d}

5. Misc 题目

5.1. steganography

  • 解题过程
    1. 修复文件头:首先需要将损坏的文件修复为有效的PNG格式。
    2. LSB隐写提取:对修复后的PNG图片,提取其RGB每个通道最低有效位(LSB),将提取的比特流按8位一组转换为字节,写入文件lsb_dump.bin
    3. CRC32爆破lsb_dump.bin内包含多个损坏的ZIP文件(pass*.zip)。这些ZIP文件中某个关键文件(如code.txt)的CRC32校验和已知,但文件内容的前4个字节未知。利用CRC32的线性性质,可以构造方程组,通过已知的CRC值逆推出未知的4字节内容,从而修复ZIP文件。
    4. 零宽字符隐写:在修复ZIP后得到的文件中,可能包含使用零宽字符(Zero-Width Characters)进行的隐写。通过识别并提取这些不可见字符(如U+200B, U+200C等),将其映射为比特01,进而解码出隐藏的信息。

6. 溯源与反制 题目

6.1. traffic_hunt

  • 解题过程
    1. WebShell 识别:分析提供的HTTP流量(pcap),发现大量对favicondemo.ico的POST请求,其请求体和响应体异常,确定为WebShell通信入口。
    2. 冰蝎流量解密
      • 从第一个POST请求的解码数据中,得到一个Java Class文件,反编译确认是“冰蝎”(Behinder)WebShell的核心类。
      • 直接使用Class文件中的默认密钥解密失败。
      • 使用工具CTF-NetA对全流量进行深度分析,发现了Shiro反序列化攻击的流量,并从中解密出了冰蝎通信所使用的新密钥
      • 使用这个新密钥,成功解密了后续所有的冰蝎流量,得到了大量传输的Class文件。
    3. 文件传输与提取:在解密的冰蝎流量中,发现多个update请求,其参数blockIndexcontent表明攻击者正在分块上传一个文件(名为out)。编写脚本,将所有分块内容按照索引顺序拼接并Base64解码,还原出完整的out文件。
    4. Python打包文件分析:运行out文件报错,但提示其为PyInstaller打包的可执行文件。使用pyinstxtractor解包,并对核心pyc文件进行反编译,得到Python源码。
    5. 木马功能分析:分析源码,out是一个反弹Shell后门。通信数据使用AES-GCM模式加密。加密数据包的格式为:12字节Nonce + 密文 + 16字节Tag
    6. 流量解密与Flag获取:在pcap的TCP流中(非HTTP),找到与out后门通信的加密数据。使用从Python代码中提取或推导出的AES密钥,按照AES-GCM格式解密这些TCP负载,在解密后的明文通信中,找到攻击者最终执行的命令或返回的结果,其中包含flag:dart{d9850b27-85cb-4777-85e0-df0b78fdb722}
相似文章
相似文章
 全屏