3

Is reflected XSS impossible, when HTML meta-characters, e.g., < and >, are encoded, and the result output in HTML context?

I have a website that displays the URL path directly in HTML context, i.e.,

www.mysite.com/helloworld results in helloworld being displayed between <body> tags.

However, some meta-characters, e.g., < and >, are HTML escaped.

In this case, is it possible to perform a reflected XSS attack, like some esoteric UTF encoding attack etc.?

6

This depends on the context. I am assuming you're using htmlentities() function, which would be generally safe. It does more or less the exact same thing as htmlspecialchars() does.

Both of which secure against general XSS, and prevent event-based XSS when the sanitized parameter is injected into a HTML tag.

They both do not prevent javascript: attacks, which can happen if injecting the parameter value into a link, iframe, or other similar tag. If injecting a src or href from any of them tags, I would recommend first removing any whitespace from the parameter, and then checking for both javascript: and data:.

javascript:alert(0) will give you an alert when injected into a link or iframe. data:text/javascript:alert(0) will do the same. data:text/html:<script>alert(0);</script> does the same thing too, and bypasses strip_tags.

The reason for first removing whitespace, is to prevent an attacker dropping a line break/CRLF character in the middle of their payload, so PHP reads it as not being javascript: or data: when blocking the payload, but it will still execute as javascript will ignore it.

I hope that explains what type of attacks are possible, it's very easy to claim that htmlentities() and htmlspecialchars() are a one-fits-all solution to the problem, but depending on the situation, that can be extremely dangerous advice.

  • 1
    Don't try to sanitize. Pseudo-protocol javascript: is not always required. Simply apply OWASP's rules: no plain custom data in src or href attribute (only insert dynamic data here if the complete origin is constant). See owasp.org/index.php/… – Xenos Jul 24 '18 at 7:54
  • Yes, I meant to add a colon. Thanks for the correction. And although it'd be great if everyone followed OWASP's rules, it is important to note that these attacks exist. My above sanitized example should be impossible to bypass. Let me know if you find a non-whitespace character to bypass. – Cillian Collins Jul 24 '18 at 14:32
  • That would still allow ssh: protocol or any other (harmful) protocol. Besides, I wonder what you would like to do if you get the javascript: or data: matching (since it's not in the answer)... And if you've also include U+000C in the whitespace list to remove [Note: that might be better suited for chat] And you cannot tell if new protocol will appear in the next years that would be injectable as javascript: is – Xenos Jul 24 '18 at 15:01
  • You raise some good points. On a personal level, I would never trade security for functionality, but a lot of developers would rather place raw input into the value of a link or iframe. A solution I would use to sanitize it would be preg_replace("/\s+/", "", htmlentities($input)); which would encode the user's input using the htmlentities() function as suggested by OP, and then replace all whitespace. The result of this should be easily checked for javascript: and data: as there are no whitespace characters in there. – Cillian Collins Jul 24 '18 at 15:22
  • You then block legitimate URLs with whitespaces, and still allow some harmful ones like blob: – Xenos Jul 24 '18 at 16:18
0

If quotes are not escaped and the text is placed inside of a quoted html attribute, then a value that sets a javascript-bearing attribute like " onmouseover="alert(0) may work.

  • 1
    No, HTML entities will be read as an actual value, and be given no significant authority. I tested your example and it does not work in my case. I don't see this working but maybe it is browser specific or something? – Cillian Collins Jul 23 '18 at 21:35
  • If the server generated some html by doing '<div title="' + yourValue + '">', then injecting the value " onmouseover="alert(0) will result in the html <div title="" onmouseover="alert(0)">, which will trigger some javascript when the user hovers over the element. – Macil Jul 23 '18 at 21:41
  • There are better alternatives for event-based payloads (such as onload where possible, or even some onfocus combined with autofocus will automatically execute the payload too). Still, I don't believe PHP would allow this when the htmlentities() function is being used. – Cillian Collins Jul 23 '18 at 22:02
  • The quotes are a meta HTML character that would have been encoded as shown in HTML living spec – Xenos Jul 24 '18 at 7:59
  • I agree that any good standard html encoding function will encode quotes, but OP doesn't know that the site is using such a function if they don't test for it. I've seen multiple sites in the wild which specifically encoded < and > but not quotes. – Macil Jul 25 '18 at 18:02

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.