Security
Headlines
HeadlinesLatestCVEs

Headline

CVE-2023-44469: Real-life OIDC Security (IV): Server-Side-Request-Forgery

A Server-Side Request Forgery issue in the OpenID Connect Issuer in LemonLDAP::NG before 2.17.1 allows authenticated remote attackers to send GET requests to arbitrary URLs through the request_uri authorization parameter. This is similar to CVE-2020-10770.

CVE
#vulnerability#web#amazon#red_hat#git#ldap#ssrf#pdf#aws#oauth#auth

This is the fourth post of a series on Single Sign-On and OpenID Connect 1.0 security. In this post, SSRF vulnerabilities that were discovered in popular OIDC implementations (Keycloak (CVE-2020-10770) and Amazon Cognito) are explained in detail.

The series consists of following posts:

  1. [Overview] Common Issue Patterns and Derived Security Considerations
  2. [Implementation] Login Confusion
  3. [Implementation] Injection of CRLF sequences
  4. [Implementation] SSRF issues in real-life OIDC implementations
  5. [Specification] Redirect URI Schemes
  6. [Specification] Reusable State parameter
  7. [Responsible Disclosure] Lessons learned during Responsible Disclosure of OIDC/OAuth related issues

As you can see, we structure this series in an [Overview], attacks with concrete examples categorized in [Implementation] and [Specification], and finally lessons learned during the [Responsible Disclosure]. Note that this post gives detailed insights into SSRF vulnerabilities that were encountered in real-life OpenID Connect implementations, namely Keycloak and Amazon Cognito.

Acknowledgment

We made the observations within this advisory during the execution of my master’s thesis on “Single Sign-On Security: Security Analysis of real-life OpenID Connect Implementations”. The thesis was written at the chair for network and data security of Ruhr University Bochum.

The advisors of my thesis are Dr.-Ing. Christian Mainka (@CheariX), Dr.-Ing. Vladislav Mladenov (@v_mladenov) and Prof. Dr. Jörg Schwenk (@JoergSchwenk). Huge “Thank you” for your continuous support! 🙂

Introduction

Server-Side-Request-Forgery (SSRF) is a web application vulnerability. If a malicious entity exploits such a vulnerability, “the attacker can abuse functionality on the server to read or update internal resources”, according to OWASP [1].

In the context of OpenID Connect, there are multiple known and previously discussed pitfalls that could enable SSRF vulnerabilities, e.g.:

  1. request_uri parameter: Fett et al. outlined in 2017 that the request_uri allows unauthenticated SSRF [3, Section III; A. 8)]. If this parameter is implemented, the Identity Provider is supposed to fetch a resource to obtain the Request Object. As a result, if the Identity Provider implements the request_uri parameter, an unauthenticated attacker can launch a SSRF attack against the victim Identity Provider.

  2. Backchannel Communication/Malicious Endpoints: In an OIDC scenario there is direct Server-to-Server communication. If the OpenID Connect Discovery is used, an Identity Provider can specify its endpoints that are used as the target of requests within genuine OpenID Connect flows. Therefore, a malicious Identity Provider could specify malicious endpoints as its OIDC endpoints during discovery, tricking a benign Service Provider into sending requests to unintended destinations. As pointed out by Mladenov and Mainka in [2], if there are no restrictions regarding the internal infrastructure or localhost, such a SSRF vulnerability can be used to “[…] (1.) gather information about the Intranet infrastructure of the Client, and (2.) disseminate attack vectors” [2].

Example 1: Unauthenticated SSRF in Keycloak (CVE-2020-10770)

Keycloak is an open-source Identity and Access Management Software (IAM) maintained by Red Hat. In addition, Keycloak is used as a base for Red Hat’s Red Hat Single Sign-On.

Attacker Model

The attacker model applied for the following attack is an unauthenticated web attacker model introduced by Barth et al. in 2008 [4]. In the following, the malicious entity targets a benign Identity Provider. The attacker’s objective is to gain access to internal hosts that are situated within the internal network; direct access to these hosts is restricted using a firewall.

Description

The request_uri is an optional parameter within the OpenID Connect Authentication Request that allows specifying an external URI where the Request Object can be found. Fett et al. discovered in 2017 [3, Section III; A. 8)] that, as the Identity Provider is supposed to request the external Request Object, this parameter can easily launch an SSRF attack against the Identity Provider.

The OpenID Connect Core specification defines the request_uri as an Authentication Request parameter that “[…] enables OpenID Connect requests to be passed by reference, rather than by value” [3, Section 6]. If a Service Provider uses this parameter, the Identity Provider retrieves the Request Object “[…] from the resource at the specified URL” [5, Section 6.2].

The Identity Provider could restrict allowed URLs by allowing the Service Provider to specify the request_uris parameter that is an “[…] array of request_uri values […]”, within OpenID Connect Dynamic Client Registration [6, Section 2]. If the OpenID Connect Dynamic Client Registration is used, the Identity Provider can require the Service Provider to “[…] pre-register request_uri values using the request_uris parameter […]” [5, Section 6.2]. Thus, only if OpenID Connect is implemented with the Registration Extension, there is a mitigation hint given by the specification.

