HexBrain

GSA Bounty · Report #263662

Cross-Site Request Forgery on the Federalist API (all endpoints), using Flash file on the attacker's host

Validstatus
mediumseverity
34upvotes
27 Sept 2017disclosed

Summary

We endorse sp1d3rs's summary! The PR fixing this ticket is here: https://github.com/18F/federalist/pull/1157

Thanks to the 18F team for the great experience, fast fix, and the bounty! The report details (i requested the limited disclosure due to lot of sensitive info in the attachments and report itself, and possibility to use a Summary as a kind of structured write-up):

Hello. At the beginning of my work with TTS Bug Bounty program, I noticed, that Federalist API does not have any CSRF protection - but was unable to make proper POC, since data had JSON format, and the Content-Type header was correctly checked.

However, I was able to forge valid Content-Type header using flash file now, after reading some articles of other researchers.

I recommend to read this article first to fully understand the issue: http://www.geekboy.ninja/blog/exploiting-json-cross-site-request-forgery-csrf-using-flash/ http://resources.infosecinstitute.com/bypassing-csrf-protections-fun-profit/#gref

It means that JSON data without any CSRF protection is not so safe, as supposed to be.

Why it works

To clarify, the SOP/CORS are failing in the case of 307 redirect trick (due to that fact, that during 307 redirect crossdomain.xml on the target host will be called after the POST request for some reason - so POST request will reach the destination), and can only prevent the response reading by the Flash application, but not prevent the CSRF attack itself (it can be the Flash fault, or the way how the browsers are handling 307 redirects of the requests, initialized by Flash applications).

So it does not actually matter, does Access-Control-Allow-Origin header exist or not on the target host (Flash ignores it), same as crossdomain.xml.

Tested HTTP methods on Federalist API:

GET - CSRF possible POST - CSRF possible PUT - CSRF not possible DELETE - CSRF not possible

POC

You can use live POC (host was redacted in this Summary due to security reasons 【ツ】):

http://[REDACTED]/test.swf?jsonData={"site":1,"branch":"master"}&php_url=http://[REDACTED]/test.php&endpoint=http://localhost:1337/v0/build/

You can specify the jsonData (for example, if you need to change siteID param), and endpoint by different Federalist endpoint (in case you are testing not on the localhost)

This POC will work on the Federalist staging site:

http://[REDACTED]/test.swf?jsonData={"site":1,"branch":"master"}&php_url=http://[REDACTED]/test.php&endpoint=https://federalist.fr.cloud.gov/v0/build

and this will work on the Federalist production site:

http://[REDACTED]/test.swf?jsonData={"site":1,"branch":"master"}&php_url=http://[REDACTED]/test.php&endpoint=https://federalist.18f.gov/v0/build

The only conditions for this:

  1. Flash must be enabled in the browser.
  2. User must be logged in.
  3. User must have access to the site with ID 1.

In other case, change the payload from

{"site":1,"branch":"master"}

to

{"site":[siteID you have access to],"branch":"master"}

for successful testing.

The SWF file will send JSON data to the http://[REDACTED]/test.php, which then will be 307-redirected to the Federalist with correct Content-Type.

The result will be restarting the build of the site with ID 1 (if exist, and the current user is the owner). On the screen below I did this with site ID 35 on my test instance. [SCREENS REMOVED]

Reproduction steps:

If you want to reproduce it on your own servers, you need the host, specially crafted SWF file, PHP file with 307 redirect, and crossdomain.xml file (in case PHP and SWF files are not on same-origin). It should also work locally. I created GitHub repo to simplify the CSRF testing process: https://github.com/sp1d3r/swf_json_csrf

Impact

The attacker can call any POST API action on behalf of Federalist user, who will visit the specially crafted page with SWF file. The attacker can trigger the build, add the site (if the repository name is known), etc - basically, all possible POST API actions which the user can do. Still, because the attacker does not know private repo names - he can't easily do the worst actions, so this issue has Medium impact.

Suggested fix

The fix can actually be the one of (order is determined by safety):

  1. Implementing anti-CSRF tokens protection (header-based). [This one was chosen as fix]
  2. Switching the POST method on the API endpoints to the PUT- we can leave GET API endpoints as is, because these endpoints are only informational, and their responses can't be read by the Flash application - so I think we are safe here, and JSON Hijacking is not possible for now (if no bypass will be discovered).
  3. Check the Referer/Origin header - at this moment we can't set arbitrary headers using Flash - so it can be considered as the fix too. However, due to weird things discovered on regular basis with Flash - all can happen in the future.

References

How it was found

The write-up for this report has not been downloaded yet, or the program disclosed it without one. Read it on HackerOne.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original