nr: #1 dodano: 2017-01-03 15:01
Careless use of
innerHTML in an extension can lead to several (security) issues, including:
- Same origin bypasses (including universal XSS, aka UXSS).
- Privilege escalation.
- Privacy violations (e.g. referrer leaking).
Your proposed use of innerHTML (taking HTML from untrusted sources and inserting it in a contentEditable element on another site without sanitization) is insecure. In theory, scripts should not execute in contentEditable elements, but there have been browser bugs where this is not the case (e.g. in Firefox and in Chrome).
For the record - assigning untrusted content to
innerHTML is unsafe, unless the document is not associated with a view (e.g. such view-less documents can be created with
document.implementation.createHTMLDocument). Note that even though assigning
innerHTML in such documents is safe, it is completely unsafe to insert elements from such documents in documents with a view. See the XSS article at OWASP for general information about XSS.
Privilege escalation may occur when the untrusted content manages to execute in the context of the extension. In content scripts, this is limited to cross-origin network requests and some other extension APIs, in extension pages this includes access to all extension APIs for which the extension has permissions. This has far-reaching consequences and XSS is not uncommon in extensions. For this reason, Chrome enforces a default content security policy for extensions using
"manifest_version": 2. This greatly reduces the impact of XSS in extensions, but it is not 100% flawless and you should not use CSP as an excuse to not properly sanitize the data that you assign to
(once the dust settles I can share some impactful real-world security incidents with CSP bypasses)
For your specific situation (copying a DOM tree to a contentEditable element in another document), I suggest one of the following approaches:
- Whitelisting: Recursively enumerate all child nodes of an element, and only clone the element if it is a safe element (e.g. "b", "strong", "em", "i", etc.), and only copy the attribute if it is a safe attribute.
- Blacklisting: Deep-clone a subtree, and remove all unsafe elements and unsafe attributes (exercise for the reader: what is an unsafe element? Hint: The answer is not easy, and it depends on the attributes).
If you don't have a DOM tree to start with, parse the HTML using one of the previously suggested methods (e.g.
DOMParser). And be careful in selecting what elements and attributes you choose to accept. For example, this safeResponse.js file seems like a good start (because it removes script tags and all attributes except for some seemingly safe attributes), but it is not. Someone can use the
style attribute to make the element transparent and on top of the whole document, and then put a
href attribute (spaces in front of the link are stripped by the browser). When the user clicks anywhere in the page, the script runs in the page's context. This patch for sendResponse.js fixes the issue, and the result is probably safe against XSS (not safe against privacy violations though, e.g. one can reference external content via CSS in the