CSP bypass: Event handlers on elements added by a trusted script bypass the Content Security Policy
Categories
(Core :: DOM: Security, defect)
Tracking
()
People
(Reporter: aayla.secura.1138, Unassigned)
Details
(Keywords: reporter-external, Whiteboard: [reporter-external] [client-bounty-form] [verif?])
Attachments
(1 file)
|
911 bytes,
application/zip
|
Details |
When JavaScript that is allowed by CSP creates and adds a new HTML element with an event handler, that inline JavaScript (in the event handler) is not blocked by any CSP.
For example, the "default-src 'self'" CSP should only allow resources from the site itself, and should block all inline and external scrips. However, adding an HTML element, for example an image, and adding an event handler to it, bypasses this.
I've attached a proof of concept which shows that for a CSP of "default-src 'self'":
- all inline and external scripts originally on the page are blocked as expected
- external scripts added to the DOM by a trusted script are blocked as expected
- inline scripts in event handlers for newly created elements, which have been added to an existing element via innerHTML by a trusted script, are blocked as expected
- inline scripts in event handlers for newly created elements, which have been added to the DOM by a trusted script, are NOT blocked, leading to a bypass
Run "php -S localhost:50001" in the same directory as the proof of concept files, then visit http://localhost:50001/csp-bypass.php
Alternatively, visit http://csp-bypass.gotdns.ch which has the proof of concept running.
Tested on Firefox Nightly 90.0a1 (2021-04-29) on MacOS Big Sur
Note: One may argue that CSP should trust anything that has been added by a trusted script does, however this is not correct and cases 2. and 3. above confirm this.
Updated•5 years ago
|
Comment 1•5 years ago
|
||
The "inline script" blocking relates to "parsing strings into executable" because that's where people get into trouble. If part of the string comes from attacker input and the escaping isn't done right then some of that input can turn into code. If you tried to set the onerror attribute to a string, for example, it will get blocked. Setting the .onerror method to a function made of script that comes from your trusted script is perfectly fine.
Because of the string parsing thing, if you tried to set the .onerror method to a new Function("string") it would also get blocked unless 'unsafe-inline' or 'unsafe-eval' were allowed.
Chrome and Safari behave in exactly the same way
Updated•5 years ago
|
| Reporter | ||
Comment 2•5 years ago
|
||
(In reply to Daniel Veditz [:dveditz] from comment #1)
The "inline script" blocking relates to "parsing strings into executable" because that's where people get into trouble. If part of the string comes from attacker input and the escaping isn't done right then some of that input can turn into code. If you tried to set the
onerrorattribute to a string, for example, it will get blocked. Setting the.onerrormethod to a function made of script that comes from your trusted script is perfectly fine.Because of the string parsing thing, if you tried to set the
.onerrormethod to anew Function("string")it would also get blocked unless 'unsafe-inline' or 'unsafe-eval' were allowed.Chrome and Safari behave in exactly the same way
Oh I see, thanks for clarifying.
Updated•5 years ago
|
Updated•1 year ago
|
Description
•