Case Study: OpenSSH


In this chapter, you have learned about the four-phase application review process that functions at a high level. To see how these steps could be applied in a real-world setting, you walk through a practical example using the OpenSSH server. The source code is available from www.openssh.com/, and the version is OpenSSH 4.3.

Note

For those unfamiliar with OpenSSH, it's the premier Secure Shell (SSH) server on the Internet. It provides an encrypted interactive shell service to authenticated users for a particular machine. More details are available on the OpenSSH Web site (www.openssh.com).


Preassessment

Referring back to the application review process, first you need to establish essential application information. You don't have a design specification or SDLC documentation; instead, you need to examine the code briefly to identify the key components you need to look at. The first thing you do is determine attack vectors you need to cover. To do this, you need a good idea of how the application is exposed and to whom. As mentioned earlier, you apply your knowledge of threat modeling to identify the major attack vectors. In the OpenSSH server example, the application is exposed to three main classes of users:

  • Administrator This user has permissions to start and stop the SSH server and modify the configuration file.

  • Authenticated users This class of users can log in remotely and start a shell interactively.

  • Unauthenticated users This class of users doesn't have valid credentials and shouldn't be able to do anything.

In this audit, you're largely uninterested in the administrator and authenticated user classes; you want to focus on remote unauthenticated users. You need to begin collecting SSH documentation to get an idea of how an SSH server works, the protocol constraints it has to work within and the exposure level available to each user class. In this case, the SSH RFCs are particularly useful. After a brief search on www.ietf.org, you can find the following RFCs:

  • RFC 4250 The Secure Shell (SSH) Protocol Assigned Numbers (www.ietf.org/rfc/rfc4250.txt)

  • RFC 4251 The Secure Shell (SSH) Protocol Architecture (www.ietf.org/rfc/rfc/4251.txt)

  • RFC 4252 The Secure Shell (SSH) Authentication Protocol (www.ietf.org/rfc/rfc4252.txt)

  • RFC 4253 The Secure Shell (SSH) Transport Layer Protocol (www.ietf.org/rfc/rfc4253.txt)

  • RFC 4254 The Secure Shell (SSH) Connection Protocol (www.ietf.org/rfc/rfc4254.txt)

Looks like a lot of reading! Fortunately, you can skim over a lot of the details, as long as you make sure you grasp the basic architecture of an SSH server and how SSH clients and servers communicate.

Before you go any further, you need some insight into the architecture of the OpenSSH server code. When you unpack the source, you'll notice that all the source files unpack into one directory. Because there's no neat directory structure hinting at how the application is designed, you need to start from the main() function in the SSH server and examine the code briefly. This cursory look indicates several subsystems you need to be familiar with to analyze the code in more depth:

  • Buffer subsystem Manages binary data streams for both input and output. All code for managing these buffers is in buffer.c and bufaux.c.

  • Packet subsystem Deals with transmitting and receiving packets. Most of the packet subsystem is a wrapper for buffer functions, with the exception of I/O functions. The code for dealing with packets is in packet.c.

  • Crypto subsystem Each supported cryptography algorithm is represented by a structure defining key elements of the algorithm, such as encryption/decryption routines, key sizes, and so on. This code is in cipher.c.

  • Privilege separation When you read any code and documentation about OpenSSH, you'll discover a mechanism known as "privilege separation" that attempts to minimize the chances of exploitable vulnerabilities gaining much access to the target system. It works by forking two processes to handle each connection: an unprivileged child dealing with network data and a privileged parent that can authenticate users based on requests from the child. Most of the code for privilege separation is in monitor.c and monitor_wrap.c.

You should also figure out what functionality you're going to focus the audit on, which should be clear after doing the brief code inspection. You want to focus on code that can be triggered by remote unauthenticated users, which means you probably want to cover the following code portions:

  • Low-level packet handling routines (a more in-depth vulnerability analysis of the buffer and packet reception routines)

  • Identification exchange (initial identification exchange as defined by the SSH protocolin sshd.c)

  • Session setup (proposal and key exchangespans multiple files)

  • Compression handling (SSH supports compression by default, located in compress.c)

  • Authentication (spans multiple files, all beginning with auth- or auth2-). Note that authentication data is extracted in the child and handled in the server, so you need to examine both sides.

Finally, make note of any objects that are used. Given that you're concerned only with preauthentication routines, you need to examine very few objects. The relevant ones are listed here:

  • Configuration file Obviously, remote unauthenticated users can't read or write to this file or affect it in any way. You should familiarize yourself with what options are available and what default options are set, however.

  • Local privilege separation socket The parent and child processes in a privilege separation relationship communicate via a local socket. You don't need to worry much about this object because you can't influence how it is accessed.

  • Remote client socket This object addresses how you can communicate with the server.

  • Various authentication files Various forms of authentication examine local files for authentication datahost entries, keys, and so on. Some files you examine could be system files, and others are files in a user's home directory. If you already had an account on the system and were using SSH to leverage elevated privileges, parsing and interpreting these files would be significant. However, you're not considering that case for this example.

  • External application invocation OpenSSH can be made to invoke external applications, even before authentication has been established. For example, on BSD systems, the BSD authentication mechanism can be used, which calls a user-defined login program that is responsible for deciding whether a user is authenticated. For this example, you can ignore these invocations, although a thorough audit would involve some examination of them.

Implementation Analysis

