Secure Coding: Attacks and Defenses

Attacks and Defenses

In the following sections, we'll list quite a few types of attacks that your applications may have to withstand. We've divided the discussion into three categories, according to which stage of development the vulnerability relates:

Architecture/design

While you are thinking about the application

Implementation

While you are writing the application

Operations

After the application is in production

The attacks, of course, will usually—not always—take place while the program is running. In each case, we'll try to make a clear distinction.

At the end of each description, we'll discuss briefly how an application developer might approach defending against the attack. We'll develop these ideas in greater depth in subsequent chapters, as we make our case that application security is an essential element at every stage of development.

In these sections we describe only a very few of the many, many ways that security can be breached. We refer you again to the Appendix for pointers to more complete discussions, as well as pointers to formal attack taxonomies.

Architecture/design-level attacks

As a general rule, the hardest vulnerabilities to fix are those resulting from architectural or design decisions. You may be surprised at how many of the vulnerabilities you have heard of we ascribe to errors at "pure think" time.

At the end of this section we list two types of attacks, session hijacking and session killing, that are unusually difficult to defend against from within an application. What's the point of mentioning them? As we argue in Chapter 3, the fact that you as a developer may not be able to institute adequate defenses against an attack does not relieve you of responsibility for thinking about, planning for, and considering how to minimize the impact of such an occurrence.

It's worth mentioning that architectural and design-level attacks are not always based on a mistake per se. For example, you may have used the telnet program to move from one computer to another. It does well what it was designed to do. The fact that its design causes your username and password to be sent along the cables between computers, unencrypted, is not a "flaw" in and of itself. Its design does make it an unattractive choice for using in a hostile environment, however. (We use ssh instead.).

The following are the main attacks we've observed at the architecture/design level:

Man-in-the-middle attack

A man-in-the-middle (or eavesdropping) attack occurs when an attacker intercepts a network transmission between two hosts, then masquerades as one of the parties involved in the transaction, perhaps inserting additional directives into the dialogue.
Defense: Make extensive use of encryption—in particular, strong cryptographic authentication. In addition, use session checksums and shared secrets such as cookies. (You might, for example, use ssh instead of telnet, and encrypt your files using utilities such as PGP or Entrust.)

Race condition attack

Certain operations common to application software are, from the computer's point of view, comprised of discrete steps (though we may think of them as unitary). One example is checking whether a file contains safe shell (or "batch") commands and then (if it does) telling the host system to execute it. Sometimes, the time required to complete these separate steps opens a window during which an attacker can compromise security. In this example, there may be a very brief window of opportunity for an attacker to substitute a new file (containing attack code) for the previously checked file. Such a substitution can trick an application into running software of the attacker's choosing. Even if the resulting window of opportunity is too short for a human to reliably exploit it, a program might well be able to repeatedly test and then execute the attacker's program at just the right moment in time. Because the result often depends upon the order in which two or more parallel processes complete, this problem is known as a "race" condition.2Defense: Understand the difference between atomic (indivisible) and non-atomic operations, and avoid the latter unless you are sure there are no security implications. (Sample actions that do have security implications include opening a file, invoking a subprogram, checking a password, and verifying a username.) If you are not sure whether an operation is atomic, assume that it is not—that is, that the operating system may execute it in two or more interruptible steps.

Replay attack

If an attacker can capture or obtain a record of an entire transaction between, say, a client program and a server, it might be possible to "replay" part of the conversation for subversive purposes. Impersonating either the client or the server could have serious security implications.
Defense: Same as for the man-in-the-middle attack; in addition,consider introducing into any dialog between software elements some element (e.g., a sequence identifier) that must differ from session to session, so that a byte-for-byte replay will fail.3

Sniffer attack

A program that silently records all traffic sent over a local area network is called a sniffer. Sniffers are sometimes legitimate diagnostic tools, but they are also useful to attackers who wish to record usernames and passwords transmitted in the clear along a subnet.
Defense: This attack is best addressed at the network level, where its impact can be diminished (but not removed) by careful configuration and the use of "switched" network routers. Still, as an application writer, you can render sniffers fairly harmless by making maximal effective use of encryption.

Session hijacking attack

By exploiting weaknesses in the TCP/IP protocol suite, an attacker inside the network might be able to hijack or take over an already established connection. Many tools have been written and distributed on the Internet to implement this rather sophisticated technical attack.
Defense: This network-level attack is quite difficult to defend against from within application software. Encryption, of course, is a help (although a discussion of its limitations is beyond our scope here). And some operational procedures can help detect a hijacking after the fact, if careful logging provides enough information about the session.

Session killing attack

Legitimate TCP/IP sessions can be terminated when either of the communicating parties sends along a TCP reset packet. Unfortunately, an attacker inside the network might be able to forge the originating address on such a packet, prematurely resetting the connection. Such an attack could be used either to disrupt communications or, potentially, to assist in an attempt to take over part of a transaction (see the description of session hijacking above).4Defense: Like session hijacking attacks, session killing attacks are difficult to defend against from within an application. Unfortunately, we believe that deterrence from within the application is not possible. However, your application may be able to compensate after the fact by either reasserting the connection or reinitializing the interrupted transaction.

Endnotes

1Note also that in this definition we don't limit ourselves to events that take place in an electronic realm. An attack against an application could well involve a physical act, such as carrying a hard drive out of a data center in a briefcase. For the most part, though, we'll concentrate on electronic attacks in this book.

2The example would also be described in the technical literature as a "late binding" problem.

3You might consider, for example, using the (trustworthy) current time as an example of a sequence identifier, such as the Kerberos 5-minute overlap requirement.

4Note, too, that such attacks can be successful even if the attacker is not on the local segment, if the network is not doing any ingress filtering—that is, if there's no check to see if a data packet is really coming from the destination listed inside the packet.

About the Authors

Mark Graff is Chief Cyber Security Officer for Lawrence Livermore National Lab and was formerly Network Security Architect and Security Coordinator at Sun Microsystems. He has been a Congressional expert witness, has lectured on network security topics at the Pentagon, and has appeared before the Presidential Commission on Infrastructure Survivability.

Ken van Wyk is Director of Technology for Tekmark Global Service's Technology Risk Management (TGS-TRM) practice, and was Chief Technology Officer and Co-Founder of security firm Para-Protect Services. He was one of the founders of the Computer Emergency Response Team (CERT), and is also the co-author of O'Reilly's Incident Response and Secure Coding: Principles & Practices

Source of this material

This is an excerpt from Chapter 1: No Straight Thing from the book Secure Coding (ISBN: 0-596-00242-4) written by Mark G. Graff and Kenneth R. van Wyk, published by O'Reilly & Associates.