If you ever inspected your requests to big company's API's in the browser, you might have noticed some weird javascript before the JSON itself:
F...
For further actions, you may consider blocking this person and/or reporting abuse
This is incredibly illuminating. Thank you so much for this Antony!
Replace
var x
with an html script tag?But how?
In your webpage, you would do the following:
This way you overload the constructor before loading the messages themselves.
Ah ok, I see.
I think the way it is written in the article is confusing. It should instead say "override the Array constructor before loading external scripts"
Thanks for the feedback, updated the post so it's more clear
Wow you're fast!
Is this all only to protect people that misuse
eval()
to parse JSON?JSON.parse()
has never been affected by any of this, right?Hmm, the article gives example of malicious site loading the JSON API directly with a
script
tag:<script src="https://gmail.com/messages"></script>
.So here's where I'm confused:
Is this because script tags are historically lax about same-origin policies? I knew evil.example.com can include a script tag for gmail.com, but does that also give such request access to gmail.com cookies?!?
While it is absolutely possible to implement a strict security layer on an API server, this will also increase the CPU/memory/bandwidth requirements. If you have a really big service such as gmail, you'd rather do as much security as possible on the front-end level.
I'm really wondering how any of these attack techniques would fare against simpler CSRF techniques like double-submitted cookies.
Other stupid ways that seem like they could mitigate this would be to just make all the JSON endpoints require a POST, or to use a different method of encoding data that can't be interpreted as valid Javascript at all (XML?)
Making them all POST wouldn't be semantic (POST means you're changing something on the server). JSON is the standard API data format now, and it's much better than XML in my opinion.
The ultimate way to prevent these attacks is to not allow user submitted input to end up anywhere in output unescaped so attackers' scripts are never able to be injected.
No one cares about semantics verbs. Using POST for API endpoints solves an entire class of link-based attacks. We should of course still use CSRF and other mitigations, but the semantic purism argument is a weak one, IMHO.
Not POST but using header authentication an all endpoints can add a layer of security. But this is extra. Nathan's point is well told.
I can see how adding an infinite for-loop at the start of the JSON response would prevent it from being executed as JavaScript. How does the original site access the data? Does it need to use a function to discard the first X bytes of every response before loading the JSON? Or is there something I'm missing?
This is exactly it!
As they load the string version of the JSON, they can remove their JS breaking mechanism before parsing it
I just follow along your articles with devs tool open haha
TLDR: use Auth Headers instead of cookies in your API and don't use script tags to call an API?? We shouldnt be looking at the hacks that giants use and instead use actual security improvements. CSP headers!
This was about 10 years ago, when CORS and CSP didn't exist
Wouldn't CORB prevent JSON hijacking in modern browers? developers.google.com/web/updates/...
If you have some js on your site, that can modify your constructor, you already hijacked, isn't it?
This attack is used to steal data from another website.
Say you're on dev.to, you don't want dev.to to access your emails!
But dev.to can still execute their own scripts, which makes sense.
Pardon my noob but shouldn't it be fixed with CORS instead?
Cors wouldn't work on old browsers, and CORS is also used on the source site to limit what can be accessed from this website.
What is happening here is the opposite: An attacking website want to access information from another one.
Also note that this vulnerability is over 10 years old, well older than CORS :)
Amazing article. Thank you!
I did something similar, but I used
location.href=...
to redirect to the site from which the data was supposed to be used.Amazing, I knew some of those individually however this extremely helpful post is like a complete paper with references, so I can bookmark this, thank you Antony!
So just use Protocol Buffers in your API response.
Great article. Small typo. Agaim!
Thanks, just fixed it!
Awesome post Antony! I always wondered about the for loop.
Awesome stuff!!
Great post! Very insightful
nice piece and good use of the notation to illuminate the point.
Look forward to seeing more from you!
Thank you for great article. I include it on my news letter: betterdev.link/issues/76
This is great!
I've been following this newsletter since like edition 20, it's good to see my content being part of it.
Is the API still vulnerable if CORS is disabled?
No, this has been fixed about 10 years ago in the ECMA specs, no modern browsers are vulnerable to this specific approach.