Closed Bug 1709229 Opened 5 years ago Closed 5 years ago

CSP bypass: Event handlers on elements added by a trusted script bypass the Content Security Policy

Categories

(Core :: DOM: Security, defect)

defect

Tracking

()

RESOLVED INVALID

People

(Reporter: aayla.secura.1138, Unassigned)

Details

(Keywords: reporter-external, Whiteboard: [reporter-external] [client-bounty-form] [verif?])

Attachments

(1 file)

Attached file csp-bypass.zip

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'":

  1. all inline and external scripts originally on the page are blocked as expected
  2. external scripts added to the DOM by a trusted script are blocked as expected
  3. 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
  4. 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.

Flags: sec-bounty?
Group: firefox-core-security → core-security
Type: task → defect
Component: Security → DOM: Security
Flags: needinfo?(ckerschb)
Product: Firefox → Core

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

Group: core-security
Status: UNCONFIRMED → RESOLVED
Closed: 5 years ago
Resolution: --- → INVALID
Flags: needinfo?(ckerschb)

(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 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

Oh I see, thanks for clarifying.

Group: core-security
Group: core-security
Flags: sec-bounty? → sec-bounty-
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: