Chapter 14. Network Protocol Fuzzing

 

“I own a timber company? That’s news to me. Need some wood?”

 
 --George W. Bush, second presidential debate, St. Louis, MO, October 8, 2004

Fuzzing was born at the University of Wisconsin with the introduction of random arguments to command-line setuid UNIX utilities. Despite this initial association the term fuzzing today is typically thought of as applying to network protocols, and for good reason. Network protocol fuzzing is the most interesting fuzzing transport for security researchers as the discovered vulnerabilities carry the highest criticality. A remotely exploitable vulnerability that does not require valid credentials to reach or any interaction from a target user to exploit is the epitome of discoveries, the gold medal if you will.

Client-side vulnerabilities, affecting Microsoft Internet Explorer, for example, are typically leveraged in the creation of bot nets. Nefarious actors cast a wide net hoping to catch as many fish as they can. For the most part, these captured fish are personal desktop computers sitting on broadband connections. A server-side vulnerability in a network daemon can be equally as useful for the construction of bot nets, but leveraging these vulnerabilities in this fashion is a waste of potential. From an attacker’s perspective, owning software such as a back-end database or enterprise Web server provides a great opportunity for data theft as well as a trusted platform from which to conduct further attacks. In this chapter we introduce network protocol fuzzing and present some of the unique characteristics and challenges posed by this popular fuzzing classification. Along the way we’ll explore a number of network protocol vulnerabilities.

What Is Network Protocol Fuzzing?

As with other types of fuzzing, network protocol fuzzing requires identifying the attack surface, mutating or generating error-inducing fuzz values, transmitting those fuzz values to a target, and monitoring that target for faults. Quite simply, if your fuzzer communicates with its target over some form of socket, then it is a network protocol fuzzer.

The socket communication component of network-based fuzzing poses an interesting nuance in that it creates a bottleneck on our testing throughput. Comparing the transport speed for file format, command-line argument, and environment variable fuzzing to that of the network is like racing an Aston Martin DB9 with a Geo Metro.

Existing network protocol fuzzers tend to come in two flavors. Some are generic frameworks capable of fuzzing a variety of protocols. Tools such as SPIKE[1] and ProtoFuzz, a fuzzer we build from scratch in Chapter 16, “Network Protocol Fuzzing: Automation on Windows,” fall into this category. SPIKE is the most well known fuzzer and is described in greater detail in the next chapter. The other variety of network protocol fuzzers includes those designed to target a specific protocol. Examples of this category include ircfuzz,[2] dhcpfuzz,[3] and Infigo FTPStress Fuzzer.[4] You can guess what protocols each of these mentioned fuzzers is designed to target straight from the name. Protocol specific fuzzers tend to be small targeted scripts or applications, whereas frameworks are generally larger development efforts. We discuss the values of creating and using fuzzing frameworks as opposed to specific stand-alone tools in Chapter 21, “Fuzzing Frameworks.” Next, let’s take a look at some example network protocol fuzzing targets.

Targets

There are thousands of targets to choose from that could expose remotely exploitable network protocol parsing vulnerabilities. In Table 14.1, we provide a small sample of known network vulnerabilities to highlight some common target categories.

Table 14.1. Common Types of Vulnerable Applications and Examples of Previously Discovered File Format Vulnerabilities

Application Category

Vulnerability Name

Advisory

Mail servers

Sendmail Remote Signal Handling Vulnerability

http://xforce.iss.net/xforce/alerts/id/216

Database servers

MySQL Authentication Bypass Vulnerability

http://archives.neohapsis.com/archives/vulnwatch/2004-q3/0001.html

RPC-based services

RPC DCOM Buffer Overflow Vulnerability

http://www.microsoft.com/technet/security/bulletin/MS03-026.mspx

Remote access services

OpenSSH Remote Challenge Vulnerability

http://bvlive01.iss.net/issEn/delivery/xforce/alertdetail.jsp?oid=20584

Media servers

RealServer ../ DESCRIBE Vulnerability

http://www.service.real.com/help/faq/security/rootexploit082203.html

Backup servers

CA BrightStor ARCserve Backup Message Engine Buffer Overflow Vulnerability

http://www.zerodayinitiative.com/advisories/ZDI-07-003.html

These six categories make up a good collection of target pools. However, any application or service that accepts incoming connections could be a potential target. This includes hardware appliances, network printers, PDAs, cell phones, and so on. Any software that has the capability to accept network traffic can be audited using network fuzzing techniques.

For a more thorough understanding of typical targets, we present examples for each of the seven layers defined in the Open Systems Interconnection Basic Reference Model (OSI model),[13] shown in Figure 14.1. Although never implemented directly in any single networking technology, the OSI model is commonly used as a point of reference when dissecting networked technologies to illustrate where particular functionality falls in comparison to other networking layers. In theory, network protocol fuzzing can target any of the seven OSI layers. In practice you will find fuzzers targeting all but Layer 1, the physical layer. As each layer is presented, a historical vulnerability relevant to that layer is provided for further clarity.

Open Systems Interconnection (OSI) model

Figure 14.1. Open Systems Interconnection (OSI) model

Layer 2: Data Link Layer

Relevant technologies at the data link layer include Ethernet frames and 802.11 frames. Layer 2 vulnerabilities are interesting because often the handling of this low-level networking layer is implemented within the operating system kernel. An example of a recent Layer 2 vulnerability was identified by Mitre in CVE-2006-3507.[14] In this vulnerability, an attacker can compromise an AirPort wireless-enabled Mac OS system due to the existence of multiple stack-based buffer overflows. The overflows occur within the context of the kernel and although nontrivial, can be leveraged to completely compromise the affected system. An interesting requirement here is that the attacker must be within range of the wireless network he or she is targeting. If you are ever connected over public wireless in a coffee shop and your Mac OS system goes down, it might be prudent to scan the room and hold the nearest patron holding a laptop hostage for questioning.

Layer 3: Network Layer

Layer 3, the network layer, includes IP and Internet Control Message Protocol (ICMP). Although the most common implementations of TCP/IP have been well tested over the years, vulnerabilities can still be found at this layer. It is also worth mentioning that Windows Vista contains a completely rewritten network stack, indicating that it might be a good target for fuzzing. A recent vulnerability in TCP/IP is described in MS06-032, “Vulnerability in TCP/IP Could Allow Remote Code Execution.”[16] The vulnerability manifests in the kernel due to improper parsing of IP version 4 source routing options. This improper handling leads to a buffer overflow that can be exploited by remote attackers to gain kernel-level access.

Layer 4: Transport Layer

One layer up in the model is Layer 4, the transport layer, which includes TCP and UDP. As mentioned previously, most TCP/IP implementations are well tested, but there have been issues in this layer in the past. A great example of a vulnerability at this level is the old “winnuke” attack that utilized out-of-band TCP packets.[17] The winnuke attack was arguably the simplest remote kernel DoS attack ever seen. All that was required to remotely crash an affected system was to transmit a TCP packet with the TCP urgent pointer set. This pointer can be set easily using any socket API by simply specifying the packet as containing out-of-band data.

Layer 5: Session Layer

The session layer, Layer 5 in the OSI model, houses two particularly problematic protocols, both of which implement remote procedure calls. These technologies are DCE/RPC (Microsoft’s MSRPC) and ONC RPC, also known as Sun RPC. The two protocols are implementations for Windows and UNIX systems, respectively. Numerous critical vulnerabilities have been exposed through these technologies in the past. Among the most significant was patched in Microsoft Security Bulletin MS04-011[18] and was used by the Sasser[19] worm to spread in the wild. The vulnerability was in the lsass.exe binary, which exposed RPC endpoints registered by default on all modern versions of the Windows operating system. Specifically, the vulnerability occurred due to a buffer overflow in the DsRolerUpgradeDownlevelServer function and could be exploited remotely.

Layer 6: Presentation Layer

A good example of a Layer 6 technology that lends itself well to fuzzing is XDR, the eXternal Data Representation used in Sun RPC. Across the XDR-related vulnerabilities that have been discovered in the past, a particularly good example is the xdr_array integer overflow discovered by Neel Mehta.[20] At the core of this discovery was the abuse of an integer overflow. If an attacker specified a large number of entries for an array, an undersized buffer could be allocated, subsequently written to, and overflowed. This memory corruption can be leveraged by attackers to compromise the underlying system.

Layer 7: Application Layer

Layer 7, the application layer, the most commonly thought of and targeted OSI layer with regards to network protocol fuzzing. This layer is the home for common protocols such as FTP, SMTP, HTTP, DNS, and many other standardized and proprietary protocols. Historically more vulnerabilities have been discovered at this layer than at any other. Layer 7 is the most often fuzzed layer because there are so many different implementations for common protocols.

The focus of remainder of this chapter is mostly on Layer 7, but it is important to remember that software at any layer can have implementation problems and should never be ignored when performing a thorough audit of a target.

Methods

The available fuzzing methods are for the most part identical to the methods presented in Chapter 11, “File Format Fuzzing.” At a high level, we can approach both file format and network fuzzing using either a brute force or intelligent methodology. However, there are several differences in these approaches when applied to network-based fuzzing.

Brute Force or Mutation-Based Fuzzing

In the context of file format fuzzing, brute force fuzzing requires the fuzz tester to acquire valid samples of the targeted file format. The fuzzer application then mutates these files in various ways, presenting each test case to a target application. In the context of network fuzzing, the fuzz tester generally uses a sniffer to capture valid protocol traffic, either statically up front or dynamically at runtime. The fuzzer then mutates the captured data and fires it off at the target. This, of course, is not always as trivial as it might sound. Consider, for example, any protocol that implements basic protections against replay attacks. In such situations, simple brute force fuzzing will not be effective for anything other than session initialization code, such as the authentication process.

Another example where a simple mutation-based fuzzer will fail is when attempting to fuzz a protocol that embeds checksums. Unless the checksum fields are dynamically updated by the fuzzer, transmitted data might be dropped by the target software prior to performing any in-depth parsing. Test cases are wasted in these situations. Mutation-based fuzzing works well in the file fuzzing arena, but in general, the next fuzzing method applies better to network protocol fuzzing.

Intelligent Brute Force or Generation-Based Fuzzing

With intelligent brute force fuzzing, you must first put some effort into actually researching the protocol specifications. An intelligent fuzzer is still a fuzzing engine, and thus is still conducting a brute force attack. However, it will rely on configuration files from the user, making the process more intelligent. These files usually contain metadata describing the language of the protocol.

When fuzzing a trivial network protocol, such as the control channel in FTP, intelligent fuzzing is often the best the way to go. A simple grammar describing each protocol verb (USER, PASS, CWD, etc.) and descriptions of the data types for each verb argument will allow for a fairly thorough test. Generation-based fuzzer development can build on an existing framework, such as PEACH,[21] or be built from scratch. In the latter case, a protocol-specific fuzzer is being developed that, for the most part, cannot be repurposed to target other protocols. With this approach, any notion of generic design is thrown away, simplifying the design and implementation process.

There are several tools available publicly that target a single protocol, but many testing tools remain private as they can be seen essentially as a loaded weapon. That is to say, when an author releases a generic fuzzer, whether it is mutation or generation based, the end user still needs to apply some research on his or her end to find vulnerabilities. With a protocol-specific fuzzer, all that is required is a target. If an end user runs that fuzzer against the same target the author did, the same bugs will be uncovered, at which point the tool will be of little value to the original author. This is not entirely true if new targets can be found that the fuzzer hasn’t yet been tested against, which use the same protocol. The decision to release such a tool all boils down to personal beliefs about the ethics and ideals of bug killing and research sharing.

Modified Client Mutation Fuzzing

One of the common criticisms of fuzz testing is that with increasing complexity the developed fuzzer starts to approach the complexity of developing an entire client. So why not work backward? A special class of fuzzing not previously mentioned, this method refers to a technique where the source code (when available) of the client half of the client–server exchange is modified to create a fuzzer. In essence, instead of implementing an entire protocol in a fuzzer, the fuzzer is embedded into an application that already speaks the desired language. This is advantageous in that the fuzzer has access to existing routines required for generating valid protocol data and minimizes the required efforts on behalf of the fuzzer developer.

Although we are unaware of any publicly released fuzzing tools that take this approach, several exploits have been developed in this fashion. One such example is the sshutuptheo[22] OpenSSH exploit written by GOBBLES to take advantage of a preauthentication integer overflow in the popular SSH server.

This approach is especially advantageous for complex protocols like SSH. However, the developer must be aware of any limitations the client might have that will affect code coverage. For example, if SSH is chosen and the client chosen only supports SSH version 1, there will be no code coverage for SSH version 2 specifics. Another disadvantage, of course, is that a legitimate client might have to be heavily modified to cover many test cases.

Fault Detection

Fault detection is a critical component of the fuzzing process, which is why Chapter 24, “Intelligent Fault Detection,” is entirely dedicated to its discussion. Although advanced fault detection methods won’t be covered until that chapter, let’s take a look at some basic techniques as they applies to network protocol fuzzing. The difficulty of detecting faults during network fuzzing is completely variable depending on the target. For example, consider a network daemon that crashes and stops receiving connections after any fault. Clearly, this is great behavior from a rudimentary fault detection standpoint. When the server goes down, simply assume that the last test case caused it to go down. This can be done completely by the fuzzer with no help from a software agent or manual inspection on the target host.

Let us consider another scenario where the targeted application is able to handle faults, or spawns a separate process and maintains the listening socket on its own. In theory, we can trigger an exploitable vulnerability and never know, unless, of course, we apply some form of deeper inspection on the target host. It is safe to assume that during most fuzz testing we have access to the target host. Let’s take a look at some basic approaches we can take toward conducting fault detection on the target host.

Manual (Debugger Based)

Given local access to a machine, the simplest way to monitor exceptions is to attach a debugger to a process. The debugger can detect when an exception is raised, allowing the user to determine what actions to take. Ollydbg, Windbg, IDA, and GDB are all adequate for this task. The problem here becomes correlating which test case or test cause sequence caused the behavior.

Automatic (Agent Based)

Consider a design where the manual debugging process is replaced. Instead of using a debugging application, the fuzz tester has written a debugging agent specific to the target platform that runs on the target. This agent has two jobs. The first job is to monitor for exceptions in the target process. The second job is to communicate with the fuzzer on the remote system. This allows an easy correlation of data to fault detection. The downside to this approach is that the developer will need to create an agent for each platform that will be tested. Again, this concept is dissected in further detail in Chapter 24.

Other Sources

Although debuggers will likely be your most valuable tool for detecting exceptions when conducting network fuzzing, don’t ignore other clues that might be available. Application and operating system logs might provide information on problems that have occurred. As with manually attaching a debugger to the application, the challenge here is to correlate the problem with the responsible fuzz case. Also, be sure to monitor the system for performance degradation, which could indicate hidden issues. This could include increased CPU utilization or perhaps memory exhaustion. A test case that causes an infinite loop might never trigger an exception, but at the same time effectively results in a DoS. The point here is simple: Although debuggers are fantastic tools for uncovering vulnerabilities, you shouldn’t ignore other helpful clues.

Summary

Network protocol fuzzing is perhaps the best known and most widely utilized transport of fuzzing and there are many different ways to go about performing it. Its popularity is caused by a combination of factors, not the least of which is the fact that it can be used to uncover high-risk, remote, preauthentication vulnerabilities. Beyond this, it is a mature type of fuzzing and as such a number of publicly available tools exist to aid security researchers. Armed with the knowledge of a few common approaches to network fuzzing, it’s time to move on to the implementation of a network-based fuzzer.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.216.145.175