XS-Leaks with CSP (base-uri) bypass by img tag.
Categories
(Core :: DOM: Security, defect, P3)
Tracking
()
People
(Reporter: t.satoki111, Assigned: tschuster)
References
(Blocks 1 open bug)
Details
(Keywords: csectype-disclosure, sec-low, Whiteboard: [domsecurity-backlog1] [adv-main105+][adv-esr102.3+][post-critsmash-triage])
Attachments
(8 files)
603 bytes,
text/html
|
Details | |
125.66 KB,
image/png
|
Details | |
45.63 KB,
image/png
|
Details | |
22.77 KB,
text/plain
|
Details | |
48 bytes,
text/x-phabricator-request
|
RyanVM
:
approval-mozilla-esr102+
|
Details | Review |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
197 bytes,
text/plain
|
Details | |
53.20 KB,
image/png
|
Details |
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0
Steps to reproduce:
I have a Content-Security-Policy that restricts reading of the base tag to 'self'.
And checked if this restriction is effective by injecting HTML tags.
Actual results:
CSP appeared to have successfully prevented base tag injection.
However, from the img tag, it was confirmed that the request was sent to the URI specified in the base.
Only FireFox could get the secret path of a user's img tag by XS-Leaks.
The attached poc.html confirms the leakage of confidential information (uuid).
I am assuming an attack scenario where the profile URL is secret and the tag injection occurs on the top page.
Expected results:
A base tag blocked by CSP is invalid, and the img tag should issue a request to the original URI.
Updated•2 years ago
|
Comment 1•2 years ago
|
||
The attached testcase works correctly for me -- the two links (the image and the navigation) are relative to our attachment domain and ignore the base setting. I see CSP errors for both. Were you running two test servers in the same file directory? Could you capture a HAR log in DevTools showing it doing the wrong thing?
Reporter | ||
Comment 2•2 years ago
|
||
Reporter | ||
Comment 3•2 years ago
|
||
Reporter | ||
Comment 4•2 years ago
|
||
Thank you for verifying my report.
When you open the file you attached with "bmoattachments.org", other CSP settings (e.g. img-src) get in the way and disable base.
I would like you to try either temporarily saving it locally as a poc.html file or in an environment with CSP settings turned off except for base-uri.
I am attaching a screenshot of the actual screenshot I verified to show that I am not mistaken in my perception.
One is the same html that was submitted as a PoC on the site where the base-uri was specified.
leak1.png
The other is the server log to capture the request (requestbin).
leak2.png
Reporter | ||
Comment 5•2 years ago
|
||
As far as I know, if default-src 'none'
and img-src 'none'
are valid, there is no problem.
However, if they are not, a GET request is sent to the URI specified in base, which is leak even if base-uri 'none'
is set.
I have tried with the following CSP enabled, but it leaks.
base-uri 'none'; worker-src 'none'; connect-src 'none'; font-src 'none'; object-src 'none'; script-src 'none'; style-src 'none'; frame-src 'none'; frame-ancestors 'none'; form-action 'none'
Updated•2 years ago
|
Updated•2 years ago
|
Reporter | ||
Comment 7•2 years ago
|
||
Need any additional information?
I want to create a CTF XS-Leaks problem using this behavior and am waiting for a fix.
Comment 8•2 years ago
|
||
I'm attaching some logs that I gathered by running firefox with MOZ_LOG="CSPParser:5,CSPContext:5,CSMLog:5" firefox https://localhost:8000
.
It seems we are loading the image twice. I am quoting the most interesting bits here:
First, we parse the CSP and then do a TYPE_INTERNAL_IMAGE_PRELOAD
of the URL at the domain with the injected base URL
#DebugDoContentSecurityCheck Begin
[Child 22315: Main Thread]: V/CSMLog doContentSecurityCheck:
[Child 22315: Main Thread]: V/CSMLog processType: "webIsolated=http://localhost"
[Child 22315: Main Thread]: V/CSMLog channelURI: "https://attack.example.com/profile/img/b0190b16-41fb-9059-a680-9e5b47f24ce5.png"
[Child 22315: Main Thread]: V/CSMLog httpMethod: GET
[Child 22315: Main Thread]: D/CSMLog loadingPrincipal: "http://localhost:8000/poc.html"
[Child 22315: Main Thread]: D/CSMLog triggeringPrincipal: "http://localhost:8000/poc.html"
[Child 22315: Main Thread]: D/CSMLog principalToInherit: nullptr
[Child 22315: Main Thread]: V/CSMLog redirectChain:
[Child 22315: Main Thread]: V/CSMLog internalContentPolicyType: TYPE_INTERNAL_IMAGE_PRELOAD
[Child 22315: Main Thread]: V/CSMLog externalContentPolicyType: TYPE_IMAGE
[Child 22315: Main Thread]: V/CSMLog upgradeInsecureRequests: false
[Child 22315: Main Thread]: V/CSMLog initialSecurityChecksDone: false
[Child 22315: Main Thread]: V/CSMLog allowDeprecatedSystemRequests: false
[Child 22315: Main Thread]: D/CSMLog CSP:
[Child 22315: Main Thread]: V/CSMLog securityFlags:
[Child 22315: Main Thread]: V/CSMLog - SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT
[Child 22315: Main Thread]: V/CSMLog - SEC_ALLOW_CHROME
[Child 22315: Main Thread]: V/CSMLog httpsOnlyFirstStatus:
[Child 22315: Main Thread]: V/CSMLog - HTTPS_ONLY_UNINITIALIZED
[Child 22315: Main Thread]: V/CSMLog - HTTPS_ONLY_EXEMPT
[Child 22315: Main Thread]: D/CSMLog
#DebugDoContentSecurityCheck End
Then we ask the CSP if that location is allowed to be loaded - there is no CSP directive that disallows this:
[Child 22315: Main Thread]: D/CSPContext nsCSPContext::ShouldLoad, aContentLocation: https://attack.example.com/profile/img/b0190b16-41fb-9059-a680-9e5b47f24ce5.png
[Child 22315: Main Thread]: D/CSPContext >>>> aContentType: 38
[Child 22315: Main Thread]: D/CSPContext nsCSPContext::ShouldLoad, decision: load, aContentLocation: https://attack.example.com/profile/img/b0190b16-41fb-9059-a680-9e5b47f24ce5.png
[Child 22315: Main Thread]: D/CSPContext nsCSPContext::ShouldLoad, aContentLocation: https://attack.example.com/profile/img/b0190b16-41fb-9059-a680-9e5b47f24ce5.png
[Child 22315: Main Thread]: D/CSPContext >>>> aContentType: 38
[Child 22315: Main Thread]: D/CSPContext nsCSPContext::ShouldLoad, decision: load, aContentLocation: https://attack.example.com/profile/img/b0190b16-41fb-9059-a680-9e5b47f24ce5.png
After that, we see just another image request, but with a different content policy type, TYPE_INTERNAL_IMAGE
:
#DebugDoContentSecurityCheck Begin
[Child 22315: Main Thread]: V/CSMLog doContentSecurityCheck:
[Child 22315: Main Thread]: V/CSMLog processType: "webIsolated=http://localhost"
[Child 22315: Main Thread]: V/CSMLog channelURI: "http://localhost:8000/profile/img/b0190b16-41fb-9059-a680-9e5b47f24ce5.png"
[Child 22315: Main Thread]: V/CSMLog httpMethod: GET
[Child 22315: Main Thread]: D/CSMLog loadingPrincipal: "http://localhost:8000/poc.html"
[Child 22315: Main Thread]: D/CSMLog triggeringPrincipal: "http://localhost:8000/poc.html"
[Child 22315: Main Thread]: D/CSMLog principalToInherit: nullptr
[Child 22315: Main Thread]: V/CSMLog redirectChain:
[Child 22315: Main Thread]: V/CSMLog internalContentPolicyType: TYPE_INTERNAL_IMAGE
[Child 22315: Main Thread]: V/CSMLog externalContentPolicyType: TYPE_IMAGE
[Child 22315: Main Thread]: V/CSMLog upgradeInsecureRequests: false
[Child 22315: Main Thread]: V/CSMLog initialSecurityChecksDone: false
[Child 22315: Main Thread]: V/CSMLog allowDeprecatedSystemRequests: false
[Child 22315: Main Thread]: D/CSMLog CSP:
[Child 22315: Main Thread]: D/CSMLog - "base-uri 'self'"
[Child 22315: Main Thread]: V/CSMLog securityFlags:
[Child 22315: Main Thread]: V/CSMLog - SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT
[Child 22315: Main Thread]: V/CSMLog - SEC_ALLOW_CHROME
[Child 22315: Main Thread]: V/CSMLog httpsOnlyFirstStatus:
[Child 22315: Main Thread]: V/CSMLog - HTTPS_ONLY_UNINITIALIZED
[Child 22315: Main Thread]: V/CSMLog - HTTPS_ONLY_EXEMPT
[Child 22315: Main Thread]: D/CSMLog
#DebugDoContentSecurityCheck End
[Child 22315: Main Thread]: D/CSPContext nsCSPContext::ShouldLoad, aContentLocation: http://localhost:8000/profile/img/b0190b16-41fb-9059-a680-9e5b47f24ce5.png
[Child 22315: Main Thread]: D/CSPContext >>>> aContentType: 37
[Child 22315: Main Thread]: D/CSPContext nsCSPContext::ShouldLoad, decision: load, aContentLocation: http://localhost:8000/profile/img/b0190b16-41fb-9059-a680-9e5b47f24ce5.png
[Child 22315: Main Thread]: D/CSMLog
Again, the CSP does not disallow the load.
In summary, it seems that the image preloader is accepting the base tag without (or before) asking the CSP.
Comment 9•2 years ago
|
||
Thank you for reporting this bug and please apologize the long wait.
I'm marking this as sec-low because this CSP bug does not lead to XSS and it assumes an injection in the page.
Please let us know when and where you intend to cover this in your CTF.
Reporter | ||
Comment 10•2 years ago
|
||
Thank you for your detailed understanding.
I do not think it is critical as it assumes HTML injection.
I decided it was a bit risky and reported it :)
The CTF will take place in November or January and we are thinking of XS-Leaks the secret profile page (protected by CSP).
Comment 11•2 years ago
|
||
Emilio, from looking at Document::ResolvePreloadImage
, it seems we never respected the base tag protection from CSP here.
When does the preloader logic kick in and does it know about the CSP?
Wondering what the right hooks should be..
Comment 12•2 years ago
|
||
Preloads are triggered by the speculative parser, so before the DOM is built from the meta element.
It seems we apply the CSP meta tag once it's added to the DOM which is too late: https://searchfox.org/mozilla-central/rev/15b656909e77d3048d4652b894f79a8c719b4b86/dom/html/HTMLMetaElement.cpp#90-113
However it seems the speculative parser does know about the CSP meta tag:
So the question I guess is why the preload CSP is not applying.
Comment 13•2 years ago
|
||
Aha! Looking at `BaseURIForPreload´, it seems we just don't check the CSP.
We likely need a call into CSP like we have in SetBaseURIUsingFirstBaseWithHref
.
@Tom Schuster: Maybe you can add this to your backlog, but it shouldn't have to block the other important stuff you're doing.
Updated•2 years ago
|
Assignee | ||
Comment 14•2 years ago
|
||
Taking this, but I am currently still working on higher priority stuff.
Assignee | ||
Updated•2 years ago
|
Assignee | ||
Comment 15•2 years ago
|
||
Updated•2 years ago
|
Assignee | ||
Comment 16•2 years ago
|
||
Depends on D154518
Updated•2 years ago
|
Assignee | ||
Comment 17•2 years ago
|
||
https://hg.mozilla.org/integration/autoland/rev/3849f10b51546b8d2e92ba4b1c6b088f625b6d64
I just realized that this doesn't work when the CSP is delivered via the Content-Security-Policy header instead of the meta tag. Even though the comment in nsHtml5TreeOpExecutor::AddSpeculationCSP
seemed to suggest the opposite to me.
Assignee | ||
Updated•2 years ago
|
Comment 18•2 years ago
|
||
Landed: https://hg.mozilla.org/integration/autoland/rev/3849f10b51546b8d2e92ba4b1c6b088f625b6d64
Backed out because the patch was incomplete: https://hg.mozilla.org/integration/autoland/rev/c3fb0e962fae04391186a9a9cb658ec6072417be
Assignee | ||
Updated•2 years ago
|
Comment 19•2 years ago
|
||
Assignee | ||
Comment 20•2 years ago
|
||
This is leave open to have another version of the test that uses a Content-Security-Policy header instead of meta tag. Sadly I don't think we can just set this header on the main test page?
Comment 21•2 years ago
|
||
Why do ^headers^
files not work?
Assignee | ||
Comment 22•2 years ago
|
||
Why do ^headers^ files not work?
It does indeed work! Somehow I assumed it only works for other test files. I've updated the test. I am not quite sure what flags we usually use to remember checking in the security tests.
Assignee | ||
Updated•2 years ago
|
Assignee | ||
Updated•2 years ago
|
Comment 23•2 years ago
|
||
https://groups.google.com/a/mozilla.org/g/dev-platform/c/QznyG9gzwYc/m/aGS52shgAAAJ has a suggestion for how to be reminded to land the test later. Also, please request ESR102 approval on this when you get a chance.
Assignee | ||
Comment 24•2 years ago
|
||
Comment on attachment 9289658 [details]
Bug 1770094 r?emilio!,freddyb!
ESR Uplift Approval Request
- If this is not a sec:{high,crit} bug, please state case for ESR consideration: This is a simple patch that fixes an cross-site leak and CSP bypass that would be easy to recognize by looking at the already landed patch.
- User impact if declined:
- Fix Landed on Version: 105
- Risk to taking this patch: Low
- Why is the change risky/not risky? (and alternatives if risky):
Assignee | ||
Updated•2 years ago
|
Assignee | ||
Updated•2 years ago
|
Comment 25•2 years ago
|
||
Comment on attachment 9289658 [details]
Bug 1770094 r?emilio!,freddyb!
Approved for 102.3esr.
Comment 26•2 years ago
|
||
uplift |
Reporter | ||
Comment 27•2 years ago
|
||
I have the utmost respect for your excellent work and obsession with safety.
Thank you very much.
By the way, can a CVE or something be assigned to this issue?
I want to use it when explaining to others :)
Comment 28•2 years ago
|
||
We usually decide over CVE assignment when the fix is available in Firefox release. This bug is tracking 105, which means that it will become available to our release population starting Tuesday, September 20th.
Assignee | ||
Updated•2 years ago
|
Updated•2 years ago
|
Comment 29•2 years ago
|
||
Updated•2 years ago
|
Updated•2 years ago
|
Comment 30•2 years ago
|
||
Hello! I tried verifying this issue today but I'm not sure if the following results are correct:
On Windows 10x64 with the affected build 102.0a1 (20220518214245) when loading the attached poc.html file on an HTTP local server, I see a second request for the .png file that has attack.example.com
domain in the Network tab.
On fixed builds Firefox 105.0 (20220915150737) and Firefox 102.3.0esr (20220912135840) I can no longer see the attack.example.com
request when loading the attached poc.html. This was tested on Windows 10x64, macOS 11 and Ubuntu 21.
I have attached a screenshot with my results for a better understanding. Note that I have also added a random .png file inside the server path (http://127.0.0.1:8080/profile/img/b0190b16-41fb-9059-a680-9e5b47f24ce5.png)
. Is this verification correct or do I need to follow other steps in order to verify this issue? If so can you please provide if possible another set of steps? Thank you in advance!
Reporter | ||
Comment 31•2 years ago
|
||
Thanks for the confirmation.
As you can see in your image, 105.0 does not request attack.example.com, so the security risk I reported has been fixed.
Many sites these days have user profiles created by UUID (and secret URLs).
This eliminates the risk of leaking paths that should be kept secret by the user.
Comment 32•2 years ago
|
||
(In reply to Satoki Tsuji from comment #31)
Thanks for the confirmation.
As you can see in your image, 105.0 does not request attack.example.com, so the security risk I reported has been fixed.Many sites these days have user profiles created by UUID (and secret URLs).
This eliminates the risk of leaking paths that should be kept secret by the user.
Thank you as well for the confirmation and explanation.
I am closing this issue as verified fixed based on comment 30 and comment 31. Removing the ni? request as well.
Updated•2 years ago
|
Assignee | ||
Comment 33•2 years ago
|
||
Thanks Satoki Tsuji for your confirmation.
Assignee | ||
Updated•2 years ago
|
Comment 34•1 year ago
|
||
Bug 1770094 - Test. r=emilio,freddyb
https://hg.mozilla.org/mozilla-central/rev/41cb792ce9e9
Updated•1 year ago
|
Comment 35•1 year ago
|
||
4 months ago, Tom Schuster (MoCo) placed a reminder on the bug using the whiteboard tag [reminder-test 2022-10-18]
.
tschuster, please refer to the original comment to better understand the reason for the reminder.
Assignee | ||
Updated•1 year ago
|
Updated•2 months ago
|
Updated•2 months ago
|
Description
•