I posted this to the websec mailing list but I'd like to hear slackers thoughts too:-

I'd like your thoughts on blackbox xss reversing. Do you think one canary/identifier is enough? Is it needed? Using the input as a identifier itself, would there be too many false positives? If a variable doesn't allow alphanumeric characters, how would you create a canary/identifier? If a variable is numeric only how would you know? Hmmm maybe doing a diff on the page with different numbers might work, but what about randomized content unrelated to inputs? Other then tags, attributes and characters what other stuff would be useful to know?

IMHO, a single canary is never sufficient. We already know there exists 100% disjoint sets of characters that can be used for XSS, depending on the context. So the canary, to be useful, would need to cover a wide array of potential characters. Any single character in the canary can result in the whole string being blocked. None of this however takes into account other restrictions such as maximum length, more complex regular expressions ( /<\w*[^>]*>/ ), etc.

That being said, a single canary can still be very helpful as an initial starting point, especially if you already have established the potential injection points. For this I would construct a canary which has a short set of the basic chars needed to escape from one HTML/JS/CSS parsing context to another, e.g. " ' ` ) whitespace </script> and so forth. Wherever this canary is reflected, you just have to look at the given context and see if a suitable escape char (or string) can be injected. If so, 99% of the time you'll have XSS. If the canary is blocked, you have no clue what part of the canary is to blame. So at this point, you just divide and conquer in order to establish which characters, if any, actually get through. Of course, if your original canary doesn't cover all possible weird encodings (UTF-7, overlong UTF-8, double URL, etc) and you are being thorough, then you need to try these out too.

I suppose it could be useful to use a separate and more benign canary to determine where the injection points are in the first place. In this case, you aren't even trying to escape context or inject specific characters... just looking for where you input is reflected (whether persistent or not). For this, I think a relatively short but unique (if needed) integer would be best. No string will be full proof though: it's not uncommon to have to match [a-zA-Z] only or to match only the compliment [^a-zA-Z].

Of course, more complicated things happen when you have intricate (or even simple) application workflows and business logic, conditional content, etc. Simple canaries (whether for manual or automated testing) aren't likely to uncover such scenarios.

I currently use two canary's and it will handle encoded characters within, e.g. " gets converted to \" or %22 etc.

The main problem I had using multiple canary's was they would overlap, so more than one instance would match the other resulting in incorrect results. I fixed this by checking the characters only and encoding variants after the canary. I think the same technique can be applied using just a single one.

You raise a good point though, how do you know a sequence is blocked rather than a character? For example <= may be allowed but <script may not, the character "'" might stop the whole request but you might have injected *&^%")(

So I suppose it's a question of the reverser being clever enough but keeping http requests to a minimum

@.mario

You don't know the context yet, you might have multiple contexts. The idea is to scan the page and report which characters are successful. If for example the filter only allows numbers? How do you determine that? You could inject a range of numbers and characters but that's a lot of http requests. The other problem is if XSS is possible but not with alphanumeric characters, you'd have to somehow determine that and modify your canary to become non-alphanumeric.

But you can find out about the context when approaching the problem with a browser extension, right? So you can start with several non-invasive sets and have them, depending on where the injection happened, grow in complexity. You can limit the amount of fuzzing by knowing about the context. Example: inject XYZ, find XYZ in the page markup, determine injection context, grow set of characters towards the minimal set/sets necessary for the injection point to trigger script execution.

Yeah that's cool, so in these steps I currently do, I should identify context for each of the instances and then I could get better results. If I understand correctly, lets take the following examples:-

1.
<script>
x = 'XYZ';
</script>

2.
<body>
XYZ
</body>

3.
<a href=# onclick="x='XYZ'">test</a>

So in "1" it could be determined from the first injection that you need a single quote or breaking HTML tag to create an injection. So the reverser checks XNSHDY'XNSHDY first then XNSHDY</script>XNSHDY

In "2" tag injection would only be scanned as there's no attributes to inject inside. So it would be interesting to know which tags are allowed.