Firefox Lite history.replaceState same-origin check failure
Categories
(Emerging Markets Graveyard :: Security: Firefox Lite, defect)
Tracking
(Not tracked)
People
(Reporter: dveditz, Assigned: st3fan)
References
Details
(Keywords: csectype-spoof, reporter-external, sec-high, Whiteboard: [reporter-external] [client-bounty-form] [verif?])
Attachments
(1 file)
|
742 bytes,
patch
|
Details | Diff | Splinter Review |
+++ This bug was initially created as a clone of Bug #1681103 +++
bug 1681103 comment 3 and following describes a separate issue that I'm moving to this bug.
testcase: attachment 9194803 [details]
result: attachment 9194804 [details]
There seem to be two failures to follow the specified behavior:
- relative URL is resolved wrt to baseURI (minor, annoying)
- there is no same-origin check (horrifyingly insecure)
I don't have a Firefox Lite to experiment with so I don't know if the same-origin check is always skipped or if it's only skipped in the case of relative URLs, but either way this POC demonstrates exactly why that restriction is in the standard!
I'm surprised either of these would be performed by the FF Lite browser front-end. I would have expected replaceState and pushState would be executed by the underlying platform WebView and the security checks should be at that level.
Irvan: what device do you have and android version? Does the default browser, or other WebView-based browsers have the same problem on your device? In bug 1581103 comment 0 you say the original problem doesn't reproduce in other browsers so it's likely you already tried this, but I'm very surprised at the thought of rolling our own replaceState() implementation.
| Reporter | ||
Comment 1•4 years ago
|
||
From Irvan in bug 1681103 comment 6:
The root cause of perfectspoof.html at comment 3 is when JS execute
window.history.replaceState("", "", location.href), the WebViewonPageFinishedis pointing to the base hrefhttps://accounts.google.com/signin/v2/identifier, surprisingly it pass theurlto WebViewClientdoUpdateVisitedHistory(WebView view, String url, boolean isReload)On Firefox Lite it also update the address bar when
doUpdateVisitedHistoryis called by passingString urlparameter to update the address bar. Because of that condition Firefox Lite updated the address bar tohttps://accounts.google.com/signin/v2/identifier.We can view the code at
app/src/webkit/java/org/mozilla/focus/webkit/FocusWebViewClient.javaI confirmed by changing the code fromviewClient.onURLChanged(url)toviewClient.onURLChanged(view.getUrl())it solve the perfectspoof.html bug.
| Reporter | ||
Comment 2•4 years ago
|
||
Interesting: cloning a bug keeps the keywords but not the flags. restoring sec-bounty? because this is definitely worth consideration separately from bug 1681103
Comment 3•4 years ago
|
||
(In reply to Daniel Veditz [:dveditz] from comment #0)
I don't have a Firefox Lite to experiment with so I don't know if the same-origin check is always skipped or if it's only skipped in the case of relative URLs, but either way this POC demonstrates exactly why that restriction is in the standard!
Thanks Daniel for moving this into separate bug, you can also try this on Android Emulator, but I encourage to try this on real device, because on Android emulator I experienced the Play Store stuck when Android WebView to latest version, I have to clear Play Store data to make it work.
Currently I think the bug is only affect the address bar, because on Firefox Lite it update the address bar when it listen WebViewClient doUpdateVisitedHistory(WebView view, String url, boolean isReload) Firefox lite takes the String url to update the address bar.
There seem to be two failures to follow the specified behavior:
- relative URL is resolved wrt to baseURI (minor, annoying)
- there is no same-origin check (horrifyingly insecure)
I didn't know whether it able to bypass SOP, but it worth to investigate.
I'm surprised either of these would be performed by the FF Lite browser front-end. I would have expected
replaceStateandpushStatewould be executed by the underlying platform WebView and the security checks should be at that level.
Yes I also surprised when JS execute window.history.replaceState("", "", location.href), the WebView onPageFinished is pointing to the base href https://accounts.google.com/signin/v2/identifier then pass this to doUpdateVisitedHistory(WebView view, String url, boolean isReload).
Irvan: what device do you have and android version? Does the default browser, or other WebView-based browsers have the same problem on
your device?
I'm currently using Xiaomi 9T on Android 10 with WebView version 87.0.4280.101 (Updated on Dec 7, 2020). I also able to reproduce this on Android Emulator API 29.
Comment 4•4 years ago
|
||
(In reply to Daniel Veditz [:dveditz] from comment #0)
or other WebView-based browsers have the same problem on your device?
Currently I can't reproduce this on another WebView based browser, I think other WebView-based browser doesn't take String url from WebViewClient doUpdateVisitedHistory to update the address bar.
The hotfix patch as mentioned on comment 1 is to refactor Firefox Lite to not update the address bar using String url from WebView doUpdateVisitedHistory.
I hope we can push the fix as there are a lot user using Firefox Lite (according to Google Play Store).
Comment 5•4 years ago
|
||
(In reply to my comment #3)
I didn't know whether it able to bypass SOP, but it worth to investigate.
Sorry on comment 3, I was think same-origin in context of UXSS.
Comment 6•4 years ago
|
||
(In reply to Daniel Veditz [:dveditz] from comment #0)
There seem to be two failures to follow the specified behavior:
- relative URL is resolved wrt to baseURI (minor, annoying)
- there is no same-origin check (horrifyingly insecure)
Edit: Yes, it able to bypass same-origin check on the Firefox Lite address bar using history.replaceState.
On the Stack Overflow there are answer to update the WebViewClient address bar using String url from WebView doUpdateVisitedHistory. Therefore, all WebView-based applications that update the address bar using that method are affected to this spoof.
Comment 7•4 years ago
|
||
Herewith I attach the patch to address the Firefox Lite history.replaceState same-origin bypass. When doUpdateVisitedHistory is called, it will take view.getURL() to update the address bar using URL of the current page.
(So i.e. https://www.attacker.com called history.replaceState("https://www.google.com") it's no longer possible)
After testing this patch for a day, I confirmed the address bar is still working as it should, so I consider it safe to push the current patch.
Comment 8•4 years ago
|
||
As far I know from various sources including Mozilla Blog L10n Report: December 2020 Edition and mozilla-tw/FirefoxLite repository status, the development of Firefox Lite has been dropped since September 25, 2020.
With this severe full address bar spoof with secure lock (only by visiting website), is it still possible Dan for Mozilla team to merge the hotfix patch then update this to Google Play Store?
Comment 9•4 years ago
|
||
(In reply to Irvan Kurniawan (:sourc7) from comment #8)
As far I know from various sources including Mozilla Blog L10n Report: December 2020 Edition and mozilla-tw/FirefoxLite repository status, the development of Firefox Lite has been dropped since September 25, 2020.
With this severe full address bar spoof with secure lock (only by visiting website), is it still possible Dan for Mozilla team to merge the hotfix patch then update this to Google Play Store?
setting needinfo for this.
| Reporter | ||
Comment 10•4 years ago
|
||
(In reply to Irvan Kurniawan (:sourc7) from comment #8)
With this severe full address bar spoof with secure lock (only by visiting website), is it still possible Dan for Mozilla team to merge the hotfix patch then update this to Google Play Store?
I honestly do not know if we are able to do that.
David: There was supposed to be clarity about the status of Firefox Lite last week. This bug is the Holy Grail for phishers and we either need to ship a fix ASAP or publicly pull the plug on Firefox Lite and tell people to migrate to another browser.
Comment 11•4 years ago
|
||
Thanks for the escalation Dan. Per email thread I don't think we'll get to the larger strategic decision on FF LIte before we need to fix this. Stefan has offered to drive here, thanks!
| Assignee | ||
Comment 12•4 years ago
|
||
(In reply to Daniel Veditz [:dveditz] from comment #10)
(In reply to Irvan Kurniawan (:sourc7) from comment #8)
With this severe full address bar spoof with secure lock (only by visiting website), is it still possible Dan for Mozilla team to merge the hotfix patch then update this to Google Play Store?
I honestly do not know if we are able to do that.
David: There was supposed to be clarity about the status of Firefox Lite last week. This bug is the Holy Grail for phishers and we either need to ship a fix ASAP or publicly pull the plug on Firefox Lite and tell people to migrate to another browser.
We will be actively working on getting this fix out soon.
Irvan, thank you very much for both the report and the patch. Please allow us some time to include this into an update. Consider this work in progress as of today.
Comment 13•4 years ago
|
||
(In reply to Stefan Arentz | :st3fan | ⏰ EST | he/him from comment #12)
We will be actively working on getting this fix out soon.
Irvan, thank you very much for both the report and the patch. Please allow us some time to include this into an update. Consider this work in progress as of today.
Thanks Stefan for the update,
I'm glad to be able to provide bug analysis and patches for Mozilla. Debugging on Android project is much easier, thanks to the Android Studio IDE.
Yes, I agree it will take some time to include the update, within that time we can test the patch, I hope it will be reliable (i.e. doesn't create new issue to user) and completely solves the address bar spoofing issue.
| Assignee | ||
Comment 14•4 years ago
|
||
Irvan, we just finished testing and can confirm both the bug and patch. We're working on a plan now to roll this out.
One thing that we were wondering is whether this is a WebView bug or not. It seems odd that the push state for a website from a different origin is kept or allowed to be in the push state. Do you have any insight on that?
| Assignee | ||
Comment 15•4 years ago
•
|
||
Asking :sebastian to verify the patch. We know it works, but I think we would like to understand the underlying problem better to be more confident that this is the only place and the only product.
The easiest way to reproduce this is to load https://bugzilla.mozilla.org/attachment.cgi?id=9194803 into Lite. It will show a Google Sign-In page, with a google URL, while the page is really on bugzilla. (I can help)
| Assignee | ||
Updated•4 years ago
|
Comment 16•4 years ago
|
||
(In reply to Stefan Arentz | :st3fan | ⏰ EST | he/him from comment #14)
One thing that we were wondering is whether this is a WebView bug or not. It seems odd that the push state for a website from a different origin is kept or allowed to be in the push state. Do you have any insight on that?
My insight is on comment 1 (quoted by Daniel from bug 1681103 comment 6), in summary as below:
Currently Firefox Lite is listen to WebViewClient doUpdateVisitedHistory(WebView view, String url, boolean isReload), then take the String url from the method to update the address bar.
The problem is when JS execute window.history.replaceState("", "", location.href), the WebView onPageFinished is also pointing to the base href (on perfectspoof.html is set base href to https://accounts.google.com/signin/v2/identifier).
Surprisingly the onPageFinished also pass the url to doUpdateVisitedHistory(WebView view, String url, boolean isReload), therefore the address bar is now changed (spoofed) to the base href.
Comment 17•4 years ago
|
||
(In reply to my comment #16)
Surprisingly the onPageFinished also pass the url to doUpdateVisitedHistory(WebView view, String url, boolean isReload), therefore the address bar is now changed (spoofed) to the base href.
After further testing, it turns out that onPageFinished doesn't have to point to a spoofed URL, so I can say onPageFinished doesn't necessarily affect the url variable to the doUpdateVisitedHistory method.
(In reply to Stefan Arentz | :st3fan | ⏰ EST | he/him from comment #14)
It seems odd that the push state for a website from a different origin is kept or allowed to be in the push state. Do you have any insight on that?
Oh I got your point Stefan,
From my analysis WebViewClient doesn't allow push state or replace state from different origin, we can try from DevTools after insert JS command window.history.replaceState("", "", "https://different-origin.example,"), it will return an error "Failed to execute 'replaceState' on 'History': A history state object with URL...".
I found we can also do the spoof by calling location.href = `${location.href}#test` with url fragment.
I'm not sure whether it's a bug on WebViewClient that it shouldn't happen, or the WebViewClient doUpdateVisitedHistory is working as intended (on the API docs parameter url: The url being visited) (in this case passing the base href as the String url), then FF Lite misuse the doUpdateVisitedHistory callback to update the address bar.
The way how WebViewClient doUpdateVisitedHistory is works is at https://chromium.googlesource.com/chromium/src.git/+/refs/heads/master/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java on didFinishNavigation method.
Updated•4 years ago
|
| Assignee | ||
Comment 18•4 years ago
|
||
We are on track to ship this fix very soon.
Comment 19•4 years ago
|
||
(In reply to Stefan Arentz | :st3fan | ⏰ EST | he/him from comment #18)
We are on track to ship this fix very soon.
Thanks Stefan for the progress!
I found another address bar spoof w/ secure lock using back button, reported on bug 1688979, I hope we can also address this.
| Assignee | ||
Comment 20•4 years ago
|
||
We shipped an update with this patch included. The security advisory is at https://github.com/mozilla-mobile/FirefoxLite/security/advisories/GHSA-vm4v-cxqj-jjgm
| Assignee | ||
Updated•4 years ago
|
Comment 21•4 years ago
|
||
(In reply to Stefan Arentz | :st3fan | ⏰ EST | he/him from comment #20)
We shipped an update with this patch included. The security advisory is at https://github.com/mozilla-mobile/FirefoxLite/security/advisories/GHSA-vm4v-cxqj-jjgm
Thank you Stefan and other Mozilla Team for pushing the patch to the Google Play Store!
I confirmed the vulnerability has been fixed on Firefox Lite 2.6.0 (20651) (Release date Jan 28, 2021).
| Assignee | ||
Comment 22•4 years ago
|
||
Closing this bug since we shipped a fix.
Updated•4 years ago
|
Updated•4 years ago
|
| Reporter | ||
Updated•3 years ago
|
Updated•1 year ago
|
Description
•