Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I've got an idea as to how to defeat XSS so simple that it may work and was wondering if anybody had already done something similar.

The goal here is not efficiency but security. In other words I don't care about trading bandwith for security. My idea would be to serve every single character inside simple HTML tags.

Basically if the following, for whatever reason, would be a working XSS exploit: 0WNED!byXSS (which for whatever reason nobody would have detected), then it would be served as:

<i>0</i><i>W</i><i>N</i>E<i>D</i>!<i>by</i>X<i>S</i>S<i>

Basically a loop would make sure to only do:

  • write <i>
  • write a single character
  • write </i>

Could something like that technically work (performances and bandwith issues aside) and has something like this ever been done?

EDIT

Here's a (simplified) example of what I'm thinking about.

Instead of serving this:

<html>
  <head>
    <title>Sample</title>
  </head>
  <body>
    <table>
      <tr>
        <td>Here goes user input</td>
        <td>potentially containing an XSS exploit</td>
      </tr>
    </table>
</table>
</body>
</html>

I'd serve this:

<html>
  <head>
    <title>Sample</title>
  </head>
  <body>
    <table>
      <tr>
        <td><i>H</i><i>e</i><i>r</i><i>e</i><i> </i><i>g</i><i>o</i><i>e</i><i>s</i><i> </i><i>u</i><i>s</i><i>e</i><i>r</i><i> </i><i>i</i><i>n</i><i>p</i><i>u</i><i>t</i></td>
        <td><i>p</i><i>o</i><i>t</i><i>e</i><i>n</i><i>t</i><i>i</i><i>a</i><i>l</i><i>l</i><i>y</i><i> </i><i>c</i><i>o</i><i>n</i><i>t</i><i>a</i><i>i</i><i>n</i><i>i</i><i>n</i><i>g</i><i> </i><i>a</i><i>n</i><i> </i><i>X</i><i>S</i><i>S</i><i> </i><i>e</i><i>x</i><i>p</i><i>l</i><i>o</i>it</td>
      </tr>
    </table>
</table>
</body>
</html>

The <i> tag was just arbitrarily chosen, any (preferrably one-letter) tag would do.

Various functionalities of the OS / browser seem to keep working correctly:

  • I can cut'n'paste correctly to the clipboard
  • I can still search for text (e.g. I can look out for "goes" and despite the fact that every single letter of "goes" is wrapped by tags the browser still finds it fine)

I take it that search engine would still correctly parse/index the content (not too sure about that that said).

To me it looks like quite a simple and effective way to prevent lots of exploits based on evil user inputs.

share|improve this question
1  
Seems like your thinking of a variant of HTML encoding and Javascript encoding? This example is too abstract for me –  makerofthings7 Mar 10 '13 at 15:34
    
@makerofthings7: I'm thinking of serving any input sent by a user back by wrapping every single character sent by the user inside HTML tags. I wouldn't do this from JavaScript: this would be done from the server side. Single character needing HTML escaping would be escaped, of course (but they would also, just like any other character, be wrapped inside tags). So basically every character input by a user would become 8 characters (when not needing escaping) or more (when needing HTML escaping). –  Cedric Martin Mar 10 '13 at 16:56
2  
One problem that I see with this is that you'll have a hard time detecting HTML encoded characters, such as &nbsp; and wrap them accordingly. If you really followed your example code to the letter (no pun intended), then &nbsp; would display as &nbsp; instead of a single space character. Same would go for any Base64 (or any other way) encoded URL strings. –  TildalWave Mar 10 '13 at 18:09
1  
Sorry to sound harsh, but it seems that you're not really clear on how XSS works. This is trivially bypassable, simply by the nature of XSS. I'll leave the specifics to the answers already here, but I would suggest you read up on XSS, its variants, vectors, and evasions a bit more - can't hurt, right? –  AviD Mar 10 '13 at 19:07
2  
I don't understand what the advantage of this over plain HTML-escaping is. They would both have to be executed on every injection of content into HTML so there is no difference in ease-of-use (and hence likelihood of being applied correctly). The difference is that this proposed scheme (a) generates heavier output than HTML-escaping, and (b) generates wrong output for < and & characters. Also it doesn't work in attribute values. I see no win here. –  bobince Mar 10 '13 at 21:16
add comment

