Closed Bug 1662388 Opened 5 years ago Closed 5 years ago

CSP "script-src 'self' 'unsafe-inline'" policy can be bypassed and inline Javascript payload executed, no violation reported

Categories

(Core :: DOM: Security, defect)

defect

Tracking

()

RESOLVED WORKSFORME

People

(Reporter: wiseagent, Unassigned, NeedInfo)

References

(Blocks 1 open bug)

Details

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

Attachments

(2 files)

Attached file CSP_Bypass.rar

##Firefox V80 Content-Security-Policy bypass

CSP "script-src 'self' 'unsafe-inline'" policy can be bypassed and inline Javascript payload executed, no violation reported

OS: Windows 7 - it can be reproduced in at least Windows 10.
Firefox version: Version 80(64-bit)
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0

###Step to reproduce the unsafe-eval bypass for "script-src 'self' 'unsafe-inline'" policy

  1. download the attached PoC_unsafe-eval-bypassed.Edge85.html
  2. hosting in any web server(I'm using nginx), the CSP policy is defined in the poc meta tag
  3. load the poc file and the result are printed in the console.
  4. sample results screen capture attached.

The PoC(PoC_unsafe-eval-bypassed.Edge85.html) has presented 10 cases where the CSP has been bypassed and 9 of them have no violation reported

Test case for expected CSP behaviour

TC 1: Expected behaviour - unsafe-eval violation reported

The following test cases observed no CSP voilats warning, payload getting executed. There is no CSP report on the violation sent back

TC 2: Unexpected behaviour - unsafe-eval violation is not reported, payload triggered
TC 3: eval undefined won't voilate CSP unsafe-eval
TC 4: eval null won't voilate CSP unsafe-eval
TC 5: eval NaN won't voilate CSP unsafe-eval
TC 6: eval an expression returns numeric value won't voilate CSP unsafe-eval
TC 7: eval an expression contains string and returns NaN won't voilate CSP unsafe-eval
TC 8: eval function expression won't voilate CSP unsafe-eval
TC 9: eval function pointer expecting args won't voilate CSP unsafe-eval
TC10: eval function pointer variable expecting args won't voilate CSP unsafe-eval

The following test case has payload triggered, but there is CSP violation reported
TC11: Function() payload triggered, should observed alert popup
Function(eval(alert("Function() payload triggered"))) voilation will be reported by CSP!

Summary - unsafe-eval can be bypassed and javascript code block executed by:

  1. Embeding it in a funcation call, as long as the function is rereturning undefined, null, NaN or numberic
  2. Embeding it in a expression, which contains a function call, as long as expression results in undefined, null, NaN or numeric

Observation and analysis:
Here is the highlight I hope will help speed up the triage and debugging process:
It appears to me that there is an implicited assumption that:

  1. It's harmful to eval any string values, including "blank", for obvious reasons
  2. (implicitly assumed) it's okay to eval() undefined, null, NaN or numeric as it's not a Javascript code block!
Flags: sec-bounty?
Group: firefox-core-security → dom-core-security
Component: Security → DOM: Security
Product: Firefox → Core
Type: task → defect

how does it make sense to restrict the use of eval() if you allow all other scripts with unsafe-inline? OK, I can think of one super contrived example that's not humanly realistic (guaranteed injection-free page, so you're not worried about basic XSS, only DOM XSS). I'm surprised the spec doesn't treat unsafe-inline as a superset of unsafe-eval.

The spec at 4.3. Integration with ECMAScript says

ECMAScript defines a HostEnsureCanCompileStrings() abstract operation which allows the host environment to block the compilation of strings into ECMAScript code. This document defines an implementation of that abstract operation thich examines the relevant CSP list to determine whether such compilation ought to be blocked.

So I can see that this might not be called (intentionally) in many of the cases you list as violations.

It appears to me that there is an implicited assumption that:

  1. It's harmful to eval any string values, including "blank", for obvious reasons

Yes, the explicit reason we worried about eval() is because of processing user (attacker) input--which is always a string--and accidentally turning it into code. Also same with "eval-like" functions such as setTimeout() where we don't block explicit function calls, but we do treat a string input as an eval call.

How do other browsers behave?

Blocks: csp-w3c-3
Flags: needinfo?(wiseagent)

Looking at the ECMAScript spec, HostEnsureCanCompileStrings() it's used in the PerformEval step in section 18.2.1.1 Runtime Semantics: PerformEval ( x, callerRealm, strictCaller, direct ). We see step 2 "If Type(x) is not String, return x." comes before step 4, "Perform ? HostEnsureCanCompileStrings(callerRealm, evalRealm)" which is the CSP hook.

I believe our behavior is correct. In any case it does not appear to introduce a practical security worry (given unsafe-inline) so I'm un-hiding this bug in case we need to have a wider discussion hashing out the intended behavior of cross-referencing specs that can potentially get out of sync.

In your initial comment you said this meant you could bypass the protection by embedding the string in a function call that returns null, etc. For that to work that function itself would have to contain an eval() call on the string, which would be blocked.

Group: dom-core-security

I should note that I couldn't successfully unpack your POC -- my RAR utility thinks your archive is broken. Please just upload the .html file as a non-compressed attachment.

Simple text or image attachments save us from having to be paranoid and run everything through virus checkers. This attachment appears clean, at least: https://www.virustotal.com/gui/file/fe93385bce9e1454b5c3fdaaaea8939c3756cbbae76087a4432f3c4fbfff4ab4/detection

More success with a different archive program. Here it is

I see the same results on Chrome and Safari (as I'd expect, given the spec)

Status: UNCONFIRMED → RESOLVED
Closed: 5 years ago
Resolution: --- → WORKSFORME
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: