First this challnege was awesome and I learned alot from it.
Description
The challenge was that I should execute alert(domain) showing calc.buggywebsite.com, and bypassing the CSP.
Let's take a look on the challenge, first you will notice the script.js file from this file you will notice that there is a postMessage function on the website
this mean that there is a function to receiving the message from this postMessage and do action with it, if you searched on the the source code of the the main website you will notice that there is an iframe whcih include an HTML fila called fram.html this file is show the numbers and results of the calcuator on the website, open the source code and you will find a file frame.js, the file content
first line is the listener which wait the postMessage request and the executed function is receiveMessage on the function there is a filter on the requests domain (origin) the ReqEx have some issues which lead to bypass it the RegEx is
/^http:\/\/calc.buggywebsite.com/
this RegEx can be bypassed with different ways for example the (dot) on the RegEx if you don't escape it can be a character so something like this calcXbuggywebsite.com can bypass this filter I added a simple line in my hosts file
127.0.0.1 calc.buggywebsite.com.test.test
now I can open this calc.buggywebsite.com.test.test and it will show the localhost and if I sent a request from it to the vulnerable origin filter it will be accepted so now we bypassed the origin filter.
The other condition is if the message not include (single quotes) or (&) so show it on the page so if we write on the page's console some thing like this
postMessage('testing here')
it will be printed on the page, try a simple XSS payload and you will find another problem which is the CSP this one
script-src 'unsafe-eval' 'self'; object-src 'none'
I opened the CSP Evaluator and it show me this tow info
'unsafe-eval' allows the execution of code injected into DOM APIs such as eval().
'self' can be problematic if you host JSONP, Angular or user uploaded files.
it really helped me now the website is using angular so I can use it to execute the XSS payload instead of the common payloads I tried to execute a simple angular code but the didn't execute it
<div ng-app>{{1+1}}</div><script src=angular.min.js></script>
notice here I included the angular file because page /frame.html not have the file, we can notice from here that there is a sandbox after thinking I tried to execute it with iframe using the srcdoc attribute like that
<iframe srcdoc="<div ng-app>{{1+1}}</div><script src=angular.min.js></script>">
and it works with me
now we just need to add the payload and the challenge solved right? no it's wrong the payload is
{{a=toString().constructor.prototype;a.charAt=a.trim;$eval("a,alert(document.domain),a")}}
and there is a big issue here the attribute of srcdoc is using (double quotes) and the payload which will alert is using it too because we can't use (single quote), I spent a lot of hours on this step it solved with encoding the payload
a=toString().constructor.prototype;a.charAt=a.trim;$eval("a,alert(document.domain),a")
and use it with fromCharCode fucntion so the final payload I used is
<iframe srcdoc="<script src=angular.min.js></script><div ng-app>{{$eval(({}.toString()).constructor.fromCharCode(97, 61, 116, 111, 83, 116, 114, 105, 110, 103, 40, 41, 46, 99, 111, 110, 115, 116, 114, 117, 99, 116, 111, 114, 46, 112, 114, 111, 116, 111, 116, 121, 112, 101, 59, 97, 46, 99, 104, 97, 114, 65, 116, 61, 97, 46, 116, 114, 105, 109, 59, 36, 101, 118, 97, 108, 40, 34, 97, 44, 97, 108, 101, 114, 116, 40, 100, 111, 99, 117, 109, 101, 110, 116, 46, 100, 111, 109, 97, 105, 110, 41, 44, 97, 34, 41))}}</div>"></iframe>
I added to my exploitation code
if you ask why I encoded the payload with base64 because the closing tag of script will break the script on the exploitation code, and i got the alert
Thanks for reading.
Comments
Post a Comment