IBM®
Skip to main content
    Country/region [select]      Terms of use
 
 
      
     Home      Products      Services & solutions      Support & downloads      My account     

developerWorks > Security >
developerWorks
Building secure software: Selecting technologies, Part 2
69KBe-mail it!
Contents:
heading
heading
Host-based authentication
Physical tokens
Biometric authentication
Cryptographic authentication
Defense in depth and authentication
heading
Resources
About the authors
Rate this article
Related content:
Building secure software: Selecting technologies, Part 1
Software security principles: Part 1
Subscriptions:
dW newsletters
dW Subscription
(CDs and downloads)
Operating systems and authentication technologies

John Viega (viega@securesw.com), Chief Technology Officer, Software Solutions
Gary McGraw (gem@cigital.com), Vice president, Reliable Software Technologies

01 Feb 2002

Before you select the security technologies that meet your needs, you've got to do your homework, according to Gary McGraw and John Viega, authors of Building Secure Software: How to Avoid Security Problems the Right Way (Addison-Wesley, 2001; reprinted by permission). This article and its predecessor are based on chapter 3, "Selecting technologies," which explores common choices faced by designers and programmers. Part 1 explored effective ways of choosing a programming language and a distributed object platform. Here in part 2, John and Gary take a look at the pitfalls of choosing an operating system, and the security challenges of authentication technologies, including host-based authentication, physical tokens, and biometric authentication.

Choosing an operating system
Modern operating systems are logically divided into a system kernel and user-level code (often called "user space"). Programs run in user space, but occasionally call down into the kernel when special services are needed. Many critical services are run in kernel space. The kernel usually has some sort of security model that manages access to devices, files, processes, and objects. The underlying mechanism and the interface to that mechanism tend to be significantly different depending on the operating system.

As far as the average program is concerned, the details of the security implementation don't matter very much. For programs running in user space, there are common security restrictions implemented in the kernel of almost all modern operating systems (in one fashion or another). One of the most important is process space protection. In a good operating system, a single process is not allowed to access any of the memory allocated to other processes directly. Additionally, no process can directly access the memory currently marked as "in use" by the operating system. All inter-process communication is in this way mediated by the operating system. Windows NT/2000 and all Unix systems afford this kind of protection. Other Windows systems, up to and including Windows ME do not offer it. The upshot of this fact is that in an operating system like the PalmOS, or Windows 95, 98 and ME, it is often possible to change data in other programs by exploiting a bug in a single program. That's possible because all programs share a single address space. From a security perspective, that's awful.

This has bigger ramifications than most people realize. For example, if you store a shared secret on an Internet-enabled Palm Pilot, any other application on that Palm Pilot has access to the secret. It can be read or changed. Essentially, if you allow an attacker to run code on such a machine through any means, the attacker can completely take over the machine.

As part of standard user-level protections in more advanced operating systems, processes can't directly access devices attached to the computer, such as any hard drives, video cards, and the like, at least without special permission. Instead, special pieces of software inside the kernel called device drivers act as wrappers to these devices. User-level programs must make calls through the kernel to these device drivers in order to access hardware. Most frequently, such calls are made indirectly, though a system call interface. For example, in Unix, devices appear to the application as files on the file system; meaning the application communicates with the device by performing file reads and writes.

The Windows 95/98/ME family of operating systems was not originally designed to afford the kinds of protection modern operating systems provide. This product line descends from the original Windows, and ultimately the original versions of DOS! Dinosaur operating systems like DOS were designed in a time when security was not a significant issue, since most personal computers were single user devices that were only rarely connected to any network. While some of the basic security functionality has since been added to this line of product, certain aspects of the operating system design make it impossible to build a security system for the operating system that is not exploitable. As a result, these add-on features end up being more of a reliability mechanism than a security mechanism. It is still possible with Windows 98 and its ilk to protect a computer against a network. But once an attacker can run code on such a machine, the attacker instantly attains complete control.

In popular operating systems, there are generally no security checks in the kernel, except at the interfaces through which the end user calls into the OS. For example, there is rarely an effort made to protect one part of the kernel from other parts of the kernel; they are all explicitly trusted. This trust is usually extended to code that may not really count as part of the operating system but still needs to run in the kernel. In fact, that's the case for device drivers, which are often shipped by the manufacturer of a hardware device. Sometimes third-party device drivers are even used. Talk about blindly extending trust!

Kernels tend not to protect against themselves. That is, the entire operating system stands and falls as a whole. Thus if a bad enough security flaw is found in any part of the operating system, anyone able to exploit that flaw can exert complete control over an entire machine from software. Building a kernel that is capable of protecting against itself is difficult, and usually has a large negative impact on performance. That is why it is done only infrequently. Nonetheless, there do exist operating systems that afford this sort of protection, one of the more notable being Trusted Mach, which has been used primarily for research purposes. A few similar Unix operating systems are available. There is no such implementation for the Windows platform currently available.

Authentication technologies
Authentication problems are probably the most pervasive class of security problems if we ignore software bugs, meaning that choosing a reasonable authentication technology is important. Part of the reason is that even a well-designed password-based system is usually easy to break since users almost always pick bad passwords. However, a password-based authentication approach is unfortunately not the only kind of authentication that is frequently weak. There are many diverse types of authentication mechanism, and each is difficult to get right.

Host-based authentication
A common way to authenticate network connections is to use the IP address attached to the connection. This technique is popular with firewall products, for example. Sometimes, people will instead authenticate against a set of DNS names, and will thus do a lookup on the IP address before authenticating. Both of these techniques are fairly easy to implement since the information on how to do so is readily available. Similar authentication techniques use the MAC address of the remote host's network card, or any sort of unique ID associated with that machine (such as a Pentium III processor ID, if available). You can also place identifiers on a client the first time they connect, and then have these data sent on subsequent connections. Such identifiers are often referred to as "cookies" or "tickets".

Host-based authentication is generally a quick and dirty way to raise the bar a notch, but is close to useless. If you rely on MAC addresses, processor IDs, or cookies, remember that they are essentially self-reported by an untrusted client. An attacker sophisticated enough to download and use a tool can cause the client to report a lie by modifying packets traversing the network. If you provide encryption, then an attacker can generally still attack the technique by modifying your client. This security risk can be managed by using an appropriately skeptical design (one that doesn't require a great deal of trust in the client).

IP addresses and DNS addresses might seem more reliable, and in some sense they are. Let's say that an attacker forges the IP address in packets going out from the attacking box so that the packets appear to come from an address that should be authenticated (this is called IP spoofing). In most situations, that, by itself, is not good enough. There are several reasons why:

First, the attacker needs to make sure that the fake packets will actually be routed to the target. There are tools to automate this task.

Second, even if packets make it to the target, responses will be routed to the forged IP address. In order for the forgery to be useful (in the most common sorts of attack), the attacker needs to receive those responses. The only real way to accomplish that is for the attacker to become interposed somewhere on the route between the spoofed machine and the target. Usually, what happens in practice is that the attacker will break onto a machine that is on the same network segment as one of the two machines in question (usually the network of the target). Once you're on the same network segment, you're almost always able to see all traffic addressed to the machine of interest. (The major exception is being on a switched network segment.)

Third, spoofing attacks are difficult to execute. You don't often see script kiddies executing them. Vendor FUD (fear, uncertainty, and doubt spread to sell product) aside, there are really not that many attack tools that present a complete one-stop, no-brains-required spoofing solution. As a result, any application of IP spoofing requires a significant amount of technical depth.

So why even worry about IP spoofing? The problem is that it's not extraordinarily difficult for a skilled attacker to spoof IPs if the attacker can break on to your local network. While IP-related authentication certainly raises the bar high enough to keep out all except those of significant skill, it's not something you should ever consider likely to be perfect.

DNS authentication can be defeated with IP spoofing. There are additional ways to defeat DNS authentication. One is to send a fake response to the DNS lookup. Similarly, one can tamper with the actual response from a legitimate query. These kinds of attacks require the same level of skill as IP spoofing. Another kind of attack on DNS systems is a "cache poisoning" attack, where the malicious hacker relies on flaws in some implementations of DNS to "hijack" domain names. Such an attack can point valid domain names at attacker addresses. In some cases, mistakes by system administrators can carry out this attack accidentally (as was the case with Microsoft in 2000). While not all implementations of DNS are subject to this kind of attack, many real-world sites are completely susceptible. Plus, this attack is far easier to launch than the more sophisticated spoofing attacks. For this reason, we do not recommend ever using DNS names for security, especially since using IP numbers is a far more reliable (though not perfect) approach.

Physical tokens
One common technique for authentication is to use physical tokens, such as a key, a credit card, or a smart card. Without the physical token, the argument goes, authentication should not be possible. This sort of authentication is widespread, but has a number of associated problems.

In the context of computer systems, one problem with physical tokens is that some sort of input device is necessary for every client to the system. If you have an application where you want any person on the Net with his or her own computer to be able to use your system, this requirement is problematic. Most people don't own a smart card reader. (Even most owners of American Express Blue cards haven't figured out how to install the ones they were sent for free.) In the case of credit cards, letting the user type in the credit card number nominally solves the problem. However, this solution suffers in that it doesn't really guarantee that the person typing in the credit card number is actually in possession of the card. The same risk that applies in the physical world with regard to use of credit cards over the phone applies to systems relying on credit card numbers for authentication on the Net.

Another problem with physical tokens is that they can be lost or stolen. In both cases, this can be a major inconvenience to the valid user. Moreover, many physical tokens can be duplicated easily. Credit cards and keys are good examples of things that are easily cloned. The equipment necessary to clone a magnetic stripe card is cheap and readily available. Hardware tamper proofing is possible and tends to work quite well for preventing duplication (though it is not infallible), but on the downside it is also quite expensive to place in practice.

Sometimes an attacker doesn't need to steal the physical token in order to duplicate it. A skilled locksmith can duplicate many types of keys just by looking at the original. Molding the lock is another option. Credit card information can be written down when you give your card to a waiter in a restaurant or a clerk at the video store.

Even if you're careful with your card, and only use it in ATMs, there's still the possibility for attack. Some hilarious but true cases exist where attackers go to the trouble of setting up a fake ATM machine in a public place. The ATM is programmed to appear to be broken once people put their card in the machine. However, the machine really does its nefarious job, copying all the relevant information needed to duplicate cards that get inserted. Other attackers have added hardware to valid ATMs to apply the same attacks with real success.

Biometric authentication
Biometric authentication is measuring physical or behavioral characteristics of a human and using these characteristics as a metric for authentication. There are a number of different types of biometric authentication that are used in real-world systems. Physical characteristics that can be measured include fingerprints, features of the eye, and facial features.

Examples of behavioral biometrics include handwritten signatures and voice prints. In the real world, we validate signatures by sight, even though a skilled attacker can reliably forge a signature that most people cannot distinguish from the original. If a biometric system were to capture the entire act of signing (pen speed, pressure, etc.) in some digital format, then it would be far more difficult to forge a real signature; high-quality forgeries usually take a fair bit of time.

Biometric authentication is a convenient technology, because people can't really forget their authentication information like a password or lose it like a physical token. Most people's eyes can't be removed and stored elsewhere. The necessary information is always with you. Nonetheless, there are plenty of problems with biometric authentication.

Much like authentication with physical tokens, biometric authentication has the limitation that you need to have access to a physical input device in order to be able to authenticate. Therefore, it's not appropriate for many types of applications.

Another problem that biometrics vendors often overlook is the security of the input mechanism. If an attacker can tamper with the authentication hardware, it might be possible to inject falsified digital data directly into the device. One might capture such information by observing the data generated for valid users of the system as it whizzes by on a wire. If it's possible to tamper with the authentication device, such data capture should not be all that difficult. And once your biometric pattern has been compromised, it's not possible to make a new one. You only get so many eyes! It's usually a good idea to have the security of important biometric input devices supplemented by having in-the-flesh guards, thus greatly reducing the risk of physical tampering.

Behavioral biometrics can be fickle. The best example is using a voiceprint for authentication. What happens if someone is sick? If the system isn't lenient enough to handle this situation, people may be wrongly denied authentication if they have a stuffy nose. However, if the system will accept a similar voice that sounds "sick," then it's more likely to fall prey to attackers who can reasonably mimic the voice of valid users of the system.

Another problem is that biometric identifiers are generally unique, but are not secret. If a system authenticates based solely on fingerprints, an attacker could reasonably construct a fake hand after carefully gathering fingerprints of an authorized user of the system. This kind of an attack just requires following someone into a bar and getting their beer glass. Additionally, note that such systems encourage people to steal parts of your body, which is never a good thing. To help thwart these kinds of attacks, better biometric systems will factor in "liveness" measures like temperature and blood flow to try to gain assurance that the fingerprints are from a live human being actually touching the device.

Nonetheless, if the physical security of the authentication device is an issue, what happens if a digital representation of someone's fingerprint is stolen? Yes, we can invalidate that fingerprint. But the user only has 10 fingers. What happens when an attacker steals all 10 fingerprints? In a password system, if your password gets compromised, you can just change it. You're not likely to be able to change your fingerprints quite as readily.

