Leaking Browser URL/Protocol Handlers by img onerror loading time
Categories
(Core :: Networking, defect, P2)
Tracking
()
People
(Reporter: t.satoki111, Assigned: valentin)
References
Details
(Keywords: csectype-disclosure, reporter-external, sec-moderate, Whiteboard: [reporter-external] [client-bounty-form] [verif?][necko-triaged][necko-priority-queue][adv-main127+][adv-esr115.12+])
Attachments
(6 files)
|
3.23 KB,
text/html
|
Details | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
phab-bot
:
approval-mozilla-esr115+
|
Details | Review |
|
48 bytes,
text/x-phabricator-request
|
phab-bot
:
approval-mozilla-esr115+
|
Details | Review |
|
215 bytes,
text/plain
|
Details |
Hello, I'm Satoki, a CTF player and security engineer. Inspired by CVE-2020-15680, I've discovered a new leak involving external protocol handlers. The mechanism is simple: it measures the time from when the loading of an "img" tag starts to when the "onerror" event is triggered. I've found that if a handler exists, there's a delay in response.
Threshold: 455ms
amazon:// : 437ms
ftp:// : 853ms
geo:// : 400ms
instagram:// : 392ms
mailto:// : 2527ms
ms-edge:// : 401ms
ms-store:// : 441ms
onenote:// : 952ms
skype:// : 395ms
slack:// : 901ms
sms:// : 470ms
spotify:// : 886ms
steam:// : 834ms
tel:// : 1619ms
twitch:// : 474ms
twitter:// : 455ms
whatsapp:// : 406ms
zoommtg:// : 873ms
No user interaction is required for this leak. I'm attaching poc_img.html, but the behavior is the same when deployed on a server.
Have you become a bit tired of me reporting similar vulnerabilities every time? I apologize ;(
Updated•1 year ago
|
Comment 1•1 year ago
|
||
Nika found that we don't create the channel at all if the external protocol handler doesn't exist, so that may be causing the issue.
Comment 2•1 year ago
|
||
Tom, how much do we care about this kind of fingerprinting for external handlers? Thanks.
Comment 3•1 year ago
|
||
I am guessing this is because of how and when we detect that the protocol handler doesn't exist. We appear to do external protocol handler existence checks when trying to create the ext protocol handler channel, which means the check is done before we have done content security checks. This could mean that the behaviour & timing of the error is slightly different if the handler exists vs. if it doesn't.
This might be as simple as removing the check to avoid creating the channel if the protocol handler doesn't exist (https://searchfox.org/mozilla-central/rev/6b0b8c1003504e302e243c300355ef4d61e24909/uriloader/exthandler/nsExternalProtocolHandler.cpp#523-529), and then instead making the channel fail to open in that case, by switching the debug check in OpenURL to a runtime check which sets rv = NS_ERROR_UNKNOWN_PROTOCOL and goto finish;-es (https://searchfox.org/mozilla-central/rev/6b0b8c1003504e302e243c300355ef4d61e24909/uriloader/exthandler/nsExternalProtocolHandler.cpp#152-161).
Not sure what other impacts this change might have (we may have some places where we're relying on the exception happening when the channel is created rather than when the channel is opened?).
Could be interesting to confirm if this timing change would disappear with this change.
Comment 4•1 year ago
|
||
(In reply to Andrew McCreight [:mccr8] from comment #2)
Tom, how much do we care about this kind of fingerprinting for external handlers? Thanks.
We (Emilio IIRC) made a concerted effort to remove this leak, so this vector is unfortunate and we would like to fix it to be consistent with our previous goals, but it's a sec-moderate at a stretch.
Comment 5•1 year ago
|
||
Have you become a bit tired of me reporting similar vulnerabilities every time? I apologize ;(
Not yet :-)
When I was looking into bug 1882364 this morning I found the same chunk of code Nika flagged in comment 3, confirming my suspicion these are different symptoms of the same bug. But it's also possible we would have fixed just one of these on its own with a narrower fix that didn't address the others if we didn't know about them all.
Comment 6•1 year ago
•
|
||
Hi Valentin, are you or your team the right person to confirm comment 3? Perhaps Networking is a better component for this issue?
Updated•1 year ago
|
| Reporter | ||
Comment 7•1 year ago
|
||
I had not been reporting sec-low because it is sec-moderate, but by timing this image, it is possible to leak local files from the HTML files of Bug 1882827 and Bug 1884580. You just need to specify the file scheme instead of a custom scheme.
| Assignee | ||
Comment 8•1 year ago
|
||
(In reply to Hsin-Yi Tsai (she/her) [:hsinyi] from comment #6)
Hi Valentin, are you or your team the right person to confirm comment 3? Perhaps
Networkingis a better component for this issue?
Hi Hsin-Yi, not sure if this is a pure Networking bug. There's a bit of overlap with other components.
If there's no one else who can work on this we can take it, though I'm not able to access many of the bugs referenced here.
Updated•1 year ago
|
Comment 9•1 year ago
|
||
(In reply to Valentin Gosu [:valentin] (he/him) from comment #8)
If there's no one else who can work on this we can take it, though I'm not able to access many of the bugs referenced here.
I went ahead and CC'ed you on all of them (hopefully) in case that helps.
| Assignee | ||
Updated•1 year ago
|
| Assignee | ||
Comment 10•1 year ago
|
||
(In reply to Nika Layzell [:nika] (ni? for response) from comment #3)
This might be as simple as removing the check to avoid creating the channel if the protocol handler doesn't exist (https://searchfox.org/mozilla-central/rev/6b0b8c1003504e302e243c300355ef4d61e24909/uriloader/exthandler/nsExternalProtocolHandler.cpp#523-529), and then instead making the channel fail to open in that case, by switching the debug check in
OpenURLto a runtime check which setsrv = NS_ERROR_UNKNOWN_PROTOCOLandgoto finish;-es (https://searchfox.org/mozilla-central/rev/6b0b8c1003504e302e243c300355ef4d61e24909/uriloader/exthandler/nsExternalProtocolHandler.cpp#152-161).
Could be interesting to confirm if this timing change would disappear with this change.
Excellent suggestion. I can confirm that the above changes make the timing issues disappear - at least on Linux. Will test with other platforms next.
Not sure what other impacts this change might have (we may have some places where we're relying on the exception happening when the channel is created rather than when the channel is opened?).
As far as I can tell, nsOSHelperAppService::LoadUriInternal was removed, so this comment no longer applies.
Also, I can't find any places that rely on .newChannel throwing NS_ERROR_UNKNOWN_PROTOCOL for security checks.
| Assignee | ||
Comment 11•1 year ago
|
||
Updated•1 year ago
|
Comment 12•1 year ago
|
||
(In reply to Valentin Gosu [:valentin] (he/him) from comment #10)
(In reply to Nika Layzell [:nika] (ni? for response) from comment #3)
Not sure what other impacts this change might have (we may have some places where we're relying on the exception happening when the channel is created rather than when the channel is opened?).
As far as I can tell, nsOSHelperAppService::LoadUriInternal was removed, so this comment no longer applies.
Also, I can't find any places that rely on .newChannel throwing NS_ERROR_UNKNOWN_PROTOCOL for security checks.
I'm kind of wondering about landing this kind of change in a separate public bug as a refactoring. I expect some test failures / fallout. AIUI the impact on timing and this bug is somewhat indirect so perhaps that would simplify some things?
Comment 13•1 year ago
|
||
(In reply to :Gijs (he/him) from comment #12)
(In reply to Valentin Gosu [:valentin] (he/him) from comment #10)
Also, I can't find any places that rely on .newChannel throwing NS_ERROR_UNKNOWN_PROTOCOL for security checks.
Good catch! Not sure what the approach to take with this here is then, as this would definitely break in that case. I suppose we could manually check nsIExternalProtocolService from the JS code to check if the handler exists. It'd be a bit of a pain. Probably something like this after the uri is parsed (untested):
let handler = Services.io.getProtocolHandler(uri.scheme);
if (handler instanceof Ci.nsIExternalProtocolHandler &&
!handler.externalAppExistsForScheme(uri.scheme)) { // Unrelated note: I'm not sure why the scheme needs to be provided here?
uri = Services.io.newURI("file://" + url);
}
This would also remove the need to do the recursive calls in that function, I believe. I imagine this check is useful because of windows using C:\ drive names, which might parse as a c: external protocol? :valentin did you run into any xpcshell failures on windows after the changes?
This doesn't fix any other cases which we might not have caught which depend on it though, and the fact :gijs found one means there are somewhat likely to be others.
I'm kind of wondering about landing this kind of change in a separate public bug as a refactoring. I expect some test failures / fallout. AIUI the impact on timing and this bug is somewhat indirect so perhaps that would simplify some things?
Yeah, this could probably be done on a public bug as a refactoring fairly easily.
| Assignee | ||
Comment 14•1 year ago
|
||
| Assignee | ||
Comment 15•1 year ago
|
||
| Assignee | ||
Comment 16•1 year ago
|
||
Try doesn't seem to show any issues coming from this patch. I'm inclined to land it.
Updated•1 year ago
|
Comment 17•1 year ago
|
||
Comment 18•1 year ago
|
||
Comment 19•1 year ago
|
||
Backed out for causing bustage on nsExternalProtocolHandler.cpp:
Push with failures
Failure log
uriloader/exthandler/nsExternalProtocolHandler.cpp:151:18: error: use of undeclared identifier 'MakeScopeExit'; did you mean 'mozilla::MakeScopeExit'?
Comment 20•1 year ago
|
||
Comment 21•1 year ago
|
||
Backed out for causing bustage
Push with failures
wpt Failure Log
| Assignee | ||
Updated•1 year ago
|
Comment 22•1 year ago
|
||
Comment 23•1 year ago
|
||
Comment 24•1 year ago
|
||
Push with failures
Failure log
[task 2024-05-01T00:20:00.497Z] 00:20:00 WARNING - TEST-UNEXPECTED-FAIL | devtools/shared/tests/xpcshell/test_fetch-file.js | xpcshell return code: 0
[task 2024-05-01T00:20:00.499Z] 00:20:00 INFO - TEST-INFO took 447ms
[task 2024-05-01T00:20:00.499Z] 00:20:00 INFO - >>>>>>>
[task 2024-05-01T00:20:00.500Z] 00:20:00 INFO - PID 4124 | DLL blocklist was unable to intercept AppInit DLLs.
[task 2024-05-01T00:20:00.500Z] 00:20:00 INFO - PID 4124 | [Parent 4124, Main Thread] WARNING: Failed to get directory to cache.: file /builds/worker/checkouts/gecko/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp:148
[task 2024-05-01T00:20:00.501Z] 00:20:00 INFO - PID 4124 | [Parent 4124, Main Thread] WARNING: Failed to get directory to cache.: file /builds/worker/checkouts/gecko/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp:148
[task 2024-05-01T00:20:00.502Z] 00:20:00 INFO - PID 4124 | [Parent 4124, Main Thread] WARNING: Couldn't get the user appdata directory. Crash events may not be produced.: file /builds/worker/checkouts/gecko/toolkit/crashreporter/nsExceptionHandler.cpp:2924
[task 2024-05-01T00:20:00.502Z] 00:20:00 INFO - (xpcshell/head.js) | test MAIN run_test pending (1)
[task 2024-05-01T00:20:00.502Z] 00:20:00 INFO - (xpcshell/head.js) | test run_next_test 0 pending (2)
[task 2024-05-01T00:20:00.503Z] 00:20:00 INFO - (xpcshell/head.js) | test MAIN run_test finished (2)
[task 2024-05-01T00:20:00.503Z] 00:20:00 INFO - running event loop
[task 2024-05-01T00:20:00.503Z] 00:20:00 INFO - devtools/shared/tests/xpcshell/test_fetch-file.js | Starting test_arrow_urls
[task 2024-05-01T00:20:00.503Z] 00:20:00 INFO - (xpcshell/head.js) | test test_arrow_urls pending (2)
[task 2024-05-01T00:20:00.503Z] 00:20:00 INFO - (xpcshell/head.js) | test run_next_test 0 finished (2)
[task 2024-05-01T00:20:00.504Z] 00:20:00 INFO - PID 4124 | [Parent 4124, Main Thread] WARNING: Couldn't get the user appdata directory, crash dumps will go in an unusual location: file /builds/worker/checkouts/gecko/toolkit/crashreporter/nsExceptionHandler.cpp:2982
[task 2024-05-01T00:20:00.505Z] 00:20:00 INFO - PID 4124 | [Parent 4124, Main Thread] WARNING: Couldn't get the user appdata directory. Crash events may not be produced.: file /builds/worker/checkouts/gecko/toolkit/crashreporter/nsExceptionHandler.cpp:2924
[task 2024-05-01T00:20:00.505Z] 00:20:00 INFO - TEST-PASS | devtools/shared/tests/xpcshell/test_fetch-file.js | test_arrow_urls - [test_arrow_urls : 31] The file contents were correctly read. - "ad" deepEqual "ad"
[task 2024-05-01T00:20:00.505Z] 00:20:00 INFO - (xpcshell/head.js) | test run_next_test 1 pending (2)
[task 2024-05-01T00:20:00.506Z] 00:20:00 INFO - (xpcshell/head.js) | test test_arrow_urls finished (2)
[task 2024-05-01T00:20:00.506Z] 00:20:00 INFO - devtools/shared/tests/xpcshell/test_fetch-file.js | Starting test_empty
[task 2024-05-01T00:20:00.506Z] 00:20:00 INFO - (xpcshell/head.js) | test test_empty pending (2)
[task 2024-05-01T00:20:00.506Z] 00:20:00 INFO - (xpcshell/head.js) | test run_next_test 1 finished (2)
[task 2024-05-01T00:20:00.507Z] 00:20:00 INFO - TEST-PASS | devtools/shared/tests/xpcshell/test_fetch-file.js | test_empty - [test_empty : 40] The empty file was read correctly. - "" deepEqual ""
[task 2024-05-01T00:20:00.507Z] 00:20:00 INFO - (xpcshell/head.js) | test run_next_test 2 pending (2)
[task 2024-05-01T00:20:00.507Z] 00:20:00 INFO - (xpcshell/head.js) | test test_empty finished (2)
[task 2024-05-01T00:20:00.507Z] 00:20:00 INFO - devtools/shared/tests/xpcshell/test_fetch-file.js | Starting test_encoding_utf8
[task 2024-05-01T00:20:00.508Z] 00:20:00 INFO - (xpcshell/head.js) | test test_encoding_utf8 pending (2)
[task 2024-05-01T00:20:00.508Z] 00:20:00 INFO - (xpcshell/head.js) | test run_next_test 2 finished (2)
[task 2024-05-01T00:20:00.508Z] 00:20:00 INFO - PID 4124 | DLL blocklist was unable to intercept AppInit DLLs.
[task 2024-05-01T00:20:00.509Z] 00:20:00 INFO - PID 4124 | JavaScript error: resource://gre/modules/ExtHandlerService.sys.mjs, line 57: NS_ERROR_FAILURE: Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIProperties.get]
[task 2024-05-01T00:20:00.510Z] 00:20:00 INFO - PID 4124 | [Parent 4124, Main Thread] WARNING: NS_ENSURE_SUCCESS(rv, rv) failed with result 0x805E0006 (NS_ERROR_CONTENT_BLOCKED): file /builds/worker/checkouts/gecko/dom/security/nsContentSecurityManager.cpp:1456
[task 2024-05-01T00:20:00.510Z] 00:20:00 INFO - Unexpected exception NS_ERROR_CONTENT_BLOCKED: Failed to open input source 'c:\\Users\\task_171451964454847\\AppData\\Local\\Temp\\test_fetch-file-0.042017455803060044'
[task 2024-05-01T00:20:00.510Z] 00:20:00 INFO - mainThreadFetch/<@resource://devtools/shared/DevToolsUtils.js:719:15
[task 2024-05-01T00:20:00.511Z] 00:20:00 INFO - mainThreadFetch@resource://devtools/shared/DevToolsUtils.js:566:10
[task 2024-05-01T00:20:00.511Z] 00:20:00 INFO - test_encoding_utf8@D:/task_171451964454847/build/tests/xpcshell/tests/devtools/shared/tests/xpcshell/test_fetch-file.js:50:43
[task 2024-05-01T00:20:00.511Z] 00:20:00 INFO - _do_main@D:\task_171451964454847\build\tests\xpcshell\head.js:245:6
[task 2024-05-01T00:20:00.512Z] 00:20:00 INFO - _execute_test@D:\task_171451964454847\build\tests\xpcshell\head.js:596:5
[task 2024-05-01T00:20:00.512Z] 00:20:00 INFO - @-e:1:1
[task 2024-05-01T00:20:00.512Z] 00:20:00 INFO - exiting test
| Assignee | ||
Updated•1 year ago
|
Comment 25•1 year ago
|
||
Comment 26•1 year ago
|
||
https://hg.mozilla.org/mozilla-central/rev/d25baafab824
https://hg.mozilla.org/mozilla-central/rev/a887767c0627
Updated•1 year ago
|
Updated•1 year ago
|
Updated•1 year ago
|
Comment 28•1 year ago
|
||
Please request ESR uplift on this when you get a chance.
| Assignee | ||
Comment 29•1 year ago
|
||
Updated•1 year ago
|
| Assignee | ||
Comment 30•1 year ago
|
||
Updated•1 year ago
|
Comment 31•1 year ago
|
||
esr115 Uplift Approval Request
- User impact if declined: privacy leak of OS application handlers.
- Code covered by automated testing: no
- Fix verified in Nightly: yes
- Needs manual QE test: yes
- Steps to reproduce for manual QE testing: see bug 1883693 comment 0
- Risk associated with taking this patch: Slight risk of test breakage.
- Explanation of risk level: Most of the externalProtocolHandler code hasn't changed since 115, but it's possible some of the affected tests have.
- String changes made/needed: None
- Is Android affected?: yes
| Assignee | ||
Updated•1 year ago
|
Updated•1 year ago
|
Reproduce the leak using an old Nightly build from 2024-03-04, I have lots of exposed handlers as Exist such as (ftp, mailto, skype, slack, steam, tel, whatsapp, zoommtg) and the Threshold is around 503ms on Windows 11 and different values for Ubuntu 22.04 (VM) (1454ms) and macOS 13.6 (350ms).
Verified that using latest Nightly 128 from today (2024-05-23), I have every handler from the attached poc file as Does not exist and the Threshold is severally decreased on Windows 11 (30ms), Ubuntu 22.04 (VM) (132ms) / Ubuntu 22.04 PC (230ms) and macOS 13.6 (66ms).
I did ran into a weird thing on the Ubuntu 22.04 VM that I have. After I load the poc file a few times, sometimes a few handlers are displayed as Exist from time to time and not the same handler (basically randomly). This did not happen on Ubuntu 22.04 installed on a PC. Could this be something influenced by the testcase itself or is there any reason for concern?
| Assignee | ||
Comment 33•1 year ago
|
||
(In reply to Bogdan Maris, Desktop QA from comment #32)
I did ran into a weird thing on the Ubuntu 22.04 VM that I have. After I load the poc file a few times, sometimes a few handlers are displayed as Exist from time to time and not the same handler (basically randomly). This did not happen on Ubuntu 22.04 installed on a PC. Could this be something influenced by the testcase itself or is there any reason for concern?
The code is probably running slower on the VM and it's randomly exceeding the limit.
I think this should be OK. @Nika, do you think this requires more investigation?
Comment 34•1 year ago
|
||
Yeah, it seems likely based on the other numbers associated with that VM that the machine is running slower, and being given less reliable scheduling, which could lead to random longer gaps. I don't think there's much more worth investigating there.
Thanks for your feedback, I'm going to close this as verified fixed for 127 since I also checked with Firefox 127.0b5 and I get similar results as with Latest Nightly. I'll leave the qe-verify+ flag on so I can verify on ESR when the fix lands there.
Updated•1 year ago
|
Updated•1 year ago
|
Updated•1 year ago
|
Updated•1 year ago
|
Comment 36•1 year ago
|
||
| uplift | ||
Updated•1 year ago
|
Updated•1 year ago
|
Updated•1 year ago
|
Comment 37•1 year ago
|
||
Updated•1 year ago
|
(In reply to Bogdan Maris, Desktop QA from comment #35)
Thanks for your feedback, I'm going to close this as verified fixed for 127 since I also checked with Firefox 127.0b5 and I get similar results as with Latest Nightly. I'll leave the qe-verify+ flag on so I can verify on ESR when the fix lands there.
Also verified fixed on 115.12.0esr across platforms (Windows 11, macOS 13.6 and Ubuntu 22.04).
Updated•1 year ago
|
Updated•10 months ago
|
Description
•