16

In OWASP recommendations regarding escaping untrusted input for HTML element content, they list the following:

& --> &
< --> &lt;
> --> &gt;
" --> &quot;
' --> &#x27;  &apos; not recommended because its not in the HTML spec (See: section 24.4.1) &apos; is in the XML and XHTML specs.
/ --> &#x2F;  forward slash is included as it helps end an HTML entity

What is the purpose of including / in there? Indeed, / is part of the ending entity, but since we're already escaping < and AFAIK no known browser would accept / without preceding < as entity end, what is the reason to escape it?

9

Back before HTML 5 came with a standard parsing algorithm, HTML 4 was defined based on SGML. And its SGML-based syntax had features that differed in terms of browser support and differed in terms of people being aware of them.

One of the more obscure features that you'll be interested in, for the purposes of this question, is Null End Tag (NET). Have a look at the following code for an HTML page:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title/hello/
<body>
<p/hello/

If you want, try putting it through an HTML validator. NET specifies that code like <TAGNAME/text/ is parsed into the same thing you'd get from <TAGNAME>text</TAGNAME>.

From here, you may be able to see why it's a good idea to escape the / character when interpolating user-provided data into markup. A / could potentially end up in one of these NET constructions and be interpreted as the end tag, instead of a literal solidus.

Sure no browser now understands the NET syntax, but it's part of the spec, so it's prudent to account for it.

  • The question is regarding element content (see owasp link), where NET would be irrelevant. The attacker would need to inject into a tag to achieve this attack. – SilverlightFox Mar 15 '18 at 20:19
  • echo "<p/$usertext/"; is a case where you would be writing element content (I checked the OWASP link just now, and I think that's what it means?) and NET would be relevant. – guest Mar 15 '18 at 20:54
  • But if no browser understands that, why would it be an injection point? I.e. the page would never have been authored that way in the first place. – SilverlightFox Mar 15 '18 at 20:58
  • to answer that question, let's assume that no browser understands NET (although note that that's not what I claim in the answer). there's software other than browsers that interact with the web and that do understand NET. in fact, the online HTML validator is one such piece of software (not a perfect example here though, since it doesn't execute scripts). having a way to ensure your applications are safe to use with such software is a nice thing. and having practices that don't depend on the proposition that "the page would never have been authored tat way" is also a nice thing. – guest Mar 16 '18 at 20:07
6

Your question asks "Why /?".

However you don't seem to be concerned about >, " and '?

Technically, to ensure security within element content you only need to encode the < and & characters because HTML tags cannot start with >, ", ' or /. Note that I am only talking about HTML here (not XHTML).

To answer your question the reason is that / is an HTML character with special meaning. If you are following the OWASP guidelines it is assumed that you want your system to be secure and it is always best to err on the side of caution since there are little downsides to doing so in this case.

If you want to be minimalistic check out the OWASP XSS Experimental Minimal Encoding Rules.

  • 1
    Thanks for the link to minimal rules. They make much more sense, actually. – StasM Feb 4 '14 at 19:02
  • 1
    " and ' are encoded so that the encoded string can be used as the value of an attribute (<img title="encoded username goes here" ...>). – Macil Feb 15 '17 at 21:57
  • @age The question is regarding why to HTML Escape Before Inserting Untrusted Data into HTML Element Content, not for attributes. – SilverlightFox Feb 16 '17 at 7:59
3

When a character has syntactical meaning in any context, you should be wary, and err on the side of escaping it.

If for instance an attacker has found a way to inject it at the end of some existing tag, they can create a tag like <br /> which does not require ending; the transformation could change the meaning of the document.

I apologize that I don't have a concrete example for you beyond that, but it costs very little to escape it, so the tradeoff is certainly in favour of doing so.

I see no particular reason for it besides a safeguard against other bugs or mistakes being rendered exploitable by this particular inclusion. It isn't an especially strong recommendation in that no PoC can be universally developed to show its necessity, but there is no harm whatsoever in following it.

  • Well, then they should suggest escaping pretty much any non-alphanum character, since most of them have significance in some context. They don't do it. They correctly identify the characters that may be significant in HTML, but then add / which is not. Also, you can not inject <br/> since < and > are encoded, so you could inject only &lt;br/&gt; - what's wrong with that? – StasM Feb 4 '14 at 7:01
  • 2
    For a concrete example, phpBB used to have a bug in how it turned BBCode into HTML, with the result that [b /><script onclick=alert()>Foo<b] would become <b /><script onclick=alert()>Foo<b></b>. – Mark Feb 4 '14 at 7:37
  • 2
    @StasM I think you might be making the mistake of thinking that the OWASP is completely infalliable and has ironclad reasons for everything they do. In security it is usually better to err on the side of caution, and looking at this closely it looks like that is precisely what is up. You could err further in that direction if you so desired, certainly. – Falcon Momot Feb 4 '14 at 8:56
  • 1
    @FalconMomot in general, it is, but adding random characters to escape list just doesn't make sense. Why won't they then suggest to add letter Z to the list? Just to be cautious, maybe it's dangerous too. It just looks completely random, sorry. – StasM Feb 4 '14 at 18:58
2

"as far as I know..." is the root of many bugs, failing to encode dangerous characters. It is the 'blacklist' approach to encode only the things you know are dangerous instead of not-encoding only the things you know are not dangerous.

For an example, imagine that the server sets an HTML tag attribute's value to user input...

<input value=userdata>

The above is completely legal and valid HTML. Many web pages do not encapsulate their values in quotes, and browsers interpret this correctly.

Now, assume you use the OWASP list that you included at the top of the page. Note that space is not in the list....

<input value=foo onclick=alert()>

Now we have a successful attack. We have used space to break out of the previous context, then equal sign to set a context where we can write javascript, and parenthesis to execute a function. None of these were in the (broken) blacklist you showed.

With this same attack (using space to break out) the / symbol can be used as part of javascript content as a division sign, part of a comment (// or /*) or in other ways. The OWASP filter evasion cheat sheet (https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet) has a good list of attack strings using varying characters, depending upon what is or is not encoded, and for different contexts. The dash (-) character can be used for XUL markup against mozilla.

Just because you can't see where it would be a problem is never good enough. You MUST know that it can never be a problem before you let it through. As yu can see with the above example, even OWASP failed to predict certain valid usage of user data, and thier encoding instructions were incomplete.

The safe thing is to always encode everything but that which cannot possibly be dnagerous. Generally, it is safe to encode all non-alphanumeric ASCII characters below character point 127 and let everything else go unencoded. Less than this invites errors oike the one described above.

  • 1
    This recommendation is specifically for content outside elements, not for attributes. For attributes they recommend completely different handling, see the next item after the one I have linked. – StasM Feb 4 '14 at 7:02
  • If you write shitty html like that, you deserve what you get. – CodesInChaos Feb 4 '14 at 8:56
  • 1
    @CodesInChaos If you do not protect valid html, correctly interpreted by standard interpreters, and written by a substantial population of web developers, then you doom a substantial amount of the web to insecurity. I would rather take approaches that work all of the time than approaches that work some of the time. – atk Feb 4 '14 at 13:32
  • @StasM there are a few reasons I gave the example i did. First, an older version of esapi made the exact mistakes i point out in the attribute encoder. I don't know if it was ever fixed. Second, i didn't have an example on hand for that specific character in the specific context you were looking for, though (third) the example i provided was analogous to the question and demonstrated the same error in judgment. – atk Feb 4 '14 at 13:37
  • 1
    No, it's not analogous, because / has meaning in that context, while in original context it does not, and that was the point of the question! – StasM Feb 4 '14 at 18:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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