Closed toasted-nutbread closed 4 years ago
Don’t inject moz-extension paths directly
Agreed. It's good that the <iframe>
isn't injected before text is scanned, though. I also think that Chrome is not affected by this, because they use the same ID in Chrome Web Store (other than fingerprinting by the fact of having Yomichan installed). What about other identifying data (however small) such as class
or data-yomichan-theme
?
What about other identifying data (however small) such as
class
ordata-yomichan-theme
?
I don't see that as being as big of a deal, since it's not truly unique per user. Unfortunately, Mozilla's page doesn't really describe how to hide the assets. They mention it's possible to use data urls or srcdoc, but the host webpage can read both. If the iframe is treated as a empty temp frame which Yomichan subsequently injects scripts into, then Yomichan would need a way of correlating that iframe element to the extension frame ID. I ran into this same issue while trying to implement better popup iframe support, but I didn't find a good solution. At least not without making assumptions on how some of the web extension APIs work which is not covered in the documentation.
I also mentioned this briefly in #292, but a closed shadow DOM may help with this, as scripts won't be able to read the DOM. This could also help isolate the Yomichan styles. (There are potentially issues with closed
being able to be bypassed, but we may not have this issue since the context of the web extension scripts is more secure.)
Also: it does seem possible to manually call postMessage
from the host webpage on the iframe to trigger the iframe APIs. This may be able to be improved by changing targetOrigin
to something other than '*'
, but this will take some experimentation.
They mention it's possible to use data urls or srcdoc, but the host webpage can read both.
I guess a way to protect yourself against non-targeted fingerprinting could be to include a random value inside the srcdoc
or data url each time, but it would still be quite easy to identify the usage of Yomichan. Still better than a unique ID, though.
I also mentioned this briefly in #292, but a closed shadow DOM may help with this, as scripts won't be able to read the DOM. This could also help isolate the Yomichan styles. (There are potentially issues with
closed
being able to be bypassed, but we may not have this issue since the context of the web extension scripts is more secure.)
Certainly looks like shadow DOM could be a solution for this issue if it doesn't mess up focus handling on different browsers.
Also: it does seem possible to manually call
postMessage
from the host webpage on the iframe to trigger the iframe APIs. This may be able to be improved by changingtargetOrigin
to something other than'*'
, but this will take some experimentation.
Scary, that could open the browser for exploitation if there was a vulnerable integration in Yomichan that can be accessed with postMessage
.
Also: it does seem possible to manually call
postMessage
from the host webpage on the iframe to trigger the iframe APIs. This may be able to be improved by changingtargetOrigin
to something other than'*'
, but this will take some experimentation.Scary, that could open the browser for exploitation if there was a vulnerable integration in Yomichan that can be accessed with
postMessage
.
Another solution could be a CSRF style token that Backend
provides.
Re: eslint-plugin-no-unsanitized: #352 / ecdb476a3a4f6adcb5a88ae2693b609b31c096d1
I have committed 912d59d3dfefde5738b4244d74d944795edcc02c, which hides the iframe's URL from fingerprinting. Based on some stuff I found while looking into https://github.com/FooSoft/yomichan/pull/364#issuecomment-586663700.
I have also committed created a PR #367, which defers the injection of the /fg/css/client.css stylesheet until after the popup iframe is added to the document. This prevents the detection of Yomichan's presence using CSS rules testing (before the popup is spawned of course).
There is currently an issue with about:blank pages, so this may or may not work.
Origin is now checked on posted messages: aee16c443195ff8ab2b0f5f5e8551e44895d48a1.
A unique token is now used for posting messages to the float.html page: 0f46e3a093e7f0c07ad310d8c17e2582bdfd2741
There are two remaining places which could use some modifications: https://github.com/FooSoft/yomichan/blob/0f46e3a093e7f0c07ad310d8c17e2582bdfd2741/ext/fg/js/float.js#L71-L77
These messages are posted to the parent window, so the host webpage would also be able to see these messages. Not only does that tell the host page that Yomichan is doing something, it could also potentially interfere with the host page if it expects messages of the same format.
There is also this: (7d9d45ae10302582ce7431bd72ec4f8604dc5e65) https://github.com/FooSoft/yomichan/blob/0f46e3a093e7f0c07ad310d8c17e2582bdfd2741/ext/bg/js/search.js#L250
Which may have to be changed if the other messages are changed.
Awesome, that should patch the attack vector when the other three places are handled too.
There's a related issue in https://github.com/FooSoft/yomichan/pull/364, I had to add checks like this https://github.com/FooSoft/yomichan/blob/0f6c62ab0a0420a13911e410a588419868725914/ext/fg/js/frontend.js#L218 to make sure that the iframe popup doesn't trigger the same method on itself infinitely.
It might be solved by switching to the PopupProxy
class but I'm not sure.
Another is to use an ID like in https://github.com/FooSoft/yomichan/pull/366 and reject its own ID, but there has to be some kind of reliable communication from the iframe popup to its host Frontend
first.
While reviewing https://github.com/FooSoft/yomichan/pull/380, I got interested in the inner workings of Handlebars and found that there are different kinds of ways to compile a template: https://github.com/wycats/handlebars.js/blob/master/docs/compiler-api.md https://handlebarsjs.com/api-reference/compilation.html#handlebars-precompile-template-options
Yomichan currently uses Handlebars.compile
, but there is also Handlebars.precompile
which does the same thing the template compile script used to do. Handlebars.precompile
doesn't use the Function
constructor:
Handlebars.precompile
set compile
flag to recursive compileChildren
calls
use Function.apply
only if asObject
is true
So, since Anki runs QtWebEngine, it could also use the template once it's been precompiled. It would probably require a fork of Handlebars removing support for Handlebars.compile
. This is still missing the step of getting Handlebars into Anki without triggering extension store detectors, because the precompiled templates don't work as standalone functions without the host library.
If the above seems impossible, it could also be possible to turn the AST generated with Handlebars.parse
into HTML within Yomichan without doing any eval
, but that could be a huge task and also worth upstreaming.
I also found that Handlebars is supposed to be somewhat compatible with Mustache, and while Mustache doesn't use eval
(https://github.com/janl/mustache.js/issues/207), it also doesn't support helper functions or nested objects for input.
Not sure to what extent this will affect Yomichan, but apparently a v3 of the extension manifest is eventually coming to Chrome. https://developer.chrome.com/extensions/migrating_to_manifest_v3
Noteworthy points:
Are you currently using chrome.tabs.executeScript({code: '...'}), eval(), or new Function() in background contexts or content scripts?
- Move all external code (JS, Wasm, CSS) into your extension bundle.
- Update script and style references to load resources from the extension bundle.
- Use chrome.runtime.getURL() to build resource URLs at runtime.
Potential issues with Handlebars.js.
Are you currently using chrome.runtime.getBackgroundPage(), chrome.extension.getBackgroundPage(), chrome.extension.getExtensionTabs(), or chrome.extension.getViews()?
- Migrate to passing messages between other contexts and the background service worker.
This is already planned.
CORS related changes for content scripts. See: https://www.chromium.org/Home/chromium-security/extension-content-script-fetches
This shouldn't affect Yomichan, but #428 was having a similar CORS issue.
Closing as most security concerns have been addressed, except the Handlebars eval
issue, which is large enough to be a separate issue. The one other potential "security" issue is that window.postMessage
is used for iframe parent resolution, but it's not so much of a "security" issue as it is a "potential to mess with the underlying website" issue.
I was recently going through Mozilla's security best practices for extensions page and noticed a few things that may affect Yomichan.
eval
(reallyFunction
constructor) to generate content. Can't do anything about this at this point, but just mentioning it here anyway. #203<iframe>
element.