4 Answers

This seems like a silly solution to an already solved problem:

  1. Use an HTML purifier library to only allow a safe subset, OR
  2. HTML escape questionable input characters like <>'"& to their equivalents (e.g., < goes to &lt;). Additionally, if you needed to allow some formatting (e.g., users can submit links, insert bold text) use a safe subset of a lightweight markup language so you convert user input like [google link](http://www.google.com) to google link.

If your scheme was perfect and inserted each character of the untrusted user input character by character between its own tag like <i>h</i><i>e</i><i>l</i><i>l</i><i>o</i>, I personally don't see anyway for an attacker to easily do a XSS attack though someone else maybe able to think of something.

Lines of attacks that could work:

  • maybe they can mess up the DOM (by inserting stray < > symbols) and some random browser will try to fix and fix in some unsafe way.
  • maybe some browser will let an attacker insert backspace (unicode 08) and escape out of your tags somehow
  • or some browser internally optimizes consecutive tags -- e.g., converts it to <i>hello</i>.
  • or your method of parsing the user input character by character is flawed and surpassed.

Additionally, with your method I don't see how your scheme would allow you to do anything fancy that you may want to do; e.g., allow users to format text or post links or anything fancy. In this case, its simpler to just ban the characters <>&'" that have special meaning in HTML.

share|improve this answer
    
an already "solved" problem? Hardly a week passes by without someone finding an exploit that is yet another variation on the XSS exploit and which manages to somehow dodge all the purifier and whatnots already in place... Good point about posting URLs that said: some thoughts would need to go into that. Now I don't see how it could be "silly" when you say yourself that you're not seeing any way for an attacker to easily do XSS on such a system. It's also not mutually exclusive with a purifier and HTML escaping :-/ –  Cedric Martin Mar 10 '13 at 18:00
4  
@CedricMartin he might have said he doesnt see any way, but then he went right ahead and listed quite a few valid vectors. Most often what we hear about the "new" exploits is simply yet another app whose developers did not bother implementing the proper controls. If done correctly (and this is really NOT complicated), there would be no exploits. Part of the problem is the developers see many different "solutions" and either get confused or try something wrong. There really is only one solution that works: context-sensitive encoding. –  AviD Mar 10 '13 at 19:13
1  
@CedricMartin - Calling it silly was a bit harsh -- it is a clever novel way that likely solves the problem. But being clever and novel is an anti-pattern for security called "rolling your own". When well-vetted common methods exist, you should stick to them. Your method is less flexible than existing methods (e.g., couldn't be used to encode a URL into a link), couldn't be used inside javascript, and less efficient on the browser. Again, just because the people in this thread can't easily find a vulnerability in an abstract idea, any specific implementation may have one. –  dr jimbob Mar 10 '13 at 20:55
    
@dr jimbob: well but it's not really "rolling my own", I'm just adding another layer of security which is not IMHO incompatible with other security measures. Moreover I could be totally public about it: it's not "security by obscurity". I more see it as "defense in depth". It's not because I'd be using such a scheme that I'd dodge the other, accepted, security practices. I may give it a try on a Java / Tomcat webapp for the fun : ) –  Cedric Martin Mar 11 '13 at 16:29
    
@CedricMartin - Never called it obscurity, called it Rolling Your Own--its something new you came out with that hasn't been field tested. If you (1) intend to use only as defense-in-depth (also HTML escaping <>&'"), (2) never need user input in places this method breaks (in javascript, between <title> tags, inside HTML tags like the href part of a link), and (3) do not mind the extra overhead (server-side template processing/client-side DOM rendering/more network traffic), then this is likely ok. However, I really don't see any extra defense or positives it gives over HTML escaping. –  dr jimbob Mar 11 '13 at 17:12
add comment

Congratulations! I have put some thought into this and this is actually a pretty solid escape system. Although it can lead to errors, I don't believe this is very useful to an attacker. The main reason why a character separation encoding is better than a traditional html-encode is that is causes problems with an attacker's payload.

For example, XSS filters sometimes fail to prevent XSS depending on where its written on the page. If an XSS filter takes into consideration the usual <> while ignoring a doublequote then this is an xss vector using the payload ";alert(1)//:

<script>
var j="";alert(1)//";
document.write(j);
</script>

However, using a character separation encoding method will cause a java parse error:

<script>
var j="<i>"</i><i>a</i><i>l/i><i>e</i><i>r</i><i>t</i><i>";
document.write(j);
</script>

Html encoding is not a panacea! The browser automatically HTML-decodes values within an HTML tag and this can lead to xss in DOM events:

<a href="" onclick="alert('hi&#39;);alert(/xss/)//'">click</a>

In this case two alert boxes will be displayed because &#39; will automatically be decoded to a single quote ' before it is evaluated as javascript. However if you can only inject a single character, then you will get an exception in the payload.

HTML Encoding is nice because the browser will decode HTML values like <form value="o&#39;connel"> into the expected o'connell before sending it as a request. If you use any other xss encoding method all incoming values will have to be decoded, which could cause filtering problems or data-corruption.

I don't believe the added overhead of this escape method justifies the security provided. Using a traditional HTML Encoding is preferable. A good templating system makes it easy to defend against xss.

share|improve this answer
1  
+1 - Good point with HTML encoding not being panacea. Granted if had earlier in the page in a script: var msg = "hi&#39;);alert(/xss/)//'" and then <a href="" onclick="alert(msg)">click</a>, the HTML encoding would have saved you. –  dr jimbob Mar 10 '13 at 20:00
add comment

If your special character is <i> and </i> and the data you're trying to encode or display includes <, i, or > then you will need to "escape" those characters. (or the trio of 3 characters) Since they are fairly common characters, I think you will need to ensure they are always encoded/decoded properly.

So now what we have is a solution that requires the developer to ensure proper escaping we should also note that not everything is escaped in all instances. Namely the <title> tag.

In one case a Title may contain user names, product names, etc. If this feature is used, the conditional escaping of user input is one more thing the developer will have to remember. The next thing to consider is JSON, and Javascript. Things aren't so simple now.

The solution you're proposing is creating the same problem you're trying to solve albeit in another form: Requiring the developer to conditionally escape characters based on the context of the value to be displayed.

Further complicating this is any DHTML created by javascript that needs to also be displayed in the browser, or if user input is used to download an image:

   <img src="http://xxx.com/hackedUserDisplayName.js"> 

In that case the developer wanted to use user input to include in the page, but didnt clean it properly. The tagging approach wouldn't be used here and would have broken the image url if it were.

I commend you for thinking about proactive security measures, and trying to come up with a one-size-fits-all approach, but you should test your ideas with the XSS examples listed on this page.

Keep trying, and let us know if you are able to invent a more consistent approach to fixing XSS. The more likely outcome is that you'll become well versed in XSS. It's a win/win.

share|improve this answer
    
... Yeah but does his filter work? –  Rook Mar 10 '13 at 19:24
2  
@Rook 'course not, it's not context sensitive. –  AviD Mar 10 '13 at 19:53
add comment

XSS is a solved problem. Just because XSS exploits continue to be found, doesn't mean it hasn't been solved. It just means someone incorrectly, or did not implement a solution.

This solution you pose here is interesting, but I wouldn't use it.

For one, you would probably have to use span elements instead of i elements. That's a <span> followed by 1 character followed by </span>. multiplied by however many input characters your web application allows. Imo, that is an unnecessary bloat in data that must be stored. Additionally, you still have to consider erroneous input such as NULL characters, <, >, ;, ', ", and other symbols.

Additionally, it's best to sanitize input both before storing it in a database and again after retrieving it from a database. The solution you have here would not do anything for santizing data upon retrieval from a database--I say that because I am sure you and I both agree that you wouldn't pull one character out of the database and insert it inside of a span tag.

share|improve this answer
    
#cmt: if there's a XSS exploit that managed to make it to the DB then at least using the filter I suggested that exploit would be served with every single character wrapped inside tags (upon dynamically serving the webpage to the user). So, as Rook wrote, it would pose problem to the attacker's payload. Now I agree that there are contextual issues that need to be dealt with but I haven't read anything convincing me that my scheme wouldn't provide more defense in depth. –  Cedric Martin Mar 11 '13 at 16:27
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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