XSS attack to bypass htmlspecialchars() function in value attribute

59,602

Solution 1

Also, it's important to mention that allowing people to inject HTML or JavaScript into your page (and not your datasource) carries no inherent security risk itself. There already exist browser extensions that allow you to modify the DOM and scripts on web pages, but since it's only client-side, they're the only ones that will know.

Where XSS becomes a problem is when people a) use it to bypass client-side validation or input filtering or b) when people use it to manipulate input fields (for example, changing the values of OPTION tags in an ACL to grant them permissions they shouldn't have). The ONLY way to prevent against these attacks is to sanitize and validate input on the server-side instead of, or in addition to, client-side validation.

For sanitizing HTML out of input, htmlspecialchars is perfectly adequate unless you WANT to allow certain tags, in which case you can use a library like HTMLPurifier. If you're placing user input in HREF, ONCLICK, or any attribute that allows scripting, you're just asking for trouble.

EDIT: Looking at your code, it looks like you aren't quoting your attributes! That's pretty silly. If someone put their username as:

john onclick="alert('hacking your megabits!1')"

Then your script would parse as:

<input type=text name=username value=john onclick="alert('hacking your megabits!1')">

ALWAYS use quotes around attributes. Even if they aren't user-inputted, it's a good habit to get into.

<input type="text" name="username" value="<?php echo htmlspecialchars($_POST['username']); ?>">

Solution 2

There's one way. You aren't passing htmlspecialchars() the third encoding parameter or checking encoding correctly, so:

$source = '<script>alert("xss")</script>';
$source = mb_convert_encoding($source, 'UTF-7');
$source = htmlspecialchars($source); //defaults to ISO-8859-1
header('Content-Type: text/html;charset=UTF-7');
echo '<html><head>' . $source . '</head></html>';

Only works if you can a) set the page to output UTF-7 or b) trick the page into doing so (e.g. iframe on a page without a clear charset set). The solution is to ensure all input is of the correct encoding, and that the expected encoding is correctly set on htmlspecialchars().

How it works? In UTF-7, <>" chars have different code points than UTF-8/ISO/ASCII so they are not escaped unless convert the output to UTF-8 for assurance (see iconv extension).

Solution 3

value is a normal HTML attribute, and has nothing to do with Javascript.
Therefore, String.fromCharCode is interpreted as a literal value, and is not executed.

In order to inject script, you first need to force the parser to close the attribute, which will be difficult to do without >'".

You forgot to put quotes around the attribute value, so all you need is a space.

Even if you do quote the value, it may still be vulnerable; see this page.

Share:
59,602

Related videos on Youtube

Setzer
Author by

Setzer

Updated on July 09, 2022

Comments

  • Setzer
    Setzer almost 2 years

    Let's say we have this form, and the possible part for a user to inject malicious code is this below

    ...
    <input type=text name=username value=
           <?php echo htmlspecialchars($_POST['username']); ?>>
    ...
    

    We can't simply put a tag, or a javascript:alert(); call, because value will be interpreted as a string, and htmlspecialchars filters out the <,>,',", so We can't close off the value with quotations.

    We can use String.fromCode(.....) to get around the quotes, but I still unable to get a simple alert box to pop up.

    Any ideas?

    • Frank Farmer
      Frank Farmer almost 14 years
      Excellent question, because I'm relying on htmlspecialchars() for security -- as are, I'm sure, many people. makes me wonder if you can slip an eval() in or something... especially since I believe the browser de-entitizes before passing values to the js interpreter. I think it'd be most exploitable if you're inserting user data into an onclick or href or other executable attribute; exploiting a value attribute seems harder.
    • SLaks
      SLaks almost 14 years
      @Frank: If you're putting malicious data into Javascript, you need to Javascript-encode it, too.
  • L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
    L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ almost 14 years
    Although I agree that you should quote, htmlspecialchars replaces single- and double quotes.
  • L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
    L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ almost 14 years
    Really? How can you execute code inside a quoted value when you can't close the quote?
  • Setzer
    Setzer almost 14 years
    The space is correct, but you still can't use quotations, that's when String.fromCharCode will come in handy for the above attack
  • Setzer
    Setzer almost 14 years
    I checked that page, but I can't see an attack that will bypass htmlspecialchars and the attribute is quoted
  • Iain Collins
    Iain Collins over 12 years
    +1 Not quoting attributes is a super-easy-to-fix mistake that's very common and easy to fix. With quoting and htmlspecialchars you should be set... at least along as the attributes are not something like href="" or src="" URL values (which are special cases).
  • devicenull
    devicenull about 12 years
    @Longpoke: No, you're very, very wrong (as I just discovered the hard way). htmlspecialchars does NOT escape single quotes by default. You need to pass in ENT_QUOTES as an argument for it to escape them.
  • L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
    L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ about 12 years
    Damn, I'm not good enough to use PHP. better stick to Haskell.
  • JSmyth
    JSmyth over 10 years
    @L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ some with 12+ years of PHP are still not good enough when it comes to PHP's wtfs. You've made the right choice.
  • Scott Arciszewski
    Scott Arciszewski almost 9 years
    I say htmlentities() should be used instead of htmlspecialchars(), with ENT_QUOTES | ENT_HTML5 flags. ;)
  • AviD
    AviD over 8 years
    Most shocking statement I've seen this week: "allowing people to inject HTML or JavaScript into your page carries no inherent security risk itself". WAT. You obviously have heard of XSS, you even mention it yourself, but I am having trouble imagining what kind of misunderstanding you have that would cause such a statement. OF COURSE allowing someone to inject HTML or script into your page for another user is one hell of a security risk, he would have full control over your whole page (and the user's browser, natch). Also input validation is NOT the solution, it is output encoding.
  • Tomáš Zato
    Tomáš Zato about 7 years
    Is this really secure? Also, the quotes in your example would get parsed to &quot;.
  • Rain
    Rain about 2 years
    @ScottArciszewski Why? and now in 2022 is your advice still relevant?