文章总结: 本文档为第三届数信杯CTF个人赛WP,涵盖Web、逆向、密码学及取证方向。核心内容包括利用LFI漏洞与SSO绕过获取管理员权限、逆向PyInstaller提取RSA私钥解密勒索软件、FAT16磁盘镜像恢复与内存取证、SQLite空闲块数据隐藏分析、AES-CBC密钥恢复及TLS流量解密审计越权访问。文档详细提供了解题思路、脚本代码与具体操作步骤,具有较高的实战技术参考价值。 综合评分: 93 文章分类: CTF,WEB安全,逆向分析,密码学,应急响应
解题过程
1. 模型结构分析
首先加载 multimodal_model.pth,通过 state_dict 分析模型结构。模型包含三个线性层(Linear),权重形状分别为 [64, 20], [32, 64], [27, 32]。这表明模型是一个简单的 MLP:
- Input: 20
- Layer 1: Linear(20, 64) + ReLU
- Layer 2: Linear(64, 32) + ReLU
- Layer 3: Linear(32, 27) (Output)
2. 像素提取
提示提到“左上角前20个像素”。在图像处理中,这可能指第一行前20个 (x, 0) 或第一列前20个 (0, y)。经过测试,提取第一列(即 x=0, y=0 到 y=19)的 R 通道值,并进行 % 10 运算,输入模型后能得到有意义的 ASCII 码。
3. 编写解题脚本
编写 Python 脚本实现以下功能:
- 定义
SimpleMLP类。 - 加载
multimodal_model.pth权重。 - 读取
secret_image.png,提取 (0,0) 到 (0,19) 的 R 值。 - 执行推理并解码。
4. 解题代码
importtorch
importtorch.nnasnn
fromPILimportImage
importnumpyasnp
# 定义模型结构
classSimpleMLP(nn.Module):
def__init__(self):
super(SimpleMLP, self).__init__()
self.fc1=nn.Linear(20, 64)
self.fc2=nn.Linear(64, 32)
self.fc3=nn.Linear(32, 27)
self.relu=nn.ReLU()
defforward(self, x):
x=self.relu(self.fc1(x))
x=self.relu(self.fc2(x))
x=self.fc3(x)
returnx
defsolve():
# 1. 加载模型
model=SimpleMLP()
try:
state_dict=torch.load('multimodal_model.pth')
model.load_state_dict(state_dict)
model.eval()
exceptExceptionase:
print(f"模型加载失败: {e}")
return
# 2. 加载图片并提取特征
try:
img=Image.open('secret_image.png')
img=img.convert('RGB')
exceptExceptionase:
print(f"图片加载失败: {e}")
return
# 提取第一列前20个像素的R值 (x=0, y=0~19)
pixels= []
foryinrange(20):
r, g, b=img.getpixel((0, y))
pixels.append(r)
print(f"提取的 R 值: {pixels}")
# 计算特征: R % 10
features= [r%10forrinpixels]
print(f"特征向量: {features}")
# 3. 模型推理
input_tensor=torch.tensor(features, dtype=torch.float32).unsqueeze(0)
withtorch.no_grad():
output=model(input_tensor)
output_values=output.squeeze().tolist()
# 4. 解码 Flag
flag_chars= []
forvalinoutput_values:
# 四舍五入取整转ASCII
ascii_code=int(round(val))
flag_chars.append(chr(ascii_code))
flag="".join(flag_chars)
print(f"\nFlag: {flag}")
if__name__=="__main__":
solve()
5. 运行结果
运行脚本得到输出:
提取的 R 值: [253, 248, 247, 252, 249, 251, 254, 250, 255, 246, 248, 247, 249, 252, 251, 254, 250, 255, 253, 246]
特征向量: [3, 8, 7, 2, 9, 1, 4, 0, 5, 6, 8, 7, 9, 2, 1, 4, 0, 5, 3, 6]
Flag: flag{A12I_shu1xin2bei_2025}
Flag
flag{A12I_shu1xin2bei_2025}
二、数据分析
1.数据处理
第一问:流量分析
题目描述
第一天上班的你去查看公司的流量监控记录,发现了一串非常奇怪的流量信息,你判断出这是黑客攻击所产生的流量,请你分析流量,找出泄露的信息。
分析过程
- 流量包分析使用 Wireshark 或脚本分析
attack.pcapng流量包。重点关注 HTTP 协议的流量,特别是 POST 请求和响应内容。 - 发现敏感信息泄露在分析 HTTP 响应数据时,发现第 3116 号数据包(Packet 3116)是一个登录页面的响应 HTML。在该 HTML 的
<head>标签中,存在一段可疑的 JavaScript 代码,直接硬编码了系统默认凭证:
<script>varsys_default_credential="Adm1n@2024#Secure!Pass";</script>
-
验证攻击路径继续追踪流量,发现第 3134 号数据包(Packet 3134)是一个 POST 请求,攻击者使用了上述泄露的凭证进行登录:
对 Payload 进行 URL 解码:
随后的第 3150 号数据包显示登录成功,服务器返回了后台管理页面的 HTML 内容。
-
username:admin -
password:Adm1n@2024#Secure!Pass -
URL:
/login -
Payload:
username=admin&password=Adm1n%402024%23Secure%21Pass
结论
泄露的管理员账号密码为:
admin/Adm1n@2024#Secure!Pass
第二问:数据脱敏恢复
题目描述
与你交接的同事由于工作上的疏忽将原先的居民信息文件误删除了,但是你发现公司的系统上依旧存在居民的信息,下载后发现进行了脱敏处理,你需要利用技术手段将居民信息快速整理出来。目标:找出家庭住址。
分析过程
- 文件分析打开
居民信息表.csv,观察数据内容。发现列的数据呈现乱码状,且包含+、/、=等字符,具有明显的 Base64 编码特征。 - 解密逻辑编写 Python 脚本处理 CSV 文件:
- 读取 CSV 文件的每一行。
- 对“手机号码”列的内容进行 Base64 解码。
- 将解码后的手机与目标手机进行比对。
- 查找结果
- 当脚本遍历到目标行时,成功匹配到手机。
- 提取该行的“家庭住址”密文并进行 Base64 解码。
- 解码后的地址为:
江苏省....。
结论
家庭住址为:
江苏省....
第三问:重名统计
题目描述
在得到居民信息之后,领导让你统计一下居民信息中重名的数量,方便后续的工作开展。目标:统计出现重名次数出现最多的人的姓名以及出现的次数。
分析过程
- 数据提取同样基于
居民信息表.csv,需要对“姓名”列进行处理。 - 统计逻辑编写 Python 脚本:
- 遍历 CSV 文件,提取每一行的“姓名”字段。
- 对“姓名”字段进行 Base64 解码,获取明文姓名。
- 使用计数器(如
collections.Counter)统计每个姓名出现的次数。 - 找出出现次数最多的姓名及其计数。
- 统计结果
- 运行脚本后,统计结果显示出现次数最多的姓名是 …。
- 该姓名出现的次数为 7 次。
结论
重名最多的人及次数为:
...7
2.数据应急
数据应急 – 恢复被删合同文件 WriteUp
1. 题目分析
题目描述黑客删除了磁盘中的文件,需要从提供的磁盘镜像 disk.img 中恢复被删除的合同文件,并提交合同编号。
2. 解题过程
2.1 镜像分析
首先分析 disk.img 的文件系统。读取镜像的前 512 字节(引导扇区):
withopen('disk.img', 'rb') asf:
print(f.read(512))
输出显示包含 mkfs.fat 和 FAT16 字样,确认文件系统为 FAT16。
2.2 扫描删除文件
在 FAT16 文件系统中,被删除文件的目录项首字节会被标记为 0xE5。编写脚本扫描根目录区域,寻找扩展名为 PDF 的被删除文件。
关键参数计算:
- 每扇区字节数 (Bytes Per Sector): 512
- 保留扇区数 (Reserved Sectors): 32
- FAT 表数量 (Number of FATs): 2
- 每个 FAT 表扇区数 (Sectors Per FAT): 256
- 根目录项数 (Root Entries): 512
根目录起始偏移 = 保留扇区大小 + FAT 表大小$$ \text{RootOffset} = 32 \times 512 + 2 \times 256 \times 512 = 278528 $$
在根目录区域扫描发现如下目录项:e55f5f5f5f5f7e3150444620006e114a975b975b0000114a975be12af1200000
解析该目录项:
- 文件名:
?_____~1.PDF(首字节E5代表已删除) - 起始簇号 (Offset 0x1A):
0xE1 0x2A->0x2AE1(10977) - 文件大小 (Offset 0x1C):
0xF1 0x20 00 00->0x20F1(8433 字节)
2.3 恢复文件数据
根据起始簇号计算文件数据在磁盘中的物理偏移。数据区起始偏移 = 根目录起始偏移 + 根目录大小$$ \text{DataStart} = 278528 + (512 \times 32) = 294912 $$
簇大小 = 每簇扇区数 × 每扇区字节数 = $32 \times 512 = 16384$ 字节。
文件偏移 = 数据区起始偏移 + (起始簇号 – 2) × 簇大小$$ \text{FileOffset} = 294912 + (10977 – 2) \times 16384 = 180109312 $$
使用 Python 脚本从该偏移处读取 8433 字节,保存为 recovered.pdf。
2.4 分析 PDF 内容
尝试直接在 recovered.pdf 中搜索 “HT-” 字符串未果。使用文本编辑器查看 PDF 源码,发现内容被压缩和编码。流对象 (Stream Object) 使用了过滤器:/Filter [ /ASCII85Decode /FlateDecode ]
这意味着数据先经过 Flate (zlib) 压缩,然后经过 ASCII85 编码。
2.5 解码与提取
编写脚本对 PDF 中的流进行解码:
- 提取
stream和endstream之间的内容。 - 使用
base64.a85decode(Adobe 模式) 进行解码。 - 使用
zlib.decompress进行解压。
在解码后的第一个流中发现如下内容:(\000H\000T\000-\0002\0000\0002\0005\000-\0000\0000\0001\0002\0003\0004)
这是 PDF 中的文本字符串格式,对应的内容为:HT-2025-001234
3. 最终答案
合同编号为:HT-2025-001234
数据应急 – 读取加密内容 WriteUp
1. 题目分析
题目描述在恢复出被删除文件后,发现存在加密文件,但管理员忘记了密钥。需要通过技术手段绕过验证直接读取加密文件中的内容(密码本)。
2. 解题过程
2.1 发现并恢复 ZIP 文件
在第一问中扫描磁盘根目录时,除了发现被删除的 PDF 文件外,还发现了一个被删除的大型 ZIP 文件:IN-SE~1.ZIP (对应长文件名 WIN-SERVER-PC-20251202-122722.zip 的一部分),起始簇号 3,大小约 171MB。
使用脚本恢复该 ZIP 文件:
# 恢复逻辑同 PDF,起始簇号 3,大小 179782904 字节
恢复得到 recovered.zip。
2.2 分析 ZIP 内容
解压 recovered.zip,发现其中包含一个名为 WIN-SERVER-PC-20251202-122722.raw 的文件,大小为 2GB。
File: WIN-SERVER-PC-20251202-122722.raw
Size: 2147483648
根据文件名和大小判断,这可能是一个内存镜像或磁盘镜像。
2.3 分析 RAW 文件
对 WIN-SERVER-PC-20251202-122722.raw 进行分析,搜索文件签名。发现大量 BitLocker (-FVE-FS-) 和 TrueCrypt 签名,说明该镜像中包含加密卷。通常情况下,读取加密卷需要密钥。但题目提示“绕开验证直接读取”,且文件是内存镜像(或包含内存数据的系统镜像),这意味着解密后的数据可能以明文形式存在于内存中。
2.4 搜索敏感信息
直接在 WIN-SERVER-PC-20251202-122722.raw 文件中搜索关键词 flag{。
importre
pattern=re.compile(rb'flag\{.*?\}')
# ... 读取文件并搜索 ...
搜索结果:Found flag: flag{33c3789a36bb61beb6d4268cd7d13038}
2.5 获取密码本内容
找到的 flag 即为密码本中的内容。
3. 最终答案
密码本内容为:33c3789a36bb61beb6d4268cd7d13038
3.数据分析
数据分析 第一问 WriteUp
题目回顾
安全团队提取到疑似勒索程序(en.exe),该程序采用”混合加密机制”对 PDF 文档进行加密。若要恢复文档,必须从勒索程序中获取攻击者遗留的 RSA 私钥。题目要求找到私钥,并将私钥中 -----BEGIN PRIVATE KEY----- 之后的 32 位字符作为答案提交。
分析过程
1. 初步侦察
首先对 en.exe 进行基础的字符串分析。通过提取文件中的可打印字符串,发现了 PyInstaller、pyi-windows-manifest-filename 以及 _MEI 等特征字符串。这表明 en.exe 是一个使用 PyInstaller 打包的 Python 可执行文件。
2. 提取策略
PyInstaller 将 Python 脚本编译为字节码(.pyc)并与其他资源文件一起打包。这些内容通常被压缩存储(通常使用 zlib)。虽然可以使用 pyinstxtractor.py 等工具进行完整的解包,但为了快速定位文本形式的密钥文件,我们可以直接在二进制文件中搜索 zlib 压缩流并尝试解压。
3. 编写分析脚本
编写 Python 脚本 scan_zlib.py,其逻辑如下:
- 以二进制模式读取
en.exe。 - 遍历文件内容,寻找 zlib 头部特征(如
\x78\x01,\x78\x9c,\x78\xda)。 - 尝试从每个可能的头部位置进行解压。
- 在解压后的数据中搜索 PEM 格式私钥的头部标记
-----BEGIN PRIVATE KEY-----。
importzlib
importos
defscan_zlib(filename):
ifnotos.path.exists(filename):
print(f"File not found: {filename}")
return
withopen(filename, "rb") asf:
data=f.read()
# Common zlib headers
possible_headers= [b'\x78\x01', b'\x78\x9c', b'\x78\xda']
foriinrange(len(data)):
ifdata[i:i+2] inpossible_headers:
try:
decompressed=zlib.decompress(data[i:])
ifb"-----BEGIN PRIVATE KEY-----"indecompressed:
print(f"Found potential key in zlib stream at offset {i}")
print(decompressed.decode('utf-8'))
except:
pass
if__name__=="__main__":
scan_zlib("en.exe")
4. 运行结果
运行脚本后,成功在文件偏移量 5156720 处发现了一个 zlib 压缩块,解压后得到了完整的 RSA 私钥。
私钥内容片段:
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCt4TrETrlzU4NV
083rqT3XUun3NnxgPVVioX8tJZUH9rjs0bdTPTMk877seCIsJ98yj2VAhmGbviZ7
...
5. 提取答案
根据题目要求,提取 -----BEGIN PRIVATE KEY----- 之后的 32 位字符(忽略换行符,通常 PEM 格式头后紧接着就是 Base64 编码的数据)。
私钥数据第一行:MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCt4TrETrlzU4NV
截取前 32 位:MIIEvgIBADANBgkqhkiG9w0BAQEFAASC
最终答案
MIIEvgIBADANBgkqhkiG9w0BAQEFAASC
数据分析 第二问 WriteUp
题目回顾
在成功获得攻击者的 RSA 私钥后,需要解密被勒索的 PDF 文件。题目指定解密 0999_内部文档0999.pdf.enc,并计算解密后文件的 32 位小写 MD5 值作为答案。
分析过程
1. 逆向分析加密逻辑
在第一问中我们确认了 en.exe 是 PyInstaller 打包的程序。为了理解具体的加密流程,我们进一步提取并分析了其中的 Python 字节码/脚本资源。
通过解压 en.exe 中的 zlib 流,我们定位到了核心加密脚本(对应提取出的 stream_362697.bin)。通过分析其中的字符串和逻辑,我们发现了关键信息:
- 密钥存储方式:AES 密钥并非存储在每个加密文件的头部,而是统一加密后存储在名为
store.key的文件中。 - AES 密钥加密算法:使用 RSA 公钥加密生成的 AES 密钥,填充模式为 OAEP,哈希算法为 SHA256。
- 文件加密算法:使用 AES-256-ECB 模式,并使用 PKCS7 进行填充。
相关代码特征字符串:
store.key
OAEP
SHA256
AES-256-ECB
PKCS7
2. 解密流程
根据分析结果,制定解密步骤如下:
- 获取 AES 密钥:
- 读取
store.key文件内容。 - 使用第一问提取的
private.pem私钥。 - 使用
PKCS1_OAEP(SHA256) 算法解密store.key,得到原始 AES 密钥。
- 解密 PDF 文件:
- 读取
0999_内部文档0999.pdf.enc内容。 - 使用获取到的 AES 密钥,采用
AES.MODE_ECB模式进行解密。 - 去除 PKCS7 填充。
3. 解密脚本
编写 Python 脚本 decrypt_final.py 实现上述逻辑:
fromCrypto.PublicKeyimportRSA
fromCrypto.CipherimportPKCS1_OAEP
fromCrypto.CipherimportAES
fromCrypto.HashimportSHA256
fromCrypto.Util.Paddingimportunpad
importhashlib
defdecrypt_final():
# 1. 解密 AES 密钥
withopen("private.pem", "rb") asf:
private_key=RSA.import_key(f.read())
withopen("store.key", "rb") asf:
enc_aes_key=f.read()
# 使用 RSA-OAEP (SHA256) 解密
cipher_rsa=PKCS1_OAEP.new(private_key, hashAlgo=SHA256)
aes_key=cipher_rsa.decrypt(enc_aes_key)
print(f"AES Key decrypted: {aes_key.hex()}")
# 2. 解密 PDF 文件
enc_pdf_path="pdfs/0999_内部文档0999.pdf.enc"
withopen(enc_pdf_path, "rb") asf:
enc_content=f.read()
# 使用 AES-256-ECB 解密
cipher_aes=AES.new(aes_key, AES.MODE_ECB)
decrypted_padded=cipher_aes.decrypt(enc_content)
# 去除 PKCS7 填充
decrypted_content=unpad(decrypted_padded, AES.block_size)
output_path="0999_decrypted_final.pdf"
withopen(output_path, "wb") asf:
f.write(decrypted_content)
# 3. 计算 MD5
md5_hash=hashlib.md5(decrypted_content).hexdigest()
print(f"MD5: {md5_hash}")
if__name__=="__main__":
decrypt_final()
4. 运行结果
运行脚本后,成功解密出 AES 密钥和 PDF 文件。
- AES 密钥:
79d44c189fcba167411543dc258c9a7ebf58daec249c65214560da7fe5f964f1 - 解密文件 MD5:
52fd2cb4fc43eceb3c79233038bb5f42
答案
52fd2cb4fc43eceb3c79233038bb5f42
Question 3 WriteUp
题目解析
题目要求分析 999 份 PDF 文件,找出所有指向 非 veritytech.com 域名的 URL。需要提取完整 URL,按字典序升序排序,并计算其 32 位小写 MD5 值。
解题步骤
1. 批量解密 PDF
利用 Q2 中获得的 AES 密钥 2024_VerityTech_Sec_Key_#9988,编写脚本 decrypt_all.py 对所有 .enc 文件进行批量解密。
2. 提取 URL
编写脚本 scan_urls_v4.py 从解密后的 PDF 中提取 URL。在提取过程中遇到一个关键问题:PDF 文本提取时,长 URL 可能会被换行符 \n 截断(例如 https://api.veritytech.c\nom)。解决方案:在正则匹配前,先移除文本中的换行符。
3. 过滤与清洗
提取到的 URL 包含大量噪音,主要分为两类:
- 合法域名:
*.veritytech.com,需要排除。 - 截断噪音:由于 PDF 排版或提取算法的边缘情况,产生了一些看起来像 URL 但实际上是合法域名截断部分的字符串(例如
https://api是https://api.veritytech.com的前缀)。
过滤逻辑:
-
如果域名以
veritytech.com结尾,排除。 -
如果域名没有点号(
.),且是veritytech或常见子域名(如api,docs)的前缀,判定为噪音排除。 -
排除内部基础设施域名:
-
主机名(如
dev-db:3306)。 -
内部专用顶级域(如
.local,.internal)。 -
保留所有其他非
veritytech.com的外部域名(疑似钓鱼网站)。
4. 结果汇总
最终筛选出 11 个恶意/钓鱼 URL:
https://account-checker.xyz/loginhttps://security-review.veritytech-support.info/validatehttps://ver1tytech.com/resethttps://verify-account.veritytech-portal.xyz/authhttps://verify-id.top/sessionhttps://verify-veritytech.top/authhttps://veritytech-login-security.net/updatehttps://veritytech-security-check.xyz/verifyhttps://veritytech-support-alert.co/updatehttps://veritytech-update-alert.co/noticehttps://veritytech.com.io/login
5. 计算 MD5
将上述 URL 列表用逗号连接(无空格)并计算 MD5。字符串:https://account-checker.xyz/login,https://security-review.veritytech-support.info/validate,https://ver1tytech.com/reset,https://verify-account.veritytech-portal.xyz/auth,https://verify-id.top/session,https://verify-veritytech.top/auth,https://veritytech-login-security.net/update,https://veritytech-security-check.xyz/verify,https://veritytech-support-alert.co/update,https://veritytech-update-alert.co/notice,https://veritytech.com.io/login
MD5: 0a16f1ca5e8db1270074d0d39f6edeaf
最终答案
0a16f1ca5e8db1270074d0d39f6edeaf
4.数据审计
数据审计 – 第一问 Writeup
题目要求
根据题目提供的证书关键参数(params.csv),找到 id 为 285 的参数合成的证书,判断其可以解密哪个流量包(pcap.zip),并将该流量包名称的 MD5 值作为答案提交。
解题步骤
1. 获取关键参数
读取 params.csv 文件,查找 id 为 285 的行,获取 RSA 参数 p 和 q。
参数信息:
- id: 285
- p: 177264302295959185550899884811457697789837321132319354039496340545988969470422347313577084568610012957139649359576035974322283705879187577664768699213211347033624840318251940972496063336844685896882713624561971974788692556498019960846465311267474369690812099681875735569564330504277517754796899917257323134723
- q: 143990163909936129648804807321551478733567016733642335522156625973321506509458427490929508866189002322826874210961910641865602374675333206288577734876005828016379170951078934469472423840724164310343028554942665656763806178050620857070820746559094989518930589089970082522430002916286799917078785172333647028571
2. 计算模数 N
RSA 算法中,模数 $N = p \times q$。在 TLS 握手过程中,服务端发送的证书包含了公钥信息,其中就包含模数 $N$。因此,包含该证书的流量包中必然包含 $N$ 的二进制数据。
3. 流量包匹配
解压 pcap.zip 得到大量 pcap 文件。为了快速定位,我们不需要尝试解密所有包,只需搜索哪个 pcap 文件中包含了计算出的 $N$ 的字节序列。
匹配脚本逻辑:
- 计算 $N = p \times q$。
- 将 $N$ 转换为大端序字节串。
- 遍历所有 pcap 文件,读取文件内容。
- 检查 $N$ 的字节串是否存在于文件内容中。
4. 匹配结果
经过脚本搜索,发现文件 mAqY0WRHsV.pcap 包含该模数。
5. 生成答案
计算文件名的 MD5 值:
- 文件名:
mAqY0WRHsV.pcap - MD5:
1f5c34eab5696a300afff7452b7f7e6a
最终答案
1f5c34eab5696a300afff7452b7f7e6a
数据审计 – 第二问 Writeup
题目要求
根据题目对每个流量包进行解密,并得到明文。找到 “王梅” 的手机号,并将其 32 位小写 MD5 值作为答案提交。
解题步骤
1. 批量解密与搜索
由于流量包数量较多,且每个包对应不同的证书,我们编写脚本遍历所有 pcap 文件。对于每个 pcap 文件:
- 提取证书 Common Name 中的 ID。
- 根据 ID 从
params.csv获取 $p, q$ 生成私钥。 - 使用
tshark配合生成的私钥解密流量。 - 在解密后的数据中搜索 “…” 的相关编码。
2. 编码分析
在 HTTP 流量中,中文字符通常以 Unicode 转义序列的形式存在(如 \u738b\u6885),或者被进一步 Hex 编码。经过分析,我们在流量包 ZQYTMYb2ZY.pcap 中发现了如下 Hex 字符串:7b22757365726e616d65223a20225c75373338625c7536383835222c202270686f6e65223a20223133393330303739333635227d
3. 解码与提取
将上述 Hex 字符串解码为 ASCII 字符串:{"username": "\u738b\u6885", "phone": "13930079365"}
进一步解析 Unicode 转义:{"username": "...", "phone": "139...."}
成功找到 “…” 对应的手机号。
4. 生成答案
计算手机号 的 MD5 值:
- 手机号:.
- MD5:
5a4df03b5f1aaad3f465fc78a84b7101
最终答案
5a4df03b5f1aaad3f465fc78a84b7101
数据审计 – 第三问 Writeup
题目要求
系统使用 JWT 进行身份认证(Authorization 头部)。为了安全,密钥设置为用户姓名的拼音。题目要求统计有多少个账号进行了越权访问(即 JWT 中的身份信息与请求体中的内容不一致),并将越权账号数量的 MD5 值作为答案提交。
解题步骤
1. 批量解密流量
由于每个流量包对应不同的证书参数(params.csv),我们需要对每个 pcap 文件进行单独处理:
- 提取 ID:解析 pcap 文件中的 TLS Certificate 消息,从证书的 Common Name (CN) 字段中提取 ID(格式为
batch_{id}.example.com)。 - 生成私钥:根据提取的 ID,从
params.csv中查找对应的p和q,计算私钥参数并生成 PEM 格式的 RSA 私钥文件。 - 解密流量:使用
tshark配合生成的私钥,解密 TLS 流量,提取 HTTP 请求的Authorization头部和请求体(File Data)。
2. 身份核验
对提取到的数据进行分析:
- 解析 JWT:从
Authorization头部提取 Bearer Token,进行 Base64 解码获取 Payload 部分(无需验证签名,只需读取内容)。 - 解析请求体:解析 HTTP POST 请求的 JSON 数据。
- 对比信息:比较 JWT Payload 中的
username和phone与请求体中的username和phone是否一致。
3. 统计越权账号
遍历所有 pcap 文件后,发现以下 5 个流量包存在身份不一致的情况(越权访问):
- jFC0Edvnas.pcap: 用户 王丽娟
- pHpodYofLg.pcap: 用户 赵平
- qFX9ydkNoY.pcap: 用户 宋建平
- U8LyjJBxvY.pcap: 用户 魏云
- WYPfbs24cE.pcap: 用户 蔡旭
共计 5 个账号进行越权。
4. 生成答案
计算数量 5 的 MD5 值:
- 数字:
5 - MD5(32位小写):
e4da3b7fbbce2345d7772b0674a318d5
最终答案
e4da3b7fbbce2345d7772b0674a318d5
5.签到
填写调查问卷 flag{2989f956eb5f46ff}
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:赛查查 《第三届数信杯个人赛第二名WP》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论