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.?

1

2 Answers 2

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.

7
  • 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, 2018 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. Jul 24, 2018 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, 2018 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. Jul 24, 2018 at 15:22
  • You then block legitimate URLs with whitespaces, and still allow some harmful ones like blob:
    – Xenos
    Jul 24, 2018 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.

5
  • 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? Jul 23, 2018 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, 2018 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. Jul 23, 2018 at 22:02
  • The quotes are a meta HTML character that would have been encoded as shown in HTML living spec
    – Xenos
    Jul 24, 2018 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, 2018 at 18:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .