前言
前端加密是很目前网站非常常见的一种形式,相对于明文传输的数据,我们可以很简单的就可以爆破,但是密文传输,又该如何解决呢?常见的场景如下
AES 固定 key
首先我们需要简单了解一下 AES 加密
对称加密:
对称加密意味着加密和解密使用的是同一个密钥。在加密过程中,发送方和接收方使用相同的密钥来加密和解密数据。
直接举个例子容易理解,我们不需要在意具体是怎么计算的,我们只需要知道原理
假设你有一段文字 "HELLO",你使用一个密钥(比如 "1234567890abcdef"),将这个文字加密后变成了密文,只有拥有相同密钥的人才能解密它,得到 "HELLO" 这个明文。
实际例子
一个登录页面,我们选择 AES 固定 key
然后我们给 js 代码下个断点
得到关键部分
const jsonData = JSON.stringify(formData); const key = CryptoJS.enc.Utf8.parse("1234567890123456"); const iv = CryptoJS.enc.Utf8.parse("1234567890123456"); const encrypted = CryptoJS.AES.encrypt(jsonData, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }) .toString(); const params = `encryptedData=${encodeURIComponent(encrypted)}`; fetch(url, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded; charset=utf-8" }, body: params }) .then(response => response.json()) .then(data => { if (data.success) { alert("登录成功"); window.location.href = "success.html"; } else { alert("用户名或密码错误"); } }) .catch(error => { console.error("请求错误:", error); }); closeModal();}
这就是一个典型的固定 key 传输数据,得到的内容如下
POST /encrypt/aes.php HTTP/1.1Host: qianduan:7952Content-Length: 84User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36Content-Type: application/x-www-form-urlencoded; charset=utf-8Accept: */*Origin: http://qianduan:7952Referer: http://qianduan:7952/easy.phpAccept-Encoding: gzip, deflate, brAccept-Language: zh-CN,zh;q=0.9Cookie: PHPSESSID=8l013iet6fdujht6mblfj2o1seConnection: keep-aliveencryptedData=nArXfVdnoe67UzojAPP2X%2B6qSiznLMBAI3a5Bi%2BzlNxdbZ%2FOS8HQ6QCw6cm3stZk
我们如果要爆破等操作,需要知道加密逻辑
key 都告诉了,使用 autoDecoder 工具即可
需要进行一个基础的配置
至少测试能够解密成功
我们随便抓包试一试
原始请求
然后解密后
响应包我们先不需要管,可以看到是可以解密成功的,我们直接发生爆破模块开始爆破
因为密码就是 123456,这里节约时间字典随便加几个就 ok
然后我们看看 123456响应
发现成功
AES 服务端获取 Key
这次不再是固定的 key 了
然后还是一样的步骤,查查前端的 js 代码
async function fetchAndSendDataAes(url) { let aesKey, aesIv; try { const response = await fetch("encrypt/server_generate_key.php"); const data = await response.json(); aesKey = CryptoJS.enc.Base64.parse(data.aes_key); aesIv = CryptoJS.enc.Base64.parse(data.aes_iv); } catch (error) { console.error("获取 AES 密钥失败:", error); alert("无法获取 AES 密钥,请刷新页面重试"); return; } const formData = { username: document.getElementById("username") .value, password: document.getElementById("password") .value }; const jsonData = JSON.stringify(formData); const encryptedData = CryptoJS.AES.encrypt(jsonData, aesKey, { iv: aesIv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }) .toString(); fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ encryptedData: encryptedData }) }) .then(response => response.json()) .then(data => { if (data.success) { alert("登录成功"); window.location.href = "success.html"; } else { alert("用户名或密码错误"); } }) .catch(error => console.error("请求错误:", error)); closeModal();}
关键点在于我们的 key 是从 fetch("encrypt/server_generate_key.php")获取的
但是问题出现在从服务端获取的 key 和 iv 是不变的
然后抓个包看看格式
POST /encrypt/aesserver.php HTTP/1.1Host: qianduan:7952Content-Length: 84User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36Content-Type: application/jsonAccept: */*Origin: http://qianduan:7952Referer: http://qianduan:7952/easy.phpAccept-Encoding: gzip, deflate, brAccept-Language: zh-CN,zh;q=0.9Cookie: PHPSESSID=8l013iet6fdujht6mblfj2o1seConnection: keep-alive{"encryptedData":"/TU3Mh8yKqNBcTcVGqXTSwSz0T0/lmSAzTbJg7HWOSBsOhH4mVxgnoP6x6oUd5Mu"}
首先还是配置我们的工具,正则匹配需要修改一下
"encryptedData":"(.*)"
得能够提取出来
然后修改 key
然后我们去重发器解密看看
成功解密,这里就不爆破了
RSA 加密
RSA 加密是一种非对称加密技术,它广泛用于数据加密和数字签名。RSA 加密的基本特点是:使用一对密钥——公钥(公开)和私钥(保密)
一样的我们先来看看前端的逻辑
function sendEncryptedDataRSA(url) { const publicKey = `-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRvA7giwinEkaTYllDYCkzujviNH+up0XAKXQot8RixKGpB7nr8AdidEvuo+wVCxZwDK3hlcRGrrqt0Gxqwc11btlMDSj92Mr3xSaJcshZU8kfj325L8DRh9jpruphHBfh955ihvbednGAvOHOrz3Qy3CbocDbsNeCwNpRxwjIdQIDAQAB-----END PUBLIC KEY----- `; const username = document.getElementById("username").value; const password = document.getElementById("password").value; const dataPacket = { username: username, password: password }; const dataString = JSON.stringify(dataPacket); const encryptor = new JSEncrypt(); encryptor.setPublicKey(publicKey); const encryptedData = encryptor.encrypt(dataString); if (!encryptedData) { alert("加密失败,请检查公钥是否正确"); return; } const formData = new URLSearchParams(); formData.append('data', encryptedData); fetch(url, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: formData.toString() }) .then(response => response.json()) .then(data => { if (data.success) { alert("登录成功"); window.location.href = "success.html"; } else { alert(data.error || "用户名或密码错误"); } }) .catch(error => console.error("请求错误:", error)); closeModal();}
可以看到是给出了公钥的,如果我们有公钥那只能加密,是不能解密的
但是我们得知道明文的形式
问问 GPT
可能是这样的,如果会 js 调试的话还可以调试
大概也就是这样
我们发生的是加密数据,所以解密我们目前并不需要关心,配置
然后我们把加密后的数据发生过去
成功
然后发送明文数据实现自动的加密
参考https://github.com/f0ng/autoDecoder/blob/main/FAQ.md
https://github.com/SwagXz/encrypt-labs
原文始发于微信公众号(蓝云Sec):前端加密对抗常见场景突破
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论