Can someone explain the reason for the limitations for the JSON callbacks? I'm sure there are good reasons, but they're nonobvious to me. See: < https://www.mediawiki.org/wiki/API:Data_formats#JSON_callback_restrictions >
-Daniel (User:DanielRenfro)
On Wed, 16 May 2012 11:27:21 -0700, Daniel Renfro drenfro@vistaprint.com wrote:
Can someone explain the reason for the limitations for the JSON callbacks? I'm sure there are good reasons, but they're nonobvious to me. See: < https://www.mediawiki.org/wiki/API:Data_formats#JSON_callback_restrictions
-Daniel (User:DanielRenfro)
JSON callbacks can be initiated by 3rd party websites. Allowing json callbacks to act as the logged in user would allow any website on the internet to extract information that is supposed to be private and potentially make unauthorized write actions on the wiki. Private wiki content could be extracted. Articles could be edited in your name. And up till recently it would have also been possible to make some preferences changes that would effectively let someone take over your whole account.
On May 16, 2012, at 12:03 PM, Daniel Friesen wrote:
JSON callbacks can be initiated by 3rd party websites. Allowing json callbacks to act as the logged in user would allow any website on the internet to extract information that is supposed to be private and potentially make unauthorized write actions on the wiki.
Private wiki content could be extracted.
Yep! Still can on some browsers.
Articles could be edited in your name.
I thought http://www.mediawiki.org/wiki/Manual:Edit_token protects against this as it is required for an edit: http://www.mediawiki.org/wiki/API:Edit
And up till recently it would have also been possible to make some preferences changes that would effectively let someone take over your whole account.
I didn't know OptionsToken is new http://www.mediawiki.org/wiki/API:Options :-(
Cool! Learn something new about mediawiki every day.
Take care,
terry
On Wed, May 16, 2012 at 7:32 PM, Terry Chay tchay@wikimedia.org wrote:
I thought http://www.mediawiki.org/wiki/Manual:Edit_token protects against this as it is required for an edit: http://www.mediawiki.org/wiki/API:Edit
Not if you can read the data using the Object/Array constructor hacks you described. The potential for data leakage includes token leakage, and once you get the API to leak a token you can create a hidden form on the page that POSTs all the right data (including the token) to the action=edit API and call .submit() on the form.
Roan
On Wed, 16 May 2012 19:46:26 -0700, Roan Kattouw roan.kattouw@gmail.com wrote:
On Wed, May 16, 2012 at 7:32 PM, Terry Chay tchay@wikimedia.org wrote:
I thought http://www.mediawiki.org/wiki/Manual:Edit_token protects against this as it is required for an edit: http://www.mediawiki.org/wiki/API:Edit
Not if you can read the data using the Object/Array constructor hacks you described. The potential for data leakage includes token leakage, and once you get the API to leak a token you can create a hidden form on the page that POSTs all the right data (including the token) to the action=edit API and call .submit() on the form.
Roan
Actually I don't think the object constructor or getter hacks work.
jQuery('<script />', {src: "https://en.wikipedia.org/w/api.php?action=query&prop=info&titles=Mai...'); api.php:1 Uncaught SyntaxError: Unexpected token :
We don't wrap the JSON in ()'s (it would be invalid JSON). And as a result the {} is in a statement scope instead of an expression scope. As a result the JavaScript engine tries to parse this as a block of code rather than an object. Naturally since "asdf": is not valid code the JavaScript engine quickly fatals considering this a SyntaxError before it can evaluate anything.
It only works for array because [] doesn't have the ambiguity that {} has.
Ahh right, my memory is off. I forgot that {} is in the wrong scope so doesn't trigger __defineSetter__ due to syntax error.
On May 17, 2012, at 10:07 AM, Daniel Friesen wrote:
On Wed, 16 May 2012 19:46:26 -0700, Roan Kattouw roan.kattouw@gmail.com wrote:
On Wed, May 16, 2012 at 7:32 PM, Terry Chay tchay@wikimedia.org wrote:
I thought http://www.mediawiki.org/wiki/Manual:Edit_token protects against this as it is required for an edit: http://www.mediawiki.org/wiki/API:Edit
Not if you can read the data using the Object/Array constructor hacks you described. The potential for data leakage includes token leakage, and once you get the API to leak a token you can create a hidden form on the page that POSTs all the right data (including the token) to the action=edit API and call .submit() on the form.
Roan
Actually I don't think the object constructor or getter hacks work.
jQuery('<script />', {src: "https://en.wikipedia.org/w/api.php?action=query&prop=info&titles=Mai...'); api.php:1 Uncaught SyntaxError: Unexpected token :
We don't wrap the JSON in ()'s (it would be invalid JSON). And as a result the {} is in a statement scope instead of an expression scope. As a result the JavaScript engine tries to parse this as a block of code rather than an object. Naturally since "asdf": is not valid code the JavaScript engine quickly fatals considering this a SyntaxError before it can evaluate anything.
It only works for array because [] doesn't have the ambiguity that {} has.
-- ~Daniel Friesen (Dantman, Nadir-Seen-Fire) [http://daniel.friesen.name]
Wikitech-l mailing list Wikitech-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/wikitech-l
On May 17, 2012, at 7:07 PM, Daniel Friesen wrote:
On Wed, 16 May 2012 19:46:26 -0700, Roan Kattouw roan.kattouw@gmail.com wrote:
On Wed, May 16, 2012 at 7:32 PM, Terry Chay tchay@wikimedia.org wrote:
I thought http://www.mediawiki.org/wiki/Manual:Edit_token protects against this as it is required for an edit: http://www.mediawiki.org/wiki/API:Edit
Not if you can read the data using the Object/Array constructor hacks you described. The potential for data leakage includes token leakage, and once you get the API to leak a token you can create a hidden form on the page that POSTs all the right data (including the token) to the action=edit API and call .submit() on the form.
Roan
Actually I don't think the object constructor or getter hacks work.
jQuery('<script />', {src: "https://en.wikipedia.org/w/api.php?action=query&prop=info&titles=Mai...'); api.php:1 Uncaught SyntaxError: Unexpected token :
We don't wrap the JSON in ()'s (it would be invalid JSON). And as a result the {} is in a statement scope instead of an expression scope. As a result the JavaScript engine tries to parse this as a block of code rather than an object. Naturally since "asdf": is not valid code the JavaScript engine quickly fatals considering this a SyntaxError before it can evaluate anything.
It only works for array because [] doesn't have the ambiguity that {} has.
-- ~Daniel Friesen (Dantman, Nadir-Seen-Fire) [http://daniel.friesen.name]
Indeed. Browsers that evaluate the JSON response as JavaScript (rather than JSON, plain text) would quickly fail with a SyntaxError.
For the long-term future, though, since format=json has an application/json header, browsers shouldn't evaluate it as javascript at all. Mozilla Firefox has already started to adhere to this practice. Hopefully other browsers will follow.
Because until then, although an entirely different matter not related to MediaWiki API, the following would be evaluated in those browsers:
Content-Type:application/json; charset=utf-8
{"foo": (function () { var s = document.createElement('script'); /* ... */ }())}
You get the idea..
-- Krinkle
Ahh makes sense. The docs are a little confusing. I forgot that you can do action=tokens without CSRF protection.
On May 16, 2012, at 7:46 PM, Roan Kattouw wrote:
On Wed, May 16, 2012 at 7:32 PM, Terry Chay tchay@wikimedia.org wrote:
I thought http://www.mediawiki.org/wiki/Manual:Edit_token protects against this as it is required for an edit: http://www.mediawiki.org/wiki/API:Edit
Not if you can read the data using the Object/Array constructor hacks you described. The potential for data leakage includes token leakage, and once you get the API to leak a token you can create a hidden form on the page that POSTs all the right data (including the token) to the action=edit API and call .submit() on the form.
Roan
Wikitech-l mailing list Wikitech-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/wikitech-l
On Wed, 16 May 2012 19:32:40 -0700, Terry Chay tchay@wikimedia.org wrote:
On May 16, 2012, at 12:03 PM, Daniel Friesen wrote:
JSON callbacks can be initiated by 3rd party websites. Allowing json callbacks to act as the logged in user would allow any website on the internet to extract information that is supposed to be private and potentially make unauthorized write actions on the wiki.
Private wiki content could be extracted.
Yep! Still can on some browsers.
Articles could be edited in your name.
I thought http://www.mediawiki.org/wiki/Manual:Edit_token protects against this as it is required for an edit: http://www.mediawiki.org/wiki/API:Edit
Yes. Except you can get tokens by the api. If we didn't drop permissions to anon and reject requests for tokens to JSONP then it would be possible for a 3rd party website to use JSONP to extract an edit token, and then initiate a background iframe form POST to make an edit under your account.
And up till recently it would have also been possible to make some preferences changes that would effectively let someone take over your whole account.
I didn't know OptionsToken is new http://www.mediawiki.org/wiki/API:Options :-(
Cool! Learn something new about mediawiki every day.
Take care,
terry
On Thu, May 17, 2012 at 11:19 PM, Daniel Friesen lists@nadir-seen-fire.comwrote:
On Wed, 16 May 2012 19:32:40 -0700, Terry Chay tchay@wikimedia.org wrote:
On May 16, 2012, at 12:03 PM, Daniel Friesen wrote:
JSON callbacks can be initiated by 3rd party websites. Allowing json
callbacks to act as the logged in user would allow any website on the internet to extract information that is supposed to be private and potentially make unauthorized write actions on the wiki.
Private wiki content could be extracted.
Yep! Still can on some browsers.
Articles could be edited in your name.
I thought http://www.mediawiki.org/wiki/**Manual:Edit_tokenhttp://www.mediawiki.org/wiki/Manual:Edit_tokenprotects against this as it is required for an edit: http://www.mediawiki.org/wiki/**API:Edithttp://www.mediawiki.org/wiki/API:Edit
Yes. Except you can get tokens by the api. If we didn't drop permissions to anon and reject requests for tokens to JSONP then it would be possible for a 3rd party website to use JSONP to extract an edit token, and then initiate a background iframe form POST to make an edit under your account.
Read up. :)
Terry/Roan mentioned that you can use regular JSON output format, and override the property setter to steal the data.
On Thu, May 17, 2012 at 6:32 AM, Andrew Garrett agarrett@wikimedia.orgwrote:
On Thu, May 17, 2012 at 11:19 PM, Daniel Friesen lists@nadir-seen-fire.comwrote:
Yes. Except you can get tokens by the api. If we didn't drop permissions to anon and reject requests for tokens to JSONP then it would be possible for a 3rd party website to use JSONP to extract an edit token, and then initiate a background iframe form POST to make an edit under your
account.
Read up. :)
Terry/Roan mentioned that you can use regular JSON output format, and override the property setter to steal the data.
We've tried to make sure that there is no way to pull the edit token cross site. That would be a violation of our security assumptions, so we would try to fix it asap.
I've actually been looking at the override attack in my spare time for the past few weeks (since I found out the edit token as available in json). I haven't been able to find a browser that it works in yet, although I'm suspicious of IE 6/7 and haven't had the time to test yet. If someone does find a working example for a specific browser, please do notify me!
I think Opera would have been the last to change. I'm not sure of IE because early versions of IE have poor ECMAscript support. You'd might override Array(), but I doubt you can override Object with the __defineGetter__.
On May 17, 2012, at 9:37 AM, Chris Steipp wrote:
On Thu, May 17, 2012 at 6:32 AM, Andrew Garrett agarrett@wikimedia.orgwrote:
On Thu, May 17, 2012 at 11:19 PM, Daniel Friesen lists@nadir-seen-fire.comwrote:
Yes. Except you can get tokens by the api. If we didn't drop permissions to anon and reject requests for tokens to JSONP then it would be possible for a 3rd party website to use JSONP to extract an edit token, and then initiate a background iframe form POST to make an edit under your
account.
Read up. :)
Terry/Roan mentioned that you can use regular JSON output format, and override the property setter to steal the data.
We've tried to make sure that there is no way to pull the edit token cross site. That would be a violation of our security assumptions, so we would try to fix it asap.
I've actually been looking at the override attack in my spare time for the past few weeks (since I found out the edit token as available in json). I haven't been able to find a browser that it works in yet, although I'm suspicious of IE 6/7 and haven't had the time to test yet. If someone does find a working example for a specific browser, please do notify me! _______________________________________________ Wikitech-l mailing list Wikitech-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/wikitech-l
Hi Daniel,
The restrictions prevent a class of attacks that go by the name "javascript hijacking" [1] or "xssi" [2]. This is where a malicious website (evil.com) includes the json (wrapped in the callback) from a <script src=some_url /> tag. The Javascript rules say that if evil.com included the javascript file from a script src link, then any javascript on the page (written by evil.com) has full access to the variables and javascript code on the page. So evil.com could send the tokens off to an attacker for use, or it could do a csrf attack right there from evil.com. GMail was bit by this a few years ago [3].
Hopefully that makes sense, but let me know if you want any more details!
Chris
[1] - http://en.wikipedia.org/wiki/JavaScript#Cross-site_vulnerabilities [2] - http://google-gruyere.appspot.com/part3 [3] - http://jeremiahgrossman.blogspot.com/2006/01/advanced-web-attack-techniques-...
On Wed, May 16, 2012 at 11:27 AM, Daniel Renfro drenfro@vistaprint.comwrote:
Can someone explain the reason for the limitations for the JSON callbacks? I'm sure there are good reasons, but they're nonobvious to me. See: < https://www.mediawiki.org/wiki/API:Data_formats#JSON_callback_restrictions >
-Daniel (User:DanielRenfro)
Wikitech-l mailing list Wikitech-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/wikitech-l
Ah, XSS -- of course. Please excuse my temporary lapse of security-awareness. -Daniel
-----Original Message----- From: wikitech-l-bounces@lists.wikimedia.org [mailto:wikitech-l-bounces@lists.wikimedia.org] On Behalf Of Chris Steipp Sent: Wednesday, May 16, 2012 3:28 PM To: Wikimedia developers Subject: Re: [Wikitech-l] reasons for api json callback restrictions
Hi Daniel,
The restrictions prevent a class of attacks that go by the name "javascript hijacking" [1] or "xssi" [2]. This is where a malicious website (evil.com) includes the json (wrapped in the callback) from a <script src=some_url /> tag. The Javascript rules say that if evil.com included the javascript file from a script src link, then any javascript on the page (written by evil.com) has full access to the variables and javascript code on the page. So evil.com could send the tokens off to an attacker for use, or it could do a csrf attack right there from evil.com. GMail was bit by this a few years ago [3].
Hopefully that makes sense, but let me know if you want any more details!
Chris
[1] - http://en.wikipedia.org/wiki/JavaScript#Cross-site_vulnerabilities [2] - http://google-gruyere.appspot.com/part3 [3] - http://jeremiahgrossman.blogspot.com/2006/01/advanced-web-attack-techniques-...
On Wed, May 16, 2012 at 11:27 AM, Daniel Renfro drenfro@vistaprint.comwrote:
Can someone explain the reason for the limitations for the JSON callbacks? I'm sure there are good reasons, but they're nonobvious to me. See: < https://www.mediawiki.org/wiki/API:Data_formats#JSON_callback_restrictions >
-Daniel (User:DanielRenfro)
Wikitech-l mailing list Wikitech-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/wikitech-l
_______________________________________________ Wikitech-l mailing list Wikitech-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/wikitech-l
Not really an XSS since the script include doesn't originate from the target's machines, this is a variation on CSRF known as "Javascript Hijacking" or XSSI.
The idea behind CSRF is that the attacking site (on XSS the attacking origin is the target site, in CSRF it can be anywhere) generates a API call on the target to take an action on it forging the user's credentials (because the target is using cookie authentication and the user's browser has been ordered to make the call instead of a direct target using say XHR).
XSSI is just CSRF applied to read APIs instead of action APIs. It exploits a loophole in the <script> tag allowing a js wormhole to form (APIs such as OpenSocial actually use the wormhole exploit validly).
A lot of sites out there (like the Google example, but our API makes this wrong assumption also), assume that they only need to protect against CSRF forgeries on action events and thus are vulnerable to data leak on read events as the user.
…
BTW, our (current) security policy isn't technically complete. The following exploits are currently able to be done in XSSI:
* JSONP: All JSONP can be attacked this way. Currently this is blocked due to the restriction that started this thread * Overriding Array constructor (this is the Google example below): This has been fixed in most browsers. Also, our root level JSON return is an object, not arrays. * Overriding Objects using __defineSetter__ (! see below) * Overriding Objects using UTF-7 encoding (see below)
## __defineSetter__ ##
This can be done, and most security experts icorrectly say the Array is vulnerable while the object is not: https://www.owasp.org/index.php/OWASP_AJAX_Security_Guidelines#Always_return_JSON_with_an_Object_on_the_outside
An example attack might look like this:
<script type="text/javascript"> Object.prototype.__defineSetter__('query', function(x) { alert(x); }); </script> <script type="text/javascript" src="http://en.wikipedia.org/w/api.php?action=query&list=watchlist&format=json"></script>
The above code run from anywhere will alert your private watchlist data (assuming you're on a browser that implements the __defineSetter__ part ECMAscript… in other words if you're in IE8 or earlier, you're safe). However, because this vulnerability/exploit is so prevalent, this was patched in many browsers. For instance, I think Firefox patched by 2009 https://bugzilla.mozilla.org/show_bug.cgi?id=470041 (the XSSI exploit dates to 2006, and became well known in 2007). However, some browsers (Opera), don't consider this a bug (it's not. The "same origin" policy is very clear on this, but this security hole became rampantly exploited by 2008) and (I think) are still are vulnerable to this attack.
## UTF-7 encoding ##
Basically you do this
<script type="text/javascript" charset="utf-7" src="http://en.wikipedia.org/w/api.php?action=query&list=watchlist&format=json&echo=UTF-7 encoded exploit"></script>
This only works if there is a parameter inside the JSON return that can be injected and returned. Since I don't think there is an API parameter we have that implements return injection (I'm not familiar with the MW API yet), I don't think this exploit can be done on our API.
If you are curious:
http://www.thespanner.co.uk/2009/11/23/bypassing-csp-for-fun-no-profit/
Net result: Our policy is a hack that protects against XSSI read exploits if your browser is less than 3 years old enough and is not Opera.
## What we should probably have done ##
A better policy is to implement a standard CSRF barrier (shared secret). State changing APIs are already protected using the edit token https://www.mediawiki.org/wiki/Manual:Edit_token (acts shared secret), but the same should be true (optionally) for all API calls, even read ones. The optional shared secret could be the session ID for all I care (remember in CSRF attacks, session token is not revealed by the attacker, but forged).
- if it is not provided, then the client is treated as an anonymous user - if it is provided but doesn't match the session then the client is treated as an anonymous user - if it is provided and matches then the client can be treated as the user
Then:
- state-changing actions should be blocked simply by the user being anonymous in the above cases - login actions should be allowed (it's irrelevant if jsonp or not since it requires the user's credentials to successfully run action=login and in our API is a two step process that blocks CSRF hard. - jsonp for state changing should be allowed (if it isn't already) since they require an edit token (shared secret) [QUESTION: is this prevented or is the API documentation in error? It should be allowed. The edittoken blocks XSSI and CSRF exploits already. "This means that things that require additional rights, such as rcprop=patrolled, won't work unless anonymous users are allowed to use them." I don't know what that means… rcprop=patrolled is a query=list operation. :-(]
Unfortunately, default anon unless secret provided for all API calls would break the bots. :-(
Take care,
terry
On May 16, 2012, at 2:28 PM, Daniel Renfro wrote:
Ah, XSS -- of course. Please excuse my temporary lapse of security-awareness. -Daniel
-----Original Message----- From: wikitech-l-bounces@lists.wikimedia.org [mailto:wikitech-l-bounces@lists.wikimedia.org] On Behalf Of Chris Steipp Sent: Wednesday, May 16, 2012 3:28 PM To: Wikimedia developers Subject: Re: [Wikitech-l] reasons for api json callback restrictions
Hi Daniel,
The restrictions prevent a class of attacks that go by the name "javascript hijacking" [1] or "xssi" [2]. This is where a malicious website (evil.com) includes the json (wrapped in the callback) from a <script src=some_url /> tag. The Javascript rules say that if evil.com included the javascript file from a script src link, then any javascript on the page (written by evil.com) has full access to the variables and javascript code on the page. So evil.com could send the tokens off to an attacker for use, or it could do a csrf attack right there from evil.com. GMail was bit by this a few years ago [3].
Hopefully that makes sense, but let me know if you want any more details!
Chris
[1] - http://en.wikipedia.org/wiki/JavaScript#Cross-site_vulnerabilities [2] - http://google-gruyere.appspot.com/part3 [3] - http://jeremiahgrossman.blogspot.com/2006/01/advanced-web-attack-techniques-...
On Wed, May 16, 2012 at 11:27 AM, Daniel Renfro drenfro@vistaprint.comwrote:
Can someone explain the reason for the limitations for the JSON callbacks? I'm sure there are good reasons, but they're nonobvious to me. See: < https://www.mediawiki.org/wiki/API:Data_formats#JSON_callback_restrictions >
-Daniel (User:DanielRenfro)
Wikitech-l mailing list Wikitech-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/wikitech-l
Wikitech-l mailing list Wikitech-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/wikitech-l
Wikitech-l mailing list Wikitech-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/wikitech-l
On May 16, 2012, at 4:37 PM, Terry Chay wrote:
BTW, our (current) security policy isn't technically complete. The following exploits are currently able to be done in XSSI:
Terry scares the crap out of me sometimes.
--- Brandon Harris, Senior Designer, Wikimedia Foundation
Support Free Knowledge: http://wikimediafoundation.org/wiki/Donate
On Wed, May 16, 2012 at 4:37 PM, Terry Chay tchay@wikimedia.org wrote:
- jsonp for state changing should be allowed (if it isn't already) since they require an edit token (shared secret) [QUESTION: is this prevented or is the API documentation in error? It should be allowed. The edittoken blocks XSSI and CSRF exploits already. "This means that things that require additional rights, such as rcprop=patrolled, won't work unless anonymous users are allowed to use them." I don't know what that means… rcprop=patrolled is a query=list operation. :-(]
Currently, JSONP immediately drops all privileges (i.e. treats you as an anon) and will refuse to provide any tokens. rcprop=patrolled is a query=list operation, yes, but it requires additional privileges (the right to see the patrolled-ness of changes) that typically aren't given to anons. Similarly, list=deletedrevs (shows deleted history, restricted to administrators) won't work either, and list=watchlist will give you an error message about how you need to be logged in to view your watchlist.
Dropping privileges for JSONP is needed to prevent data leaks as described above. Not providing tokens is necessary to prevent CSRF, because using tokens for CSRF protection relies on the fact that scripts cannot read (but can execute) code from another domain.
State-changing actions over JSONP are theoretically allowed, but you could only do them as an anon and you would have to hard-code the token (the token for anons is always the same), because the API won't give you one (theoretically unnecessary, because you'd get an anonymous token, but good for extra paranoia). You can't do state-changing actions as a logged-in user over JSONP because of the privilege dropping, but even if we didn't drop privileges if a valid token is provided, that token could not have been obtained using JSONP (otherwise our CSRF protection would be broken), so I don't see how that would be useful in practice.
Roan
wikitech-l@lists.wikimedia.org