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="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?
How about not displaying them as a link? Just use the text.
Combined with a warning to proceed at your own risk may be enough.
addition - see also Should I sanitize HTML markup for a hosted CMS? for a discussion on sanitizing user input
You don't specify the language of your application, I will then presume ASP.NET, and for this you can use the Microsoft Anti-Cross Site Scripting Library
It is very easy to use, all you need is an include and that is it :)
While you're on the topic, why not given a read on Design Guidelines for Secure Web Applications
If any other language.... if there is a library for ASP.NET, has to be available as well for other kind of language (PHP, Python, ROR, etc)
The process of rendering a link "safe" should go through three or four steps:
If security is a priority I would hope that the users would forgive a bit of paranoia in this process, even if it does end up throwing away some safe links.
If you think URLs can't contain code, think again!
https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
Read that, and weep.
Here's how we do it on Stack Overflow:
Just HTMLEncode the links when you output them. Make sure you don't allow
javascript:
links. (It's best to have a whitelist of protocols that are accepted, e.g., http, https, and mailto.)Use a library, such as OWASP-ESAPI API:
Read the following:
For example:
Another example is to use a built-in function. PHP's filter_var function is an example:
Using
filter_var
allows javascript calls, and filters out schemes that are neitherhttp
norhttps
. Using the OWASP ESAPI Sanitizer is probably the best option.Still another example is the code from WordPress:
Additionally, since there is no way of knowing where the URL links (i.e., it might be a valid URL, but the contents of the URL could be mischievous), Google has a safe browsing API you can call:
Rolling your own regex for sanitation is problematic for several reasons:
Other issues to consider:
file:///
andtelnet://
acceptable)?