攻击面
1.使请求拦截工具(Charles等)处于打开状态
2.使用管理员账户登录应用程序。
3.在账号列表的搜索框中输入普通用户,查询普通用户信息。
4.选择用户搜索结果部分中的普通用户 链接。
5.检查拦截的请求并查看 cookie 包含loggedIn、role 和 jwt 值。提交请求并注意可以看到 普通用户 的帐户信息。角色现在的值为Administrator
6.使用普通用户 登录应用程序。
7.在搜索框中输入管理员,然后选择“搜索”按钮。
8.检查拦截的请求并查看角色和 jwt 的值已更改:角色现在的值为User。
9.从 cookie 复制 jwt 值并在 jwt.io 对其进行解码,以确认有效负载中的角色属性也具有“User”值。
10.尝试通过单击 管理员 链接来查看 管理员 的帐户,并确认您收到“访问被拒绝:需要管理员访问”错误消息。
11.返回搜索页面并再次搜索管理员。这次,点击管理员链接后,通过将cookie更改为role=Administrator来利用该漏洞;而不是角色=用户;并验证您现在是否能够看到 管理员 的帐户信息。
修复
1.打开服务端代码 2.通过从解码的 JWT(而不是 cookie)中提取角色来修复漏洞。 修改前
def account_lookup(session):
user_id = session["user_id"]
cookies = session["cookies"]
decoded_jwt = session["decoded_jwt"]
username = decoded_jwt["username"]
current_users_id = get_user_id(username)
if not user_exists(username):
raise Exception("Bad Request")
if int(current_users_id) == int(user_id):
return get_account(user_id)
if not cookies.get("role") == "Administrator":
raise Exception("Access Denied: Administrator Access Required")
return get_account(user_id)
修改后
def account_lookup(session):
user_id = session["user_id"]
cookies = session["cookies"]
decoded_jwt = session["decoded_jwt"]
username = decoded_jwt["username"]
current_users_id = get_user_id(username)
if not user_exists(username):
raise Exception("Bad Request")
if int(current_users_id) == int(user_id):
return get_account(user_id)
if not decoded_jwt["role"] == "Administrator":
raise Exception("Access Denied: Administrator Access Required")
return get_account(user_id)