[HackerNotes Ep.110] Oauth Gadget Correlation and Common Attacks

A DOMPurify 3.2.3 Bypass, Ophion Security Cisco Webex research, a new postMessage Chrome Extension, and a whole lot of OAuth research. Check it out below.

Hacker TL;DR

  • DomPurify Bypass: By abusing agreed-upon definitions of an HTML comment, this research details a DomPurify bypass. The full bypass ended up being:

    <math><foo-test><mi><li><table><foo-test><li></li></foo-test><a> <style> <! \${ </style> } <foo-b id="><img src onerror='alert(1)'>">hmm...</foo-b> </a></table></li></mi></foo-test></math>

  • Ophion Security - Live Chat Blog #2: Cisco Webex Connect - Access to millions of chat histories: Research by Ophion security that allowed them to disclose millions of chat results. The biggest highlight of this research is to really understand the auth processes of a target and question how each value involved in the process is derived.

  • postLogger: A new chrome extension dropped by ndEVtk to track all things postMessage, including scope checking of all messages, insecure origin checks, MessageChannel API checks and more.

  • OAuth Hacking: The research team at Doyensec dropped some great OAuth research along with a nice cheat sheet. Some of the tips dropped in the pod:

The White House has recently banned the use of Kaspersky products across the United States, citing concerns over potential data access risks and allegations of incorporating "backdoors" in their software.


In response, ThreatLocker®, a prominent provider of Zero Trust cybersecurity solutions, has introduced a complimentary system cyber health report. This tool offers businesses insights into their IT environments, highlighting vulnerabilities associated with foreign software. This proactive measure assists organizations in assessing and securing their software ecosystems, ensuring compliance and preemptively addressing security threats. While acknowledging national security concerns raised by foreign software, ThreatLocker® emphasizes the broader scope of vulnerabilities, exemplified by incidents like the 2020 SolarWinds attack. The ThreatLocker® cyber health report comprehensively details all applications in use, their countries of origin, and potential data access implications, promoting informed decision-making and robust security protocols.

Learn More About the ThreatLocker® Cyber Health Report Here: https://www.criticalthinkingpodcast.io/chr

I’m not sure about anyone else but every time I see the words ‘DomPurify’ and ‘bypass’ together, I feel a little glimmer of hope bubble up inside.

This research by ensy.zip targets DomPurify in its default configuration. The main takeaway for this one is that there is not an agreed-upon definition of what forms an HTML comment by the browser and DomPurify, which allowed for the exploit, detailed below, to happen.

The WHATWG HTML spec specifies that comments are meant to start with <!-- ... --> , but they also allow <! .. > to be used, and the second case wasn’t handled properly in DomPurify. If a library and the component are each parsing or defending against input in different ways, it’s unlikely the library will be able to adequately protect the component.

Any discrepancies in agreed-upon definitions of valid and invalid input can make some pretty nasty bugs, and this one is no different. Using this discrepancy, it’s possible to sneak in a mutation XSS payload with the following:

<math><foo-test><mi><li><table><foo-test><li></li></foo-test><a>
    <style>
      <! \\${
    </style>
    }
    <foo-b id="><img src onerror='alert(1)'>">hmm...</foo-b>
  </a></table></li></mi></foo-test></math>

What’s cool about this research is how concise it is. It’s literally a page or so long, covers everything you need, and has a bunch of cool resources if this kind of research interests you. These kinds of discrepancies are precisely the kind of things we need and want to bypass these kinds of defences.

Check it out below:

This research by Ophion allowed them unauthenticated access to Cisco Webex Chats by peeling back and attacking the authentication chats authentication mechanisms. It’s a great write-up - not only technically but also the thought process and the approach to mapping out and really understanding a target.

By piecing together how users were differentiated by understanding various values in API calls - with the initial suspects being the secretKey header and the title value generated for each chat request, it was possible to use a hidden endpoint to pull arbitrary chat logs.

The below request is taken from the research of the initial request to initiate a new chat:

