4

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.

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

1 Answer 1

10

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.

8
  • 1
    Does json_encode escape </script> though?
    – user253751
    Oct 10, 2017 at 19:55
  • 1
    @immibis Yes, with the correct flags! (That's why I linked this answer that addresses this aspect.)
    – Arminius
    Oct 10, 2017 at 20:02
  • Alternatively, it maybe be useful to use <![CDATA[ tags instead of trying to escape your json.
    – Matthew
    Oct 10, 2017 at 20:27
  • 1
    @Matthew how does that help?
    – user253751
    Oct 10, 2017 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, 2017 at 20:40

You must log in to answer this question.

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