blazingfast
Last updated
Last updated
I made a blazing fast MoCkInG CaSe converter!
Looking at the site's JavaScript, we can see that the demo()
function is called on the demo
GET request parameter, which results in the setting of the innerHTML
of the result
element.
The mock()
function is a wrapper for the functions exposed by the WASM module. Interestingly, the str.length
is measured before converting the string to upper case - this leads to inconsistencies in length measurement of some Unicode characters.
Another interesting point to note is that when reading from the buffer, str.length
is not used. Instead, characters are read until a null terminator is reached.
Notably, the mock()
function in the WASM module also uses the initialized length
, which is set to str.length
to validate the buffer.
Therefore, if the str.length
is shorter than the actual number of characters written into the buffer, the mock()
function will not check the entire buffer, allowing the <>&"
characters.
When converting to upper case, some Unicode characters like ß
turn into multiple characters instead. ß
is converted to SS
, which falls within the range of 0 to 128, passing the if (c.charCodeAt(0) > 128) return 'Nice try.';
check.
When str.length
is initialized, the single character ß
is used to calculate the length. However, when writing to the buffer, two characters SS
are written instead. This allows us to bypass the XSS validation.
For instance, ß<
will have a length of 2, but is converted to SS<
when writing to the buffer. The mock()
function uses the initialized length to iterate through the buffer in the for (int i = 0; i < length; i ++)
loop, missing out the final <
character.
Our final hurdle lies in the fact that JavaScript is a case-sensitive language, and our payload is converted to upper case before being added to the innerHTML
. For example, if we use eval()
as our JavaScript payload, then EVAL()
will be called - but the EVAL
function is not defined.
I found inspiration from this post, which shows how we can construct an XSS vector without using letters. In his payload, the following is used to build ""["sub"]["constructor"]("alert(1)")()
.
To modify this payload for our purposes, I just had to change the part where the "alert(1)"
stirng is constructed, and replace it with octal characters for our JavaScript payload, which was
The following script generates the XSS payload, using <img src="x" onerror=PAYLOAD>
.