Show Notes

A Slack Attack and a MySQL Scientific Notation Bug

The gist here is that One-Time-Password brute-force prevention was based on IPs, so using IP rotation could get around that.

The overall attack chain was to attempt to register a new account using an existing accounts phone number. The OTP is sent to validate the new account, it can be bruteforced, and then once validated, any existing user that is using that phone number as a 2FA will have it removed. Allowing the attacker to remove the phone number as a 2FA option.

It is possible for a malicious website to associate a visitor with their a known slack account. The attack relies on a difference in behavior when accessing a file with and without permission, and the ability to share a file with specific users. When sharing a file on Slack it’ll be uploaded and when the URL is accessed in a browser it will either redirect away if the user is not authorized to access the file, or it will trigger a download of the file.

This difference in behavior can be detected by a malicious website by noting whether or not a user was redirected. A challenge for exploiting this on slack is that in order to view the file the user must be logged in and send their session cookie in the request, this cookie is protected by SameSite=Lax meaning it is only sent during top-level navigations.

Since an authenticated request will trigger a download and not actually redirect to the page, this lack of redirect can be detected. So an attacker can change the window.location to the URL only the victim can access, wait a period of time, then see if the user is still on the original page. If they are they were not redirected and they are logged in as the victim user.

XS-Leak via form-action CSP Directive

To improve the usefulness of the attack the author looked for a way to make multiple request without requiring the navigation away if they are not the victim user. For this they found a novel XS-Leak vector that works in Chromium-based browsers. This attack works on two points:

  1. The Content-Security-Policy header can be used to specify a form-action directive which will act as an allowlist for HTML Form actions. This will trigger a securitypolicyviolation event if the form-action is not in the allowlist.
  2. Chromium-based browsers will enforce the allowlist through redirects.

With this two points in mind, the attacker can set the target URL in the allowlist, trigger a GET form post to the page (considered a top-level navigation) and if the user is not redirected (download triggered) then they know they have the victim. But if they are redirected, the redirect will trigger a securitypolicyviolation event stopping the navigation, keeping them on the page for further URLs to be attempted.

A simple bug in how MySQL deals with the e scientific notiation for numbers (1.1e5 for 110000 as an example) could be abused to bypass various Web-Application Firewalls (WAF). The bug being that the lack of any number following the e would result in the term being stripped from the query and nothing being put in its place. This meant that 1.0e or any other values for 1.0 could be placed in what would normally be syntaxically invalid locations and be stripped before the query was executed resulting in being able to defeat some of the parsing logic a WAF might be using.

Though this is a good reminder that you shouldn’t be relying on a WAF to prevent SQL injections, its a last line of defense to increase the cost of developing the attack not complete protection.

Reddit had an issue in associating transactions and order information. If you initiated a coin purchase for say $1.99, the order will be created and the order ID can be obtained. If you cancel that order, and then make a new one for a larger purchase but swap out the order_id in the response to creating the order. The redirect to Paypal will be for the original order’s amount but Reddit will have associated it with a larger coin ammount.

While the report doesn’t disclose the root cause of this bug, since the order is created and the order id is returned it is possibly then used in a follow-up request that creates the paypal transaction and mixes knowledge sources up. Where it draws some information from the current session and the transaction being performed, and other information from an order lookup. So it would be reading the number of coins associated with the paypal transaction from the session, but the cost might have been set when creating the paypal transaction earlier. Not sure, its a bit of a weird bug to have.

} }