Another issue to consider is that a significant number of people believe that the collection of biometric information is an invasion of privacy. DNA might be the ultimate authentication mechanism for a human (at least one without an identical twin), but DNA encodes enough information for an insurance company to deny issuing insurance to you on the grounds of a disease you have not yet contracted, because your genetics show you to be susceptible to the disease.

Cryptographic authentication
Cryptographic authentication uses mathematics and a digital secret in order to authenticate users. This type of authentication can be seen as a digital analog to having a physical token. While physical access to an input device is no longer a problem, the same sorts of issues we raised above otherwise apply. Most importantly, cryptographic authentication information can be stolen. Unfortunately, it's often quite easy to steal digital data.

Defense in depth and authentication
We believe that the only viable strategy for authenticating users is to apply the defense in depth principle, mixing a number of authentication techniques. In terms of ATM withdrawals, credit card companies have done very well by mixing physical tokens with a password-based scheme. Just relying on a physical token would make it easy for wild adolescents to deplete the coffers of their parents. Similarly, relying only on the simple four-digit PIN number, but no physical token, would be absolutely horrible. Attackers would be free to try to break into your account at their leisure, and would be able to succeed fairly quickly, especially if they have some help (there are only 10,000 possible pins...not that large a number in the grand scheme of things). However, when these two technologies are combined, they provide a fairly significant bar to jump. The attacker needs to steal your card AND try an expected 5,000 pin numbers. Hopefully, a victim will report the card as missing before the attacker gets that far.

Defense in depth can also be used to solve the problem of protecting cryptographic authentication information (usually called a key) from people who break into your machine. The key can be encrypted, using a password (hopefully not weak) as the encryption key. Every time cryptographic authentication is to be used, a password must be given in order to decode the key. That way, even if someone steals the bits, they would still need the password.

This solution still poses a problem when using cryptographic keys in a server environment (host-to-host authentication instead of user-to-host authentication). That's because servers need to be able to use keys in an automated fashion, without user intervention. One option is to not encrypt the key. If the key is encrypted, you can save the password somewhere on the disk, and read it in when necessary. However, you're just moving the problem to another part of the disk if you do that. A third option is to require manual intervention once, at program startup, then keep the decrypted key only in memory, not on the disk (on the theory that it's usually a lot more difficult for an attacker to snag if it only exists in memory). This solution means that a server machine cannot reboot unattended. Someone needs to be around to feed passwords to any software needing encryption keys.

Conclusion
In these articles, we have emphasized the importance of comparing and contrasting technologies and coming up with those that best meet system security requirements. We did this by frankly discussing some of the risks, pitfalls, and design techniques that surround common technology decisions. The key to using this material well is remaining cognizant of security when security-critical technology choices are being made. Using the best available crypto on the weakest platform on the planet won't buy you much security! We have discussed a number of the most common choices that technologists and security practitioners must make, and how they impact security.

Resources

  • Of course, you can find a wide range of security articles in the developerWorks Security topic including Part 1 of this series.

  • The XML Security Suite, available on alphaWorks, provides security features such as digital signature, encryption, and access control for XML documents.

  • IBM security services can help you determine what your risks are, and then design a security program to address them.

About the authors
John Viega is the CTO of Secure Software Solutions. He's co-author of Building Secure Software (Addison-Wesley, 2001) and Network Security and Cryptography with OpenSSL (O'Reilly, 2002). John has authored more than 50 technical publications, primarily in the area of software security. He is also known for security tools, and for writing Mailman, the GNU Mailing List Manager. You can contact him at viega@securesw.com.


Gary McGraw, Ph.D., is the Chief Technology Officer at Cigital. Dr. McGraw is a noted authority on software security and has co-authored four popular books: Java Security: Hostile Applets, Holes, & Antidotes (Wiley, 1996) and Securing Java: Getting Down to Business with Mobile Code (Wiley, 1999) with Prof. Ed Felten of Princeton; Software Fault Injection: Inoculating Programs Against Errors (Wiley, 1998) with Cigital co-founder and Chief Scientist Dr. Jeffrey Voas; and Building Secure Software (Addison-Wesley, 2001) with John Viega. Dr. McGraw regularly contributes to popular trade publications and is often quoted in national press articles. You can contact him at gem@cigital.com.



69KBe-mail it!
Rate this article

This content was helpful to me:

Strongly disagree (1)Disagree (2)Neutral (3)Agree (4)Strongly agree (5)

Comments?



developerWorks > Security >
developerWorks
  About IBM  |  Privacy  |  Terms of use  |  Contact