Show Notes

151 - Reading GitLab Hidden HackerOne Reports and Golang Parameter Smuggling

A somewhat low-impact vuln in CrowdStrike Falcon Sensor disclosed by modzero that caused a stir due to disagreements with CrowdStrike. Falcon Sensor is an AV + Endpoint Detection and Response solution. To prevent an attacker from easily disabling the endpoint protection, it features uninstall protection, where the uninstaller / setup will prompt for a token to authorize the uninstall. Modzero found a fairly trivial way to bypass this, by programmatically opening the uninstaller and killing the third and fourth process that gets launched. By doing this, they’re able to break the token check and uninstall without authorization. It seems to be some kind of a race, as the POC takes care to get realtime priority and tries to kill the processes as soon as possible. Unfortunately they focus more on the disclosure process and don’t have many technical details.

Fairly simple vulnerability where GitLab had an internal endpoint for their own tracking of H1 reports on h1.sec.gitlab.net. The researcher found one of these links and discovered the /a path which would dump all attachments keys, which you could use to re-construct the urls to download attachments.

Post by Microsoft’s 365 Defender research team on an access control issue in TikTok’s Android app. The problem focuses on WebViews and how they interact with deeplinks, which are special hyperlinks that Android supports that applications can setup hooks for. They’re commonly used for internal app communication and routing. WebViews have a “bridge” functionality where a Java bridge class can be exposed and it’s methods can be published and called through the WebView. You can consider the attack that’s detailed as two issues.

One problem is in the deeplink handler for https://m.tiktok[.]com/redirect, which would take a query parameter to redirect the user. It’s possible to trigger internal deeplinks through the query parameter to call into non-exported activities. This expands the attack surface, though TikTok considers this acceptable.

The more critical issue is in one of the internal schemes [redacted-internal-scheme]://webview?url=<website>, which would take a URL and load it into the WebView. TikTok has filters in-place to prevent untrusted hosts from being loaded, however, this filtering was somewhat flimsy, and was bypassed by adding two additional parameters to the deeplink. Unfortunately, the Defender team doesn’t go into any more detail here.

A vulnerability in Apache HTTPD’s mod_proxy reverse proxy module. The issue comes down to an interesting logic bug in ap_proxy_create_hdrbrgd() where it would clear hop-by-hop request headers via ap_proxy_clear_connection() after the x-forwarded header addition. This leads to a situation where x-forwarded headers that were passed in a hop-by-hop list immediately get dropped and won’t make it upstream. There’s a few scenarios this could be exploited, particularly where something relies on the x-forwarded headers (such as ExpressJS and it’s trust proxy setting, or certain tomcat valves).

A post by Oxeye which studies a desync attack based on Golang’s net/url package and some subtle changes that were made to it in Go v1.17, which patched a bug where the ParseQuery() method would consider semi-colons a valid separator. As per the RFC for the URL spec, while semi-colons are an accepted separator for the path, they aren’t for the query. Similarly, the WHATWG URL specification only lists the ampersand (&) as a valid separator. As such, other language libraries like nodejs don’t recognize ; as a valid separator, and so the Go maintainers fixed net/url to conform. In go 1.17, a check was added to ParseQuery() that would return an error if a semi-colon was present.

The problem is, the URL package’s Query() routine that calls ParseQuery() explicitly ignores the error return, making it silently fail. This is a perfect soup for a smuggling attack in instances where a front-end might be running a newer version of Golang and a back-end an older version. On top of that, the httputil module’s NewSingleHostReverseProxy() method would take a raw query string and send it as-is without parsing it. In these cases, the front-end could ignore the semi-colon separated parameter, whereas it slips through to the backend that parses it as a separate parameter. This was found in multiple open source projects, including Harbor (open source artifact registry), and HTTP reverse proxies/routers Traefik and Skipper.

A very packed research post from James Kettle introducing two new forms of desync attacks.

Client-side desync - This is a new term used to describe when a desync or disagree happens between the client (browser) and server. It is in opposition to the “traditional” desync attacks that depend on a front-end and back-end server disagreement.

These happen what a server ignores the Content-Length value. This might happen if there is an early return in handling a request, like a front-end server rejecting or redirecting a response. Another case the author came across was some servers just not expecting a body at all and assuming all requests would be GET.

So if an attacker triggers one of these requests that get handled without reading the body, the body will be treated as part of the next request that comes in from that client. Giving an attacker the ability to craft a potentially malicious prefix to any request, including control of headers.

As the attack does not rely on malformed HTTP requests, they can be launched from the browser, only requiring a victim visit an attacker-controlled website (similar to CSRF).

It can be exploited similarly to normal request smuggling, by crafting a prefix that causes sensitive user data to get stored somewhere the attacker can retrieve it. It also opens up normally unavailable attack surfaces for chaining like being able to craft a cross-site attack with a JSON Content-Type: header, or attacks that rely on modified Host: headers.

Pause-based desync - This is a new way to create a desync where one end of the connection times-out but still gets reused.

A research post from jub0bs calling out a couple of CORS misconfigurations that you might be able to use to your advantage in bypassing CORS.

  1. CORS configuration can vary from page to page so it would be a mistake to only judge the configuration
  2. The Access-Control-Allow-Origin response header can only contain one allowed origin at a time. It is not uncommon however for there to be a whitelist of allowed origins and the header will be changed depending on the origin of the request. So, one should explore the different potential origins to wider your attack surface. Testing the whitelisting is also another avenue to explore, Jub0bs specifically calls out unescaped dots in regex as a potential problem spot. This is a common regex mistake as the . character, is actually a wildcard character in regex and must be escaped \. in a regex. When they are not escaped it becomes possible to take a whitelist regex like ^(dashboard|admin).example.com$ which should match dashboard.example.com and admin.example.com and bypass by registering and using dashboardQexample.com for example.