This is the first post of a series on Single Sign-On and OpenID Connect 1.0 security. This post presents a high-level overview of observed issue patterns during my research on real-life OIDC security and proposes additions to the specification’s security considerations.
The series consists of following posts:
- [Overview] Common Issue Patterns and Derived Security Considerations
- [Implementation] Login Confusion
- [Implementation] Injection of CRLF sequences
- [Implementation] SSRF issues in real-life OIDC implementations
- [Specification] Redirect URI Schemes
- [Specification] Reusable State parameter
- [Responsible Disclosure] Lessons learned during Responsible Disclosure of OIDC/OAuth related issues
As you can see, the series is structured in an [Overview], attacks with concrete examples categorized as [Implementation] flaws and [Specification] flaws, and finally lessons learned during the [Responsible Disclosure].
Note that this post describes the overall patterns and considerations derived during my research. The following posts in this series will give detailed examples of vulnerabilities that were found in real-life OpenID Connect implementations.
We made the observations within this advisory during the research for 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! 🙂
This post outlines the lessons learned during the research on the security of real-life OpenID Connect implementations.
We presume basic knowledge of OpenID Connect 1.0 and OAuth 2.0 for this post.
First, we outline a high-level overview of the selection criteria. Afterward, we describe patterns that were regularly observed during the analysis of real-life OpenID Connect Service Provider and Identity Provider implementations.
Finally, proposals for adjusted security considerations regarding the OpenID Connect specification are derived.
High-Level Setup and Selection of Implementations
During the analysis, we evaluated OIDC Identity Provider and Service Provider implementations regarding a defined set of assertions, based on the specification’s security considerations [2, Section 16] and the OAuth 2.0 Security Best Current Practices . In doing so, we analyzed self-hosted software and hosted services. For Service Providers, we considered the ability to configure custom Identity Providers as mandatory.
The following software and services were analyzed:
Derived Issue Patterns
In the following, we outline seven issue patterns that we derived within our test-set.
Reminder: This post aims to give an overview. We discuss novel patterns and the most relevant observations in detail in dedicated posts.
Pattern 1: Redirect URI Schemes
The OpenID Connect Core specification is quite vague regarding allowed schemes for
redirect_uri values, see [2, Section 126.96.36.199]:
REQUIRED. Redirection URI to which the response will be sent. This URI MUST exactly match one of the Redirection URI values for the Client pre-registered at the OpenID Provider, with the matching performed as described in Section 6.2.1 of [RFC3986] (Simple String Comparison). When using this flow, the Redirection URI SHOULD use the https scheme; however, it MAY use the http scheme, provided that the Client Type is confidential, as defined in Section 2.1 of OAuth 2.0, and provided the OP allows the use of http Redirection URIs in this case. The Redirection URI MAY use an alternate scheme, such as one that is intended to identify a callback into a native application.
We observed that multiple Identity Providers support pre-registering
Additionally, the specification defined the
redirect_uri vague because it had native clients in mind. There are very few legitimate use-cases for these schemes as
redirect_uri values in OpenID Connect setups.
Pattern 2: Server-Side-Request-Forgery
Multiple Identity and Service Provider implementations were vulnerable to different types of Server-Side Request Forgery (SSRF) vulnerabilities.
The Identity Provider’s
request_uri parameter is already known to be vulnerable for SSRF by design since 2017 [4, Section III;A. 8)]. Notably, this vulnerability could be exploited by any unauthenticated user.
In 2017, Mladenov and Mainka pointed out [5, Section 2.1.2] that a malicious Discovery Service could be used to launch a SSRF attack against a Service Provider. Thus, the attacker can use SSRF for port scans or for retrieving data.
Additionally, having access to the endpoint configuration, administrative users could launch SSRF attacks on the Service Provider by design. Depending on the actual setup, this yields to severe security implications, especially considering hosted and cloud services.
Even though these issues were theoretically discussed earlier, SSRF to private IPs or localhost was a common and serious issue among our test-set. The blog post about SSRF issues can be found here.
Pattern 3: TLS Enforcement
The OpenID Connect Core specification already enforces TLS for communication with Authentication, Token, and UserInfo Endpoint, so does the OpenID Connect Dynamic Client Registration regarding the Client Configuration Endpoint. Nevertheless, most of the analyzed implementations allowed performing the discovery using unencrypted communication or allowed to specify OpenID Connect endpoints using HTTP without TLS.
Pattern 4: Leakage via Error Pages
Error messages and pages need extra attention. We discovered that multiple Service Provider implementations presented error pages as a direct response to Authentication Responses [2, Section 188.8.131.52.]. As a result, this page’s GET parameters include OpenID Connect values like
code. External resources like images, scripts, styles, or links to external resources on can be on any endpoint. In these cases, the attacker can retrieve sensitive information, including OpenID Connect parameters, in query parameters or the
Pattern 5: CSRF
The Service Provider’s Initiate Login Endpoint implements Login Cross-Site-Request-Forgery (CSRF) by design and per specification [2, Section 4.]. This behavior is well known and was previously discussed [4, Section III; A. 7)].
Besides this endpoint, we observed non-normative endpoints that start an external OpenID Connect login without CSRF protection as well. If the
state is correctly validated, these endpoints still allow to log in a victim End-User into her own account ("Login CSRF").
If there are additional non-normative parameters that indicate where the End-User should be redirected to after successful authentication (i.e., “next”, “nextUrl”, …) and these parameters allow specifying the
Login Initiation Endpoint or non-normative endpoints that start external OIDC login flows, Login Confusion attacks are possible. Technical details for this novel attack are presented in this post.
Pattern 6: State parameter handling
state parameter handling at the Service Provider’s Redirection Endpoint showed multiple more common issues. Some of the analyzed implementations did not handle the unexpected behavior of not receiving a
state within the Authentication Response if it was present within the Authentication Request. As a result, unhandled exceptions occurred. Depending on the actual implementation, this may lead to sensitive information disclosure or availability issues.
Further, multiple implementations correctly bound the
state to the user session. Still, they failed to make it one-time-usable, increasing the attack surface for token-reuse and Denial-of-Service Amplification attacks (we give the technical details behind this attack in a future blog post).
Service Providers often treat contents provided by Identity Providers as trustworthy. In our research, we show that this behavior in general yields injection issues (previously outlined as “Injection Attacks” by Mainka et al. in [5, Section 2.1.3]).
Striking among the test-set were CRLF-related issues, as missing sanitization can lead to HTTP header injections in Service Provider initiated requests and injections to application log files. These specific issues are discussed in this post.
Derived OpenID Connect Security Considerations
In addition to previously known security considerations [2, Section 16.], it has been shown that the following aspects need extra attention. Some of these considerations have been made earlier but with a less severe indication. In terms of RFCs and specifications, this would mean that a “MAY” or “SHOULD” would become a “MUST”.
- The specification needs to be tightened regarding the
- The Identity Provider SHOULD restrict allowed
request_uri values by allowing the Service Provider to specify the
request_uris parameter that is an “[…] array of request_uri values […]”, at registration [6, Section 2.].
Currently, only 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 […]” [2, Section 6.2.].
This registration should be moved from the Registration Extension to the Core Specification.
- In the context of OpenID Connect, Identity and Service Providers SHOULD globally restrict outgoing HTTP requests (“backchannel communication”) to localhost and private IPs [7, Section 3.]. There MAY be a configurable option to allow these connections which is only accessible for high privileged users. Further, error messages that are returned in case an OpenID Connect request fails MUST NOT include connection-specific details that could give an attacker information on the underlying transport layer (for instance error messages that indicate if a TCP connection was refused or reset).
- As the Specification already outlines, for instance in [6, Section 7.2.], OpenID Connect Service and Identity Providers MUST support and MUST use TLS for communication with the Configuration, Token and UserInfo Endpoint.
- Error messages SHOULD not be shown as a direct response to erroneous OpenID Connect requests if the error page includes external resources, without omitting the sensitive GET parameters from
Referer headers. This could either be done using a prior redirect to a generic path (e.g. https://example.com/error) or by defining a restrictive
Referrer-Policy (e.g., “origin-when-cross-origin” or “strict-origin-when-cross-origin”).
- Service Providers MUST use a
state value to prevent CSRF Login into arbitrary accounts if no other CSRF protection is implemented. If the
state was present within the Authentication Request, it MUST be included within the Authentication Response. If this is not the case, the Service Provider needs to fail safely (i.e., not ignore that the
state is missing and proceed anyway, but handle the occurring exception adequately). In addition, the
state value MUST be invalidated after it was redeemed once to prevent amplification attacks.
- As previously advised by Fett et al. [4, Section III; A. 7)], the optional Initiate Login Endpoint SHOULD NOT be implemented if it is not explicitly needed. The same applies to non-normative external login endpoints.
If these endpoints are implemented, token- or
Referer header-based CSRF mitigations MUST be in place. In case there is a non-normative GET parameter that controls the redirection target after successful authentication, session relevant endpoints like the External Login Endpoints or Logout Endpoints SHOULD NOT be allowed as redirection target.
- Contents provided by Identity Providers MUST be handled as third party input. Therefore, strict and context-aware sanitization MUST be performed before using these values.
Thank you for reading this post! Stay tuned for the following posts of this series, as they will include examples and detailed explanations of vulnerabilities that were found within popular real-life OpenID Connect Implementations.
If you have any feedback, feel free to contact me on Twitter: @_lauritz_. 👨💻
You can directly tweet about this post using this link. 🤓
Special thanks to Dr.-Ing. Christian Mainka (@CheariX), Dr.-Ing. Vladislav Mladenov (@v_mladenov) and Louis Jannett (@iphoneintosh) for your feedback on this post prior to publication! 🙂