Alok Menghrajani
Previously: security engineer at Square, co-author of HackLang, put the 's' in https at Facebook. Maker of CTFs.
This blog does not use any tracking cookies and does not serve any ads. Enjoy your anonymity; I have no idea who you are, where you came from, and where you are headed to. Let's dream of an Internet from times past.
Home | Contact me | Github | RSS feed | Consulting services | Tools & games
I gave a talk at ASFWS 2013 about JSONP security. The purpose of my talk was to share some knowledge related to attacking and securing JSONP endpoints.
The talk started with an overview of JSONP, followed by a combination of well known and lesser known security issues.
I then talked about crafting Flash files containing only specific bytes. The purpose of such files is to CSRF the domain hosting the JSONP endpoint by injecting the Flash code as the callback parameter.
These are my notes I gathered while preparing the talk. Credits to Erling for exploring these issues with me and debugging my work.
A protocol to talk cross domain
- Browsers implement a policy called "Same Origin Policy". This policy prevents different domains from stealing each others data.
- JSONP is a protocol (actually, more of a convention) to bypass the Same Origin Policy in order to exchange specific pieces of information.
- Sample application: api.pizza.com, a website which lets users share their favorite pizza toppings across different web sites.
- Data consumer (http://some-site.com/):
<html> <body> ... <script> function onTopping(data) { ... } </script> ... <script src="http://api.pizza.com/?callback=onTopping"></script> </body> </html>
- Data provider (http://api.pizza.com/?callback=onTopping):
HTTP/1.1 200 OK Date: Mon, 07 Oct 2013 20:45:39 GMT Server: Apache onTopping({... json encoded data ...})
- The callback convention allows people to mash different APIs without having collisions.
Types of data providers
There are three types of data providers: stateless, token based and cookie based.
- Stateless APIs are useful for querying public information. E.g. a weather api.
- Token based APIs require some kind of protocol to exchange the token. E.g. Connect or OAUTH.
- Stateless and token based APIs should be hosted on different domains. E.g. api-pizza.com.
- Cookie based APIs should use a subdomain. E.g. api.pizza.com.
Trusting api.pizza.com
- Malicious data providers can XSS the data consumer.
- Data consumer can protect themselves by using a combination of iframe + different domain.
Content-Type header
- If the callback's value is "<html><body><script>...", a data provider can be XSSed.
- Data providers can protected themselves by sending a
Content-Type: application/json
header.
X-Content-Type header
- In some cases, a browser can be tricked to "sniff" the content type, even when a
Content-Type
header was sent. - The data provider should therefore also send
X-Content-Type: nosniff
.
Injecting Flash files
<object type="application/x-shockwave-flash"...>
can be used to bypassX-Content-Type
.- Flash files are allowed to talk back to the originating domain. The exact policy is controlled by the
crossdomain.xml
file. - From a web security point of view, hosting Flash files is not equivalent to hosting JavaScript.
SWF file format
The SWF file format specification is not strictly enforced by current Flash players.
- Version, FileLength, FrameSize, FrameRate and FrameCount fields are ignored when invalid.
- An invalid doAction code is ignored (equivalent to a noop).
Multiple ways to compress a SWF file
- FWS, not compressed. We end up always having a null byte. (0x00-0x7f?)
- CWS with BTYPE=00, compression with no compression (mind blowning!).
- CWS with BTYPE=01, compression with fixed Huffman codes.
- CWS with BTYPE=10, compression with dynamic Huffman codes.
- CWS with BTYPE=11, unknown/invalid compression?
- ZWS, compression with LZMA.
Custom compressed data streams
Most compression algorithms generate "instructions", which the decompression algorithm interprets. The compression process can therefore make specific choices.
Let's imagine a run-length compression system. The string "AAAA" can be compressed as "4A", "2A,2A", "A,3A", etc. "4A" is obviously the most efficient compression, but the other options are valid too.
In general, compression algorithms are designed to create the smallest possible stream. We can however compress data in a way that only emits specific bytes.
As an example, here is valid Flash file which only uses bytes in the 0x03-0x7e range:
0000000: 4357 536a 6163 6b69 6843 5254 5464 6060 CWSjackihCRTTd`` 0000010: 6030 6006 681a 3b03 437c 517e 7e09 0340 `0`.h.;.C|Q~~..@ 0000020: 323e 2e7e 3e3e 4911 4060 3c0b 3046 0606 2>.~>>I.@`<.0F.. 0000030: 0303 0606 0606 0606 0606 2f61 316f 6b06 ........../a1ok. 0000040: 0606 0606 0606 0706 0606 404e 0b09 12 ..........@N...
Conclusion
- Host JSONP api on different domain.
- Filter callback.
/^[a-zA-Z0-9]{1,32}$/
seems reasonable, but cannot be guaranteed to be safe. - An empty JavaScript comment breaks the Flash injection attack.
- Be careful with PDF injection!
- Use CORS when possible.
HTTP/1.1 200 OK Date: Mon, 07 Oct 2013 20:45:39 GMT Server: Apache Content-Type: application/json X-Content-Type: nosniff /**/onTopping({... json encoded data ...})
Future work?
- Using doABC instead of doAction bytecodes.
- ZWS.
- CWS with dynamic Huffman codes.
- Crafting Flash files with a genetic algorithm.
- Can a CSRF on api.pizza.com escalte to an attack on pizza.com or www.pizza.com?
Links
- AppSecForum 2013
- Wikipedia page on JSONP
- George Jempty's proposal for JSON++ (July 2005)
- Bob Ippolito's propsal for JSONP (December 2005)
- Same origin policy for cookies
- Same origin policy for Flash
- Security risks with JSONP? (October 2012)
- Sandbox Your Cross Domain JSONP To Improve Mashup Security
- SWF file format specification (version 19)
- Deflate
- GZIP
- cure53.de xmas2013 write up: Who controls the first bytes controls the SOP
- Got a bounty too for this bug, thank you github.com!
- Twitter is kind of vulnerable to this issue. I reported it to them in Oct 2013. 5 months later they got back to me with: "We do not plan to make any changes to our JSON APIs at this time.".
- About a year after I posted my findings, Gábor and Michele improved on my work. They coined the term Rosetta Flash for this attack. Gábor Molnár's slides, Michele Spagnuolo's post