Intigriti's December XSS Challenge Writeup
This month’s Intigriti’s XSS challenge was interesting as a couple of hours after Frans Rosén submitted an unintended solution, and I got interested in that one more than in the original.
Challenge on webarchive https://web.archive.org/web/20201208103813/https://challenge-1220.intigriti.io/. Vulnerable script on webarchive https://web.archive.org/web/20201210000939/https://challenge-1220.intigriti.io/script.js.
Solution 1
Parsing query parameters using custom function (e.g. getQueryVariable
, line 3) allows to specify those in URL hash on line 11 (below) window.location.href.substr(...)
, as String.prototype.indexOf()
is looking for the first occurance of ?
(question mark):
|
|
Two of the sources (num1
and num2
) are passed to setNumber
function (line 23) when clicking on a number, which itself then passes it to parseInt
(lines 101, 104), also there is no protection against iframing it, so, having such URL https://challenge-1220.intigriti.io/#?num1=parseInt&operator=%3d&num2=eval in an iframe, we can execute parseInt=eval
as operation
in the context of the vulnerable webpage, because =
is whitelisted as an operator:
|
|
Now we can redirect the iframe to a new hash https://challenge-1220.intigriti.io/#?num1=parseInt&operator=%3d&num2=alert(document.domain)// and as, only, the URL hash is changed, no request is going to be sent to the server and if the user hits any number, the following script will be executed alert(document.domain)//<number>
.
A similar technique can be leveraged when having calc=eval
executed then redirecting to a new hash https://challenge-1220.intigriti.io/#?num1=alert(document.domain)&operator=%3d&num2=eval, where the user has to hit an operator
POCs:
- for numbers - https://jsfiddle.net/td6yzm0w/1/
- for operators - https://jsfiddle.net/td6yzm0w/
Solution 2
Now the intended one, that leads to DOM XSS (Cross site swagging) with no user interaction.
Very right, because getQueryVariable
iterates in a loop and takes the value of the last occurrence of the requested parameter (lines 5-10)
|
|
Chain:
- https://challenge-1220.intigriti.io/?num1=onhashchange&operator=%3d&num2=init&#d& - execute
onhashchange=init
- https://challenge-1220.intigriti.io/?num1=onhashchange&operator=%3d&num2=init&#d&num1=calc&num2=eval - changing hash, triggering
onhashchange
which isinit
now and executingcalc=eval
- https://challenge-1220.intigriti.io/?num1=onhashchange&operator=%3d&num2=init&#d&num1=calc&num2=eval&num1=alert(‘achievement%20unlocked:%20unlimited%20swag%20vouchers%20’%2bdocument.domain) - triggering
onhashchange
and passingalert('achievement unlocked: unlimited swag vouchers '+document.domain)
toeval
Now you can claim your unlimited swag voucher with 0 click: