However, it would still be possible to alter the data on the screen in
unexpected ways, and possible to create a convincing Phishing scam by
providing a link out to another website.
Is this accurate, or are out-links prohibitable also?
Yes it is accurate with one caveat: people on your site run modern browsers. For this exact reason, my team considers XSS without actual content injection (e.g. injecting into an unquoted tag attribute context) to be lower priority than a content injection bug itself because of CSP. We are blessed with having virtually no users on browsers that don't support some form of strong CSP.
What is the scope of a would-be XSS attack with the presence of a
tight CSP?
Forgive me here if this sounds soapboxy, but your question does not define "tight CSP", so let me elaborate on some things many overlook.
For the sake of argument, let's say this is a policy that is proposed (line breaks added for clarity, this is not a valid header):
Content-Security-Policy:
default-src 'self';
img-src https: data:;
connect-src paypal.com api.example.com;
script-src 'self' ajax.googleapis.com;
style-src 'self' 'unsafe-inline'
Note: removing unsafe-inline
from style-src
is not practical today.
That's a pretty good policy with some obvious and not so obvious flaws, but inline script is not allowed. There are many more caveats to consider with CSP, it's not just about disabling eval and inline script (yes javascript:
and on*
event handlers are included).
Locking down 3rd parties to actually limit XSS
So many other vectors still exist
GitHub's CSP journey contains many points on how the policy was tuned to prevent certain attacks.
All of the below can be abused with the proposed policy.
- Removing
'self'
from script-src
to prevent XSS via JSONP
- Exfiltrating CSRF tokens via
img
and form
tags
- Moving hosted flash files to a different origin instead of
'self'
because flash ruins everything.
- Using dynamic policies to prevent unexpected use of APIs that should only be used from a specific set of pages.
- Limiting use of
'self'
for frame-src
/child-src
- Abusing the
base
tag.
Sometimes, CSP just doesn't apply.
It's possible to circumvent CSP entirely. See PDF content-type sniffing for an example where user-controlled data on a page can really mess things up.
There's literally nothing we can do about this from CSP's perspective.
And sometimes, the internet makes you cry.
See Stealing the pie without touching the sill where CSS can be used to steal AND exfiltrate data on a page without javascript.
Because removing 'unsafe-inline'
is not practical, this attack is possible. However, this attack is difficult to execute.