OAuth学习 下
OAuth 2.0 中的 State 参数作用解析State 参数防御 CSRF 攻击State参数在 OAuth 2.0 框架中用于防止CSRF跨站请求伪造攻击。CSRF 攻击指攻击者诱导用户在已登录的 Web 应用上执行未授权操作。在 OAuth 的场景下CSRF 攻击可能导致敏感资源被非法获取攻击者可通过劫持 OAuth 流程实现未授权访问。State 参数通过维护授权流程的完整性有效降低此类风险。State 参数机制与验证流程State 参数是客户端应用在授权请求中附带的任意字符串。授权服务器在重定向用户回客户端时会一同返回 state 参数。客户端收到响应后需验证返回的 state 参数是否与最初发送的参数一致。只有验证通过才能确保此次响应是合法的 OAuth 流程延续而非CSRF攻击造成的。State 参数弱或缺失的风险若 state 参数缺失或易预测如使用静态值 state 或简单的序号攻击者可利用漏洞发起 OAuth 流程指定恶意重定向URI。用户完成认证与授权后授权服务器会将授权码重定向到攻击者控制的URI造成安全隐患。实操场景举例以下为攻击者视角的演示仅供安全学习使用。使用链接 http://mycontacts.thm:8080/csrf/index.php 以及凭据 attacker:attacker 登录网站。登录后你会看到一个页面该页面允许你将联系人同步到 CoffeeShopApp 账户。点击“Sync Contacts”后会跳回到同步页面。URL 分析与授权流程原始 URLhttp://coffee.thm:8000/accounts/login/?next/o/authorize/%3Fresponse_type%3Dcode%26client_id%3Dkwoy5pKgHOn0bJPNYuPdUL2du8aboMX1n9h9C0PN%26redirect_uri%3Dhttp%253A%252F%252Fmycontacts.thm%253A8080%252Fcsrf%252Fcallbackcsrf.php解析流程第一层登录地址http://coffee.thm:8000/accounts/login/进入 Coffee 登录页面。参数说明?next...登录成功后自动跳转到 next 参数指定的地址。next 参数解码后/o/authorize/?response_typecodeclient_idkwoy5pKgHOn0bJPNYuPdUL2du8aboMX1n9h9C0PNredirect_urihttp%3A%2F%2Fmycontacts.thm:8080%2Fcsrf%2Fcallbackcsrf.phpredirect_uri 再次解码后http://mycontacts.thm:8080/csrf/callbackcsrf.php完整授权流程打开 Coffee 登录页用户登录 Coffee登录成功后进入 /o/authorize/Coffee 生成 authorization codeCoffee 把 code 发送到 mycontacts 的 callbackcsrf.php关键参数说明response_typecode请求授权码client_idkwoy5pKgHOn0bJPNYuPdUL2du8aboMX1n9h9C0PN申请授权的客户端应用ContactApp / mycontactsredirect_urihttp://mycontacts.thm:8080/csrf/callbackcsrf.php授权完成后回调地址安全隐患分析本题安全问题并不在于 redirect_uri 被篡改而是缺少 state 参数正常 OAuth 授权请求应包含state随机值如/o/authorize/?response_typecodeclient_id...redirect_uri...stateabc123random但该 URL 缺少state风险客户端无法判断 callback 是否为自己发起的授权流程。攻击流程举例攻击者先获取自己的 code诱导 victim 访问http://mycontacts.thm:8080/csrf/callbackcsrf.php?code攻击者的codevictim 的 mycontacts 会误以为这是自己授权回来的 code结果是 victim 的 mycontacts 账号绑定了攻击者的 Coffee 账号一旦账户同步完成所有联系人信息都会转移到攻击者账户。授权码获取与拦截攻击者可通过 Burp Suite 等工具拦截授权过程获得授权码。我们提供了一个授权链接http://coffee.thm:8000/o/authorize/?response_typecodeclient_idkwoy5pKgHOn0bJPNYuPdUL2du8aboMX1n9h9C0PNredirect_urihttp://coffee.thm:8000/oauthdemo/callbackforcsrf/通过该链接可直接获得授权码无需完成完整 OAuth 流程。示例代码def oauth_logincsrf(request): app Application.objects.get(nameContactApp) redirect_uri request.POST.get(redirect_uri, http://coffee.thm/csrf/callbackcsrf.php) authorization_url ( fhttp://coffee.thm:8000/o/authorize/?client_id{app.client_id}response_typecoderedirect_uri{redirect_uri} ) return redirect(authorization_url)def oauth_callbackflagcsrf(request): code request.GET.get(code) if not code: return JsonResponse({error: missing_code, details: Missing code parameter.}, status400) if code: return JsonResponse({code: code, Payload: http://coffee.thm/csrf/callbackcsrf.php?codecode}, status400)访问上述链接使用凭据 attacker:tesla123 获得授权码。响应中的 URL 参数Payload即为攻击用数据请复制其值用于后续攻击。发起攻击流程 Launching the Attack攻击者获得授权码后准备 CSRF 载荷。例如向受害者发送如下链接http://bistro.thm:8080/csrf/callbackcsrf.php?codexxxxxxxx 为攻击者授权码受害者点击链接后攻击者的 CoffeeShopApp OAuth 账户会与受害者账户关联受害者的联系人信息被转移到攻击者账户。照此操作即可拿到 flag。为什么直接拿到 flag你可能会疑惑为什么如此容易就获得 flag下面详细解析身份与系统划分身份attacker攻击者victim受害者系统coffee.thmOAuth 授权服务器mycontacts.thm联系人同步应用正常功能流程mycontacts 网站功能同步 CoffeeShopApp 联系人到 mycontacts正常流程victim 登录 mycontactsvictim 点击 Sync Contactsvictim 跳转至 coffee.thm 登录/授权coffee 返回 victim 的 codemycontacts 用 code 换 tokenmycontacts 同步 victim 的联系人攻击流程攻击者目标让 victim 的 mycontacts 账号绑定/同步 attacker 的 Coffee 账号步骤攻击者用自己的 Coffee 账号获取 codeattacker_code构造链接http://mycontacts.thm:8080/csrf/callbackcsrf.php?codeattacker_code诱导 victim 在已登录 mycontacts 状态下访问该链接攻击为何成功因为 OAuth 请求缺少 state 参数state 的作用让 mycontacts 记住回调是否为当前用户自己发起的没有 statemycontacts 无法判断 code 来源误以为是 victim 自己授权回来的 code用该 code 换 token实际获得的是 attacker 的 Coffee token最终victim 的 mycontacts 账号与 attacker 的 Coffee 账号关联为什么“一下就拿到 flag”靶场用 flag 直接表示最终影响一旦 victim 执行带 attacker_code 的链接系统判定 CSRF 成功返回 flag现实中的影响可能包括受害者账号被绑定到攻击者第三方账号攻击者可通过 OAuth 登录受害者账户受害者数据被同步到攻击者账户账户关联关系被篡改