Keycloak supports using a Request Object that is referenced externally. The “Fine Grained OpenID Connect Configuration” for a specific client allows specifying the following values for the option “Request Object Required”:

  • Not required (default)
  • request or request_uri
  • request only
  • request_uri only

As one can observe, if an OpenID Connect Client is set-up with default settings, the default value for this option is “Not required”. There is no option to do not support a Request Object at all, as “not required” means submitting the request object is optional, but if you submit one, it is used by Keycloak. Additionally, there is no option to manually define the request_uris parameter during manual client registration. Finally, using the default configuration, Keycloak does not require a Request Object, but supports passing the request_uri parameter with an Authentication Request. As a result, Keycloak is in its default configuration for Clients vulnerable to the SSRF attack Fett et al. described in 2017 [3, Section III; A. 8)].

Proof-of-Concept

A straight forward PoC to trigger the SSRF issue is given with the following URL (Authentication Response): https://keycloak.local/auth/realms/master/protocol/openid-connect/auth?scope=openid&response_type=code&redirect_uri=[Valid-RedirectURI]&state=aaaa&nonce=bbbb&client_id=[Valid-ClientID]&request_uri=http://127.0.0.1:1234

Thus, to launch the SSRF in a real-life scenario, an attacker would obtain an Authentication Request (to get the valid client_id and redirect_uri).

If the attacker then sends the Authentication Response GET request including valid client_id and redirect_uri, Keycloak sends a GET request to 127.0.0.1:1234 to fetch the Request Object resulting in blind SSRF.

By measuring the response time, a malicious actor may additionally perform a port scan of localhost or internally accessible hosts. The following ports are open on localhost:

  • 8080: Open, Keycloak, 1087 Bytes as default response
  • 8081: Open, Mailslurper, 4086 Bytes as default response
  • 5555: Closed
  • 5556: Closed

Demo: An example using the Timeinator Burp Plugin [7] is presented below:

Keycloak responds significantly faster if the port is closed in our test. Thus, the Blind SSRF enables an attacker to learn about the internal network structure.

Recommendation

To mitigate the described issue, the request_uri should be disabled in Keycloak’s default Client configuration. Furthermore, localhost and private IPs should be forbidden as request_uri, unless explicitly enabled by an administrative user with high privileges. Finally, the request_uris whitelist should also be available and enforced during manual configuration to restrict the request_uri parameter.

Responsible Disclosure

  • 2020-04-29: Initial Report to Red Hat via https://issues.redhat.com/projects/KEYCLOAK/.
  • 2020-06-05: Red Hat triages the submitted report.
  • 2020-06-11: CVE-2020-10770 is assigned.
  • 2020-10-16: Red Hat is informed that this post is scheduled for 2020-11-10.
  • 2020-10-19: Red Hat approves to disclose this post on the described vulnerability:

Thank you for informing about this. Since this is a Moderate impact flaw, we have 365 calendar days to publish the fix after the issue has been made public so should not be a problem publishing it on 2020-11-10.

- Internal Comment by Red Hat Employee

According to the internal ticket status, Red Hat plans to resolve this issue with the upcoming major version v12 of Keycloak.

Example 2: SSRF in Amazon Cognito (AWS)

Similar to Keycloak, Amazon Cognito implements Identity and Access Management (IAM). But in contrast Amazon Cognito is a hosted service as part of the AWS family instead of a self-hosted software.

The following vulnerability was resolved by the Amazon Cognito team in August 2020. Detailed information on the Responsible Disclosure and Remediation Process will be discussed in the following.

Attacker Model

The attacker model that is applied in the following is a malicious administrative user. The impact of attacks under this attacker model is highly conditional, but in this case, as Amazon Cognito is a hosted service, administrative users only have access to the configuration interface. The underlying infrastructure in Amazon’s hosted environment should not be accessible to external users.

Alternatively, a malicious Identity Provider could be considered as the attacker model. The actual configuration is fetched using OpenID Connect Discovery from the Identity Provider’s Configuration Endpoint so that the endpoints are controlled by the Identity Provider.

Description

Amazon Cognito allows specifying custom OpenID Connect Identity Providers for user pools. Within the configuration of an Identity Provider, an administrative user could choose to “Run discovery”, triggering an OpenID Connect Discovery that requests the Configuration Endpoint of the Identity Provider. Amazon Cognito did not restrict the endpoints observed using OpenID Connect Discovery regarding internal IP addresses or localhost so that SSRF to the local network and localhost was possible.

A malicious actor could utilize this to perform port scans or send nearly arbitrary HTTP requests to hosts that are intentionally not exposed to the internet. An example Configuration Response is presented in the following:

{
    "issuer":"https://example.com/",
    "authorization_endpoint":"https://example.com/auth",
    "token_endpoint":"http://127.0.0.1:22",
    "userinfo_endpoint":"http://127.0.0.1:22",
    "jwks_uri":"https://example.com/jwks",
    "registration_endpoint":"https://example.com/register",
    "response_types_supported":["code","token id_token"],
    "subject_types_supported":["public","pairwise"],
    "id_token_signing_alg_values_supported":["RS256"]
}

