Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assigning location.href to a javascript:... is a form of eval #688

Open
dinofx opened this issue Nov 4, 2024 · 9 comments
Open

Assigning location.href to a javascript:... is a form of eval #688

dinofx opened this issue Nov 4, 2024 · 9 comments

Comments

@dinofx
Copy link

dinofx commented Nov 4, 2024

Extracted per request in the discussion in #322.

Assigning location.href= to a string that starts with javascript: is a form of eval, similar to setTimeout(someString), and others. It should only execute if unsafe-eval is allowed. But currently in many browsers unsafe-inline will allow this dynamically constructed JavaScript to be evaluated. This is likely due to ambiguity in the spec.

What constitutes an "Inline" script is not well described in the spec. I think most would consider it to be scripts that appeared "in line" in the original HTML response. The reason such inline scripts might be unsafe is because a browser doesn't know if these scripts were dynamically constructed on the server, potentially using query params or other data an attacker would control (i.e. a reflection attack). When a page allows unsafe-inline, it's stating that such server-side attacks either don't apply, or have been considered and mitigated/sanitized on the backend.

Both of the following are an example of inline script:

<a href="javascript:alert(0)" >click me</a>
<div onclick="alert(0)"> click me</div>

In both of the above, the script executed, alert(0), was inline in the html returned from the server.

By contrast, consider these:

<script>
  location.href = 'javascript:' + malicious;
</script>
<div onclick="location.href = 'javascript:' + malicious" >
<div onclick="eval(malicious)" >

All of these should be blocked unless unsafe-eval is allowed. The importance difference is that the malicious script being executed is not inline. It may have been dynamically constructed in the browser, which is a much different threat than inline scripts originating from the server.

@annevk
Copy link
Member

annevk commented Nov 5, 2024

https://w3c.github.io/webappsec-csp/#directive-script-src seems pretty clear to me. And I doubt the corresponding algorithms would suggest anything different or be ambiguous in that manner. I also doubt this can be changed at this point.

What browsers are inconsistent on this? Do you have a test?

@dinofx
Copy link
Author

dinofx commented Nov 6, 2024

From the link above:

  1. Navigation to javascript: URLs MUST pass through § 4.2.3 Should element’s inline type behavior be blocked by Content Security Policy?

"Navigation to javascript: URLS" is clear to me. "Clicking" on an anchor tag that has an inline script (i.e. an href with a javascript: URL) is what is meant here.

Whereas code that assigns location.href== 'javascript:' + malicious is NOT a navigation. When it comes to the "should block inline" algorithm, which starts off saying "Given an element, a string type, and a string source this algorithm returns Allowed ...", it doesn't apply. The script in this case did not originate from any element, because it isn't an inline script.

However, item 4. ("JavaScript execution sinks") fails to include location.href assignment to javascript urls, which probably forced some browser implementation to guess, and the rest just followed suit.

@dinofx
Copy link
Author

dinofx commented Nov 6, 2024

I agree it will be a challenge to fix things, but the current state of things it is very misleading to web developers. Most developers will assume that unless they include unsafe-eval, they don't have to worry about arbitrary execution of javascript.

@annevk
Copy link
Member

annevk commented Nov 7, 2024

What do you mean is not a navigation? That's certainly a navigation.

@dinofx
Copy link
Author

dinofx commented Nov 8, 2024

"3." Is talking about inline scripts that run automatically as the page is loaded.
"6." is talking about inline scripts that run when a user interacts with the page. "navigation" in this context means running the inline script as a result of clicking the element whose attribute contains an inline script.

For code doing location.href== 'javascript:' + malicious, where is the inline script that would make 6. relevant? If it's a "navigation", what events get fired associated with navigating?

@annevk
Copy link
Member

annevk commented Nov 9, 2024

"navigation" in this context means running the inline script as a result of clicking the element whose attribute contains an inline script.

What makes you say that? Navigation there refers to the concept of navigation as defined in the HTML Standard.

@dinofx
Copy link
Author

dinofx commented Nov 20, 2024

What makes you say that? Navigation there refers to the concept of navigation as defined in the HTML Standard.

A javascript: url is referred to as a special case. A form of navigation only takes place when that script returns a non-null result (step 8).

But, back to the CSP spec, in step 6.:

... MUST pass through § 4.2.3 Should element’s inline type behavior be blocked by Content Security Policy?

"element" refers to the anchor in <a href="javascript:alert(0)" >click me</a>. The meaning of "navigation" in the context of the HTML standard isn't really relevant. The point is there is no inline script when code dynamically assigns location.href. In integration with HTML section:

[should block inline check] is called during handling of inline event handlers (like onclick)

Where another type of inline event handler is an anchor's href="javascript:...". Code that assigns location.href is not an event handler.

Also elsewhere in the spec:

An inline check, which takes an Element, a type string, a policy, and a source string as arguments

Code that dynamically assigns location.href doesn't satisfy the definition of an "inline check"

@dinofx
Copy link
Author

dinofx commented Nov 20, 2024

Do you agree that server-side and client-side attacks are two different classes of vulnerabilities?

If so, it would follow that unsafe-inline and unsafe-eval were intended to allow (or not) each of those.

@annevk
Copy link
Member

annevk commented Nov 21, 2024

I don't really understand what you are trying to say. The HTML navigate algorithm calls out to CSP to handle javascript: URLs and that's how they are handled. And that's what CSP is talking about when it talks about navigation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants