2

I'm currently testing my own XSS filter and don't know if I thought everything through, so I need some advice.

Let's say my code looks like this:

<script>
var test = {src: "test", layer: {"input": "USER INPUT", "event": "ready"}};
</script>

In this specific case, if I replace \ with \\ and " with \" is it possible to trick my filter? Of course the user input would be where USER INPUT is in my code.

  • 3
    Why don't you use an existing XSS filter? – MikeSchem Oct 10 '17 at 18:42
8

In this specific case, if I replace \ with \\ and " with \" is it possible to trick my filter?

That's not sufficient, your filter is insecure.

E.g., one valid XSS attack vector would be </script><svg onload=alert(1)>, ending up with:

<script>
var test = {src: "test", layer: {"input": "</script><svg onload=alert(1)>", "event": "ready"}};
</script>

Since the XML (HTML) tree is parsed before any JS is evaluated, the closing script tag (</script>) will terminate the script despite being placed within a JS string.

Another problem with your filter are line breaks. If an attacker can insert a 0x0a byte, they can break your script by causing a syntax error (since a double quoted string can't span multiple lines):

<script>
var test = {src: "test", layer: {"input": "
", "event": "ready"}};
</script>

If you're using PHP, a convenient filter function to work safely with user input inside JS is json_encode(). From this answer:

With plain PHP a common and safe approach is to use json_encode() as explained here. E.g.:

var foo = <?php echo json_encode($foo, JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS); ?>

json_encode() returns the JSON representation of a value, hence it's guaranteed to evaulate to a valid object in your JS code and you can just assign it to a variable as shown. But don't omit the additional flags. Depending on the context, an attacker could otherwise use payloads like </script> to break out of the entire script tag.

  • 1
    Does json_encode escape </script> though? – immibis Oct 10 '17 at 19:55
  • 1
    @immibis Yes, with the correct flags! (That's why I linked this answer that addresses this aspect.) – Arminius Oct 10 '17 at 20:02
  • Alternatively, it maybe be useful to use <![CDATA[ tags instead of trying to escape your json. – Matthew Oct 10 '17 at 20:27
  • 1
    @Matthew how does that help? – immibis Oct 10 '17 at 20:34
  • <script> /*<![CDATA[*/ var json = {"myvalue": "</script>"}; /*]]>*/ </script> works just fine, the entire contents of the script tag are treated as character data instead of html. alert(json["myvalue"]); will now popup with </script> – Matthew Oct 10 '17 at 20:40

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.