Portscan

The following error messages could be used to determine which ports are internally open on localhost, as the error message sent to the redirect_uri (https://a.com/cb?error_description=[ERROR]&error=invalid_request) differed depending on the underlying Transmission Control Protocol (TCP) connection. If the connection could not be established or Amazon Cognito received an HTTP error code in response to the Token Request, the following error messages were sent to the Identity Provider:

  • If the Token Endpoint was specified as “http://localhost:22”, the error message was “Connection reset”, so that we could assume Port 22 to be open.
  • If the Token Endpoint was specified as “http://localhost:20”, the error message was “Connect to 127.0.0.1:20 [/127.0.0.1] failed: Connection refused”, so that we could assume Port 20 to be closed.
  • If the Token Endpoint was specified as “http://test123.ngrok.io”, the error message was “test Error – 502 error getting token”, so that we could assume that there was an HTTP request to the specified target, but the web server responded with HTTP Error Code 502.

Arbitrary HTTP requests

Besides the feedback an attacker received that enabled him to determine the connection’s status, there was no information on the actual response to the HTTP request. Thus, this gadget could be considered as blind SSRF to the local network. The attacker had no direct feedback but could still control a GET request (UserInfo Request) and a POST request (Token Request) regarding scheme (http or https), host (potentially localhost or internal IP), path and query parameters.

Combining port scan and blind SSRF, a malicious administrative user or malicious Identity Provider could:

  1. Gather information: Which ports are open on localhost? Are there other hosts accessible? If HTTP error codes are reflected, which web service is running at this destination (fingerprinting)?
  2. If a service could be identified: Use blind SSRF to target an internally accessible service directly.

Recommendation

A blacklist is never perfect. Nevertheless, Amazon Cognito should introduce a restriction for internal IPs and localhost as OpenID Connect endpoints, as there is no legitimate use-case in the context of a hosted service.

The fix that was applied in late August 2020 mitigates the above described vulnerability.

Responsible Disclosure

Mitigations for the described issues were introduced by AWS / Amazon Cognito soon after we reported the issue on 2020-08-12.

  • 2020-08-12: Initial report to [email protected].
  • 2020-08-19: Call with AWS Security Team and Amazon Cognito Developers.
  • 2020-08-??: A fix is applied at the end of August 2020. As Amazon Cognito is a hosted service, we could not determine the exact date.
  • 2020-10-21: AWS Security Team acknowledges that the blog post is scheduled for 2020-11-10 and offers feedback for the draft prior to publication:

Thanks again for bringing your security concern to our attention. We greatly appreciate and encourage reports from the security community.

I understand you wish to do a write up on this - would you be interested in sharing your draft with us before publishing so we may provide any assistance and feedback?

  • 2020-11-05: After providing an initial draft, the AWS Security team would like to explicitly outline that the described vulnerability was mitigated shortly after we reported it responsibly. Thank you for your feedback!

References

[1] https://owasp.org/www-community/attacks/Server_Side_Request_Forgery
[2] https://www.nds.ruhr-uni-bochum.de/media/ei/veroeffentlichungen/2017/01/13/OIDCSecurity_1.pdf
[3] https://dl.acm.org/doi/10.1145/2976749.2978385
[4] https://www.adambarth.com/papers/2008/barth-jackson-mitchell.pdf
[5] https://openid.net/specs/openid-connect-core-1_0.html
[6] https://openid.net/specs/openid-connect-registration-1_0.html
[7] https://github.com/FSecureLABS/timeinator

Thank you for reading this post! If you have any feedback, Feel free to reach out via Mastodon, Twitter or LinkedIn. 👨‍💻

You can directly tweet about this post using this link. 🤓

Special thanks to Dr.-Ing. Christian Mainka (@CheariX), Dr.-Ing. Vladislav Mladenov (@v_mladenov), Louis Jannett (@iphoneintosh) and the AWS Security / Amazon Cognito Development Team for your feedback on this post prior to publication! 🙂

  • OpenID Connect
  • Keycloak
  • AWS
  • Amazon Cognito

Related news

CVE-2023-28069: DSA-2022-258: Dell Streaming Data Platform Security Update for Multiple Third-Party Component Vulnerabilities

Dell Streaming Data Platform prior to 1.4 contains Open Redirect vulnerability. An attacker with privileges same as a legitimate user can phish the legitimate the user to redirect to malicious website leading to information disclosure and launch of phishing attacks.

CVE-2020-10770: Invalid Bug ID

A flaw was found in Keycloak before 13.0.0, where it is possible to force the server to call out an unverified URL using the OIDC parameter request_uri. This flaw allows an attacker to use this parameter to execute a Server-side request forgery (SSRF) attack.

CVE: Latest News

CVE-2023-50976: Transactions API Authorization by oleiman · Pull Request #14969 · redpanda-data/redpanda
CVE-2023-6905
CVE-2023-6903
CVE-2023-6904
CVE-2023-3907