Now that you have spent time doing information gathering, it's time to move on to the code audit. To begin, you look through the exposed functionality you identified in the preassessment phase. You now have enough context to start with the lowest-level routines and work upward, so you would start with the packet and buffer-handling routines. You attempt to identify bugs that fall into your known vulnerability classes, such as integer-related vulnerabilities, memory management problems, and so forth. It's also helpful to note quirky behavior that certain parts of the application exhibit and see whether that behavior creates a vulnerability at any point. After going over the OpenSSH code, you might note some of the following behaviors:

  • The fatal() function could provide a useful application-specific candidate point (CP6). It doesn't exit the application directly; it does a series of cleanups to prevent memory leaks and so forth when it calls cleanup_exit(). Could this function be a problem if something it cleaned up were in an inconsistent state? (It has been in the past.)

  • A simple lexical candidate point search (CP3) determines that nearly every length parameter is unsigned; it's unlikely that signed integer vulnerabilities will be found.

  • Code comprehension strategies identify the consistent use of a buffer structure. Buffer overflows seem unlikely due to the consistent use of these buffer mechanisms.

  • You might want to do a candidate point search to identify double free() vulnerabilities. They seem possible, as many routines allocate a large number of data structures and have cleanup parts at the end. Maybe there's a place where one buffer is freed that's never allocated?

  • Code comprehension strategies identify that authentication success or failure is often indicated by a return value of 1 or 0. Is another value ever returned from an authentication function accidentally?

  • Code comprehension and design generalization strategies reveal that multistage authentication algorithms could have state problems. What if you repeat stages or skip stages? Is it possible? Doing so could lead to double free() vulnerabilities, memory leaks, and inconsistent variable states.

You should note several other behaviors when walking through the code. If you're unsure about some vulnerability classes mentioned in the preceding list, don't worry. They are covered in later chapters throughout the book. With your series of informal mental notes combined with formal techniques introduced throughout the book, you can analyze the code in depth for each vulnerability class, making sure to consider each code path carefully.

High-Level Attack Vectors

A higher-level analysis of the code can help you discover potential flaws in the application's logic and design. The OpenSSH specification seems to leave the possibility open for a number of higher-level logic and design vulnerabilities. You don't have a threat model; however, you can identify some basic attack vectors from the RFCs you've read and your current knowledge of the implementation.

SSH Protocol Attack Vectors

Before authentication, the identification exchange, proposal, and session setup phases take place. During this period, the SSH server and client agree on a number of supported parameters for the session and establish a secure channel. When attempting to attack this code, you would need to consider some of the following points:

  • Sniffing SSH communications are encrypted mainly to prevent third parties from snooping on a session. Therefore, you need to see whether there's any way to break that encryption. In performing an audit, often you assume the effectiveness of a publicly validated encryption protocol. However, that doesn't necessarily mean the protocol is being used safely. You might want to look at session establishment and see whether an observer can learn secret keys from watching a proposal and session setup.

  • Man in the middle Can an observer masquerade as a server and glean login credentials from clients without their knowledge?

  • Protocol quirks What interesting quirks does the protocol allow? For example, does it provide backward compatibility with previous, less secure versions of the protocol? If so, undermining security by forcing the use of old protocol features or authentication mechanisms might be possible.

  • Protocol state Examine how OpenSSH deals with the state of messages. Does the server ever attempt to handle messages sent at inappropriate stages? Also, at various points throughout SSH negotiation, it's legal to receive any of a number of different messages, which can lead to complicated and unpredictable code paths.

Login Attack Vectors

Logging in is the most crucial element of the SSH server. If any login mechanisms don't work correctly, remote attackers could gain local access to the machine the server resides on. Some things to consider when evaluating the authentication components of OpenSSH include the following:

  • Brute-forcing Can accounts be brute-forced? Are mechanisms in place to prevent remote attackers from trying millions of different passwords on a username (dictionary attacks)?

  • Multistage authentication Can any multistage authentication modules be tricked into giving access by sending out state requests? This consideration ties in with your work in assessing the protocol state attack vectors.

  • Disabled accounts Does the OpenSSH server recognize that certain system accounts are intended to be disabled? For example, can users who have the shell /bin/false log in?

  • File-based authentication A lot of authentication mechanisms require checking files on the local file system. For example, key-based authentication verifies users by checking key files in their home directories, and rhosts authentication checks a local file to see whether users can log in without a password if they're coming from a valid host. Is there any way to fool these authentication protocols into reading the wrong files, such as privileged files or authentication files for other users?

  • Incorrectly set up authentication Many authentication mechanisms (such as Kerberos) require administrators to configure the machine correctly before authentication can be established successfully. Can an enabled authentication mechanism that isn't set up correctly (or at all) yield access to the machine?

  • Incorrectly functioning authentication Most authentication mechanisms OpenSSH uses are industry-accepted and standardized mechanisms, such as BSD authentication, password authentication, Kerberos, and public key authentication. That doesn't necessarily mean the modules function correctly, however. Can the program allow an unauthorized authentication bypass? The most likely cause of this problem is incorrectly interpreting global structures that are in an inconsistent state or misinterpreting return values. This consideration ties in with your work in assessing the protocol state attack vectors.

Documentation of Findings

After the analysis is finished, you can write up your findings in the manner discussed in the "Documentation and Analysis" section of this chapter. This documentation includes locations of any vulnerabilities you identified, such as the pertinent details identified in this case study.




The Art of Software Security Assessment. Identifying and Preventing Software Vulnerabilities
The Art of Software Security Assessment: Identifying and Preventing Software Vulnerabilities
ISBN: 0321444426
EAN: 2147483647
Year: 2004
Pages: 194

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net