We have a high security application and we want to allow users to enter URLs that other users will see.
This introduces a high risk of XSS hacks - a user could potentially enter javascript that another user ends up executing. Since we hold sensitive data it's essential that this never happens.
What are the best practices in dealing with this? Is any security whitelist or escape pattern alone good enough?
Any advice on dealing with redirections ("this link goes outside our site" message on a warning page before following the link, for instance)
Is there an argument for not supporting user entered links at all?
Clarification:
Basically our users want to input:
stackoverflow.com
And have it output to another user:
<a href="http://stackoverflow.com">stackoverflow.com</a>
What I really worry about is them using this in a XSS hack. I.e. they input:
alert('hacked!');
So other users get this link:
<a href="javascript:alert('hacked!');">stackoverflow.com</a>
My example is just to explain the risk - I'm well aware that javascript and URLs are different things, but by letting them input the latter they may be able to execute the former.
You'd be amazed how many sites you can break with this trick - HTML is even worse. If they know to deal with links do they also know to sanitise <iframe>
, <img>
and clever CSS references?
I'm working in a high security environment - a single XSS hack could result in very high losses for us. I'm happy that I could produce a Regex (or use one of the excellent suggestions so far) that could exclude everything that I could think of, but would that be enough?
href
attribute unescaped that is actually bad in its place even matters. – Morbidezzaalert('hacked')
is just a very basic XSS example - if I can get that to run I can get other (more malicious) code to run. CSP stops it because it can block all inline execution (that's how a policy in the browser will help you). It's not that the HTML coming from the server is hacked, it's that I wanted users to be able to share links, but not share a script that executes as the other user. I don't think the comments here are the best place for you to learn about how XSS attacks are executed. – Morbidezzaalert
is very commonly used because you get a pop-up when you have an XSS vector, but generally if I can getalert
through your server-side sanitisation script then I can execute any script I want. In any case, thanks for clarifying that my XSS feasibility example is not a actual exploit. – Morbidezzaalert
pops up then you have an XSS vector. The question is there a sanitisation script that guarantees nothing will get through, the selected answer is basically "no but here's what we do". – Morbidezza<a href="alert('hacked!');" > alert('hacked!');</a>
. This is the non sanitized output. Then, if you are on linux, in the same folder, create a file namedalert('hacked!');
. Visit the html file and click the link. The other file will be downloaded, just as expected. There will be no alert. There is no attack at all. – Surplushref="script"
would have executed the script by default. This is a 12 year old question with a 12 year old answer, and while XSS is still a risk the basic vector described here is blocked by the vast majority of browsers today. I'd still sanitise it though. – Morbidezzaalert
specifically as the XSS vector, and the fact it is treated as a resource path now doesn't make all XSS attacks impossible. You should still sanitise URLs, and add CSP too. – Morbidezza