POST /rtmsAPI/api/v3/apps/CLIENT_ID/threads HTTP/2
Host: CUSTOMERNAME-usor.apps-imiconnect.io
Content-Length: 165
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.120 Safari/537.36
Content-Type: application/json
Accept: */*
Secretkey: CLIENT_KEY
Priority: u=1, i

{"title":"da0f3fca-5f21-4b8b-b76d-1bf5baf5813c_APP_ID_ALLOWED_ORIGIN_1727372312156","type":"Conversation","status":"Active"}

Through enumeration of the API calls, they pieced together what primitives are used to build the identifiers, for example:

  • First UUID bit → unknown initially

  • Second UUID bit → App UUID embedded in JS

  • Third Bit → allowed origin domain for the chat, for example chat.example.com

  • Final bit → Timestamp of the chat

After some digging, they determined that the title field was formed by joining these four components. Understanding how each piece was derived (e.g., the second UUID from embedded JS) allowed them to replicate valid-looking chat identifiers.

Further analysis of the application’s JavaScript and API calls, they discovered an endpoint - /rtmsAPI/api/v3/apps/CLIENT_ID/ - that wasn’t referenced in standard documentation. Turns out, this endpoint accepted the secretKey and title parameters but failed to properly enforce any other checks.

Using the knowledge of the secretKey header and the correct format for the title parameter, it was possible to issue requests to the hidden endpoint. They supplied values for each portion (UUID, App ID, domain, timestamp) and the endpoint responded with chat logs belonging to other users. This was also possible in a completely unauthenticated context!

I think the biggest highlight of this research is to really understand the auth processes of a target and question how each value involved in the process is derived. By piecing together and tracing the flows of each value, they were able to turn an ‘..that looks interesting’ into a critical finding.

The full research for this one can be found below:

- postLogger

If you’re familiar with Frans Rosen’s postMessage tracker or DomLogger++ postMessage configuration, this one might be beneficial for you.

postLogger console output

ndEVtk dropped an extension for both Chrome and Firefox that allows for some pretty neat tracking of all things postMessage. This was taken from the extensions page, with functionality including:

- console.info for postMessages from all_frames.

- detects the scope of sent messages.

- origins that are insecure due to being a sandbox domain or a wildcard, will be prefixed with UNSAFE.

- detects if a website does not check MessageEvent.origin

- MessageChannel API

Check it out below:

- OAuth Hacking

OAuth is one of those topics that can seem daunting. Luckily for us, the research team at Doyensec has dropped some more great content - this time on OAuth - that includes a really nice, easy-to-use cheat sheet.

There’s no point re-hashing the overview of each OAuth flow as the research details it perfectly. We recommend checking it out for yourself if you want a primer, and we’ll instead focus on some of the aspects covered on the pod. Full research here:

Doyensec Research

Depending on the OAuth flow in use will depend on the threat model of the OAuth flow. Each flow was created for different use cases, so understanding the context of your target, the app and its OAuth flow will craft and define the threat model and the impact of these attacks.

It’s worth noting not all attacks will be applicable to all OAuth flows, which is why we put an emphasis on understanding context. Let’s jump into some of the attacks:

Attacks

CSRF - Authorization Code Flow and Implicit Flow

A common vulnerability whereby the state parameter isn’t verified in an OAuth flow. This means the browser (or user) using the authorization code is not the browser that initiates the code, resulting in the victim consuming the attacker’s code, resulting in them being authenticated under the attacker’s context.

Redirect attacks - Authorization Code Flow and Implicit Flow

The redirect_uri is the parameter used in an OAuth flow to redirect the user after the OAuth flow has finished - this will usually be a URI to your target application to finish the flow. In some cases, this value is not checked at all, meaning an arbitrary open redirect Is possible.

The more common situation is where the scheme and origin are checked but the path are not, allowing flexibility with things such as https://target.com/original/uri/../../arbitrary/poc , allowing redirects to any path on the origin.

This is a powerful gadget when chained with CSPT or another open redirect and response mode switching, allowing you to harvest an authorization code of a user.

Mutable Claims attacks - Authorization Code Flow with OIDC, Implicit Flow with OIDC, Hybrid Flow

When a server attempts to identify each user, the OAuth spec specifies that the sub field is used. However, there is no standard for this field itself, meaning there are many implementations and formats of it.

Due to this, some applications depend on username or email to uniquely identify users. The problem is that in some cases, these fields can be modified across authorization providers and even modified by users themselves in some cases.

That gives you a situation whereby a user could update their email to one they don’t necessarily own, which could cause a myriad of problems in an application’s auth flow.

Check out this research to see this type of attack in action: https://www.descope.com/blog/post/noauth

Client confusion attacks - Implicit Flow

Sometimes applications do not cross-check if an associated client ID was used with a token it is being provided, meaning it’s possible for an entirely different client ID to generate a valid auth token for that app.

An attack scenario here would be: An attacker creates an app with the same OAuth provider as the victim application. When a user signs up to the attacker’s app and logs in via the OAuth provider, the attacker will have access to the user’s token.

Now, if the client ID isn’t being checked, an attacker can use this same token on a victim application and authenticate as the user.

Scope upgrade attack - Authorization Code Flow

If an authorization server performs no checks on a supplied scope parameter, which is used to define the scope (permissions granted) of the token, a malicious application could upgrade the scope assigned to a token by supplying arbitrary scope values along with harvested authorization codes.

This would provide an attacker means of invalidating the agreed-upon scope of the token that the user accepted in the initial auth stage.

Google Auth Gadgets

The guys have been hitting Google pretty heavily over the last few weeks and mapping out Google’s auth, and shared a tonne of insights on the pod as to how their architecture works.

For example, to hit Google APIs, you usually need:

  • API key: This key isn’t used for auth directly but instead for client & project correlation.

  • Client ID

  • Redirect URI

  • Appropriate scope associated with client and account

One thing to consider is that you may not initially have all of these pieces available to you on a target. You might have a client ID but not know the exact redirect URI value for example, and without all the pieces, you won’t be able to auth.

Taking note of any gadgets that leak information about a given flow can be pivotal to long-term success on a target. For example, Justin has a way to take a Google API key and correlate that to specific project IDs. In the context of Google, that becomes useful as the project ID is the first 12 characters of the client ID.

By itself, it isn’t impactful, but it becomes useful in black box situations whereby you’re working through a lot of APIs without this knowledge to hand.

As you build out your understanding of OAuth for a given target, take notes of gadgets that leak scope, redirect URIs, and properties - all of these things can prove to be pivotal to long-term and high signal success on a target.

Some of the more generalised tips they dropped on the pod:

Tips

  • OAuth Errors and Gadgets: Pay attention to verbose errors on auth-related endpoints or throughout the flow. This can disclose additional properties that can be abused later on or with other flows.

  • Introspection: Take note of token introspection endpoints to disclose further information on a given token: https://www.oauth.com/oauth2-servers/token-introspection-endpoint/ 

  • Universal redirects: Some environments implement a universal redirect which will work for any client ID. One of the most common ones is the oob or urn:oob or ietf: ... - if you can find one of these in an environment, it will save the added complexity of correlating a client ID to a redirect_uri

  • OAuth monitoring: Building an application to track API endpoints, keys and OAuth scopes and claims throughout an ecosystem for a bigger target can help identify some juicy bugs in their auth flows. Monitoring changes over time can unearth any misconfiguration that makes its way into scope.

And that’s a wrap - a short but packed episode this week from the guys.

As always, keep hacking!