Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Secure programming with the OpenSSL API, Part 2: Secure handshake

Avoid a man in the middle (MITM) attack

Kenneth Ballard, Software Engineer, MediNotes Corp.
Kenneth is a Software Engineer working for the MediNotes Corp. in West Des Moines, Iowa. He graduated from Peru State College in Peru, Nebraska, with a Bachelor of Science in Business Administration. He also has an Associate of Science in Computer Programming from Southwestern Community College in Creston, Iowa. Kenneth has written several applications and programming libraries.

Summary:  Securing the handshake during a Secure Sockets Layer session (SSL) is vital, since almost all of the security involving the connection is set up inside the handshake. Learn how to secure the SSL handshake against a man in the middle (MITM) attack -- in which the intruding party masquerades as another, trusted source. This article also introduces the concept of digital certificates and how the OpenSSL API handles them.

View more content in this series

Date:  03 May 2005
Level:  Intermediate PDF:  A4 and Letter (198 KB | 10 pages)Get Adobe® Reader®
Also available in:   Korean  Japanese

Activity:  6592 views
Comments:  

Not too long ago, a secure handshake was the sign that business between two parties was going to be on sound footing. After all, the handshake was the face-to-face opportunity to size up a potential partner. A secure and confident handshake meant that both parties to the transaction are confident that they are doing something that will benefit all. An insecure handshake was a sign that one side is apprehensive about the transaction.

The handshake works the same way in online transactions.

An earlier article on developerWorks, "Secure programming with the OpenSSL API, Part 1: Overview of the API," showed you how to create a basic, simple secure connection using OpenSSL. However, it demonstrated only the basics involving default settings; it did not show how to customize anything. Still, I recommend reading it to fully appreciate this article, because the earlier article introduced the concept of digital certificates and showed how to determine if OpenSSL's internal verification of a certificate has passed or failed.

This article goes deeper into OpenSSL, showing you how to secure the handshake against what is called a man in the middle (MITM) attack.

About digital certificates

Later in this article I'll cover retrieving and verifying digital certificates, so I'll quickly discuss what a digital certificate is and how it works. If you're familiar with data cryptography and SSL, you can skip this section. To learn more about cryptography and SSL issues, browse the articles and tutorials listed in the Resources section later in this article.

In its simplest form, a digital certificate is an asymmetric cryptography key. Current standards regarding digital certificates have identifying information included along with the key. A typical digital certificate contains the owner's name (which is the full domain name if the certificate is used on a Web server) and contact information. There is a valid date range as well and a security signature to verify that the certificate has not been tampered with.

Digital certificates can be easily created with the command-line OpenSSL tool or with any other tool made for that purpose. But a digital certificate created by just anyone is going to have a problem on the basis of trust. A digital certificate is more than just a cryptography key; it is an online credential. A certificate verifies your identity to whoever is attempting to communicate with you. To show trust, a digital certificate is signed by a Certificate Authority (CA).

Certificate authorities act as a trusted third party in the world of digital security. Because verifying identity in the online world is difficult, certificate authorities take over that challenge. They verify the identity of anyone purchasing a certificate or paying to have their certificate signed. Thus to trust the certificate, the user only needs to trust the certificate authority. The user signifies trust in the certificate authority by possessing and using the CA's trust certificate. Verisign and Thawte are two well-known certificate authorities.

If a certificate's security is ever compromised, it is revoked -- that is, declared void and invalid. When a certificate is declared invalid, it is impractical for a CA to notify every person who may have a copy of that certificate. Instead, CAs issue a Certificate Revocation List (CRL). Browsers and other security applications using digital certificates can verify that the certificate has not been revoked by either the owner or the CA.

Certificate revocation can also be checked using the OCSP protocol. OCSP stands for Online Certificate Status Protocol and is defined in RFC 2560. OpenSSL has both OCSP and CRL functionality, but that functionality is beyond the scope of this article. The current standard for digital certificates is X.509, as defined in RFC 3280.


A handshake to start business

Since this article focuses on handling the server's digital certificate during the handshake, let's go into depth as to how the handshake works. If you're familiar with the SSL procedure, feel free to skip this section.

The opening handshake on a connection starts with the client basically saying "Hello" to the server. The hello message -- which is what it's called in the specification -- contains the client's security parameters:

  • SSL version number
  • Randomly generated data
  • Cipher settings
  • Anything else needed for communication

The server responds back with its own hello message containing the server's security parameters, the same type of information as the client provided. It's at this time that the server also sends its digital certificate. If client authentication is to be employed for the connection, the server also sends a request for the client's certificate.

Once the server's hello message is received, the digital certificate is verified. This involves checking the various parameters of the certificate to make sure the certificate is intact along with checking that the certificate is being used within its validity period.

One other step that should also be performed here is checking the name on the certificate against the host name used to connect to it. This is not part of the SSL standard, but is highly recommended to prevent a man in the middle attack (MITM). This step verifies that the certificate is coming from the entity you think it is coming from. If the two don't match at this point, the certificate is only suspect, not invalid.

The random data that was shared between the client and server is used to create a premaster secret, a shared secret value known only to the server and client and used only for that session. This secret value is encrypted to the server's digital certificate and sent to the server for verification that everything is as it should be.

If the server requested client authentication, the client creates a one-way hash of the data randomly generated during the handshake and known only to the server and client. The client signs the hash using the client's private key and sends the signed data and the digital certificate to the server. The server uses that information to authenticate the client.

If authentication succeeds, both the server and client run the shared random data through an algorithm to create the master secret. From the master secret, the client and server create the session keys, symmetric keys within the bounds of the chosen symmetric cipher used to encrypt the session's data.

The client terminates the handshake by sending a message to the server that it has finished, an encrypted set of one-way hash values to be verified by the server. The server sends a similar message to the client. Both the client and server verify the data is correct before terminating the handshake and beginning communication.


Man in the middle

It's a game played by children, but it's also a serious attack that can occur on public key infrastructures (PKI). When talking about digital certificates, it is an attack that must be considered because regardless of the security parameters behind the SSL connection, a man in the middle attack can render those precautions worthless.

Let's say that Casey and Samantha want to communicate using SSL. A third party, Isabel, intercepts the connection attempt, acting as a proxy between them. When she notices that an SSL connection is being set up, she masquerades as Casey to Samantha and Samantha to Casey. Sitting in the middle, she can intercept both sides of the conversation. If the conversation includes account numbers and personal information, she can use that to commit identity theft.

This is where the chain of trust and the common name on a certificate can prevent this from occurring. During the handshake, certificates are exchanged. When the certificates are analyzed for validity, trust signatures are checked as well. If the common name on the server certificate is verified along with the rest of the certificate, the attack is defeated, right? Not entirely.

Let's assume that Isabel has a certificate with Samantha's name on it. It is also signed by a CA within Casey's trust model. Here the MITM attack is not defeated by checking the common name. The certificate and its trust are valid and the name checks out. We now have a big problem.

However, this problem is placed aside when looking at the certificate authorities. Most certificate authorities attempt to verify a person's identity to the best of their ability before issuing a digital certificate with that person's name on it. Because of this, it is highly unlikely that Isabel will be able to get a digital certificate with Samantha's name on it from a well-known and highly reputable certificate authority.

Working with a CA can make it easier to defeat this security measure -- for instance, if the CA and Isabel work for the same company (in other words, an "inside job"). Then it becomes possible for the signing key to be stolen by someone within the CA's work sphere who could then create arbitrary certificates with almost anyone's name. While the private portion of the certificate is used to create the signature, the password could also be stolen using social engineering or other similar techniques.

The MITM attack becomes especially important when talking about proxy servers. Because the secure connection must "tunnel" through the proxy server to the intended destination, malicious proxy servers can very easily eavesdrop on any conversation. A malicious proxy can make it appear that the connection is tunneled when it actually is not. This is an important thing to keep in mind when using the "anonymous proxy" services available across the Internet: How well can you trust them since you're sending usernames and passwords through their systems?

Realize, though, that this attack is not reserved strictly for the realm of computer and digital security. A woman used a technique similar to the MITM attack to rob families out of a lot of money (see Resources).


OpenSSL and digital certificates

OpenSSL has an entire internal library devoted to digital certificates. The source code for it, assuming you have OpenSSL's source code available, is under the crypto/x509 and crypto/x509v3 directories. The source code defines several structures for handling digital certificates. These are listed in Table 1.

Table 1. OpenSSL structures pertaining to X.509 certificates

StructureFunction
X509Contains all data pertaining to the digital certificate.
X509_ALGORProvides which algorithm the certificate is designed for.
X509_VALTime span for which the certificate is valid.
X509_PUBKEYPublic key algorithm of the certificate, typically RSA or DSA.
X509_SIGThe certificate's hash signature.
X509_NAME_ENTRYEntries for the various fields of data the certificate contains.
X509_NAMEContains the stack of name entries.

These are only a few of the structures involved. Most of the X.509 structures used inside of OpenSSL you will most likely never use in an application. Of the structures listed above, the only two used in this article are X509 and X509_NAME.

On top of the structures are various functions used to handle and process digital certificates. The functions are named from the structures to which they apply. For example a function whose name begins with X509_NAME will typically apply to an X509_NAME structure. These functions will be introduced as necessary.


Providing your own trust certificates

Before the certificate can be verified for trust, a default trust certificate set must be provided to the SSL_CTX object created while setting up OpenSSL for a secure connection. This can be provided in several ways, but the easiest way to do so is to store the certificates as a PEM file and load them into OpenSSL as shown using SSL_CTX_load_verify_locations(ctx, file, path);. file is the path to a file containing one or more certificates in PEM format. path is a directory path to one or more files in PEM format, but the filenames have to be in a certain format. It is easier having the trust certificates in a single PEM file, keeping the path argument as NULL, like this: SSL_CTX_load_verify_locations(ctx, "/path/to/trusted.pem", NULL);.

Even though it is easier to add and update trust certificates when they are individual files in a folder, it is unlikely you will be updating the trust certificates so frequently as to warrant that.


Verifying the certificate

Before communication continues on the connection or the certificate is retrieved, determine the results of OpenSSL's internal verification of the certificate using SSL_get_verify_result(). If SSL_get_verify_result() returns a code other than X509_V_OK, does this mean that the certificate is invalid? That depends on the return code.

Typically if the return code is not X509_V_OK, there is a problem with the certificate or the security surrounding the certificate. One thing to bear in mind: There are a few security checks that OpenSSL does not perform when verifying the certificate, including revocation checking and validating the common name in the certificate.

The return codes for SSL_get_verify_result() are documented in the OpenSSL documentation under verify, which is listed under apps. Some codes are listed as unused, meaning they are never returned. Some of the codes are fatal, while others are not. For example, if the trust cannot be verified because a trust certificate store has not been loaded, then whether to continue with the communication is strictly up to the developer.

No matter the result of the verification, continuing under potentially unsafe security parameters is entirely up to the developer. Error return codes are given because the certificate is potentially unsafe.


Retrieving the peer certificate

Retrieving the peer certificate is necessary if you wish to either display it to the user or verify it either against the host name or the certificate authority. To retrieve the certificate after verifying the test result, call SSL_get_peer_certificate(). It returns an X509 pointer to the certificate or NULL if no certificate was presented (see Listing 1).


Listing 1. Retrieving the peer certificate
X509 * peerCertificate;


if(SSL_get_verify_result(ssl) == X509_V_OK)
    peerCertificate = SSL_get_peer_certificate(ssl);
else
{
    /* Handle verification error here */
}


Validating the peer certificate

The server's certificate provided in the handshake should have a name on it that matches the server's host name. If it does not, the certificate should be flagged as suspect. The internal verification procedure already checks the certificate for trust and expiration; the certificate is marked as invalid if the certificate has expired or contains a signature that is not trusted. Because it is not part of the SSL standard, OpenSSL does not check the certificate's name against the host name.

The certificate's "name" is actually the Common Name field on the certificate. This field should be retrieved from the certificate and verified against the host name. If the two don't match, the certificate is only suspect, not invalid. Some companies -- Yahoo! for example -- use the same certificate throughout the various hosts owned even though the Common Name on the certificate is for only one host. More in-depth checks can be employed to ensure that the certificate is coming from the same company, but that is entirely up to the security needs of the project.

Retrieving the common name from the certificate requires two steps:

  • Retrieving the X509_NAME object from the certificate structure,
  • Then retrieving the name from the X509_NAME object.

Use X509_get_subject_name() to retrieve the X509_NAME structure from the certificate. This returns a pointer to an X509_NAME object. From this use X509_NAME_get_text_by_NID() to retrieve the common name to a string (as in Listing 2).


Listing 2. Retrieving and verifying the Common Name
char commonName [512];
X509_NAME * name = X509_get_subject_name(peerCertificate);
X509_NAME_get_text_by_NID(name, NID_commonName, commonName, 512);

/* More in-depth checks of the common name can be used if necessary */

if(stricmp(commonName, hostname) != 0)
{
    /* Handle a suspect certificate here */
}

Using the standard C string functions or your favorite string library, compare the common name and the host name. How a mismatch is handled is solely up to the requirements of the project or the decision of the user. If more in-depth checks are to be used, I recommend using a separate string library to remove some of the complexity.


The trust is earned

In this article, I've demonstrated how to secure the SSL handshake against a man in the middle attack in which the intruding party masquerades as another, trusted source. I've also introduced the concept of digital certificates and how the OpenSSL API handles them.

Remember, securing the handshake during a SSL session is vital since almost all of the security involving the connection is set up inside the handshake. How critical is to follow each step outlined in this article will depend on the security requirements of the project and be based on the decision of the developer.


Resources

About the author

Kenneth is a Software Engineer working for the MediNotes Corp. in West Des Moines, Iowa. He graduated from Peru State College in Peru, Nebraska, with a Bachelor of Science in Business Administration. He also has an Associate of Science in Computer Programming from Southwestern Community College in Creston, Iowa. Kenneth has written several applications and programming libraries.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Linux, Open source
ArticleID=86620
ArticleTitle=Secure programming with the OpenSSL API, Part 2: Secure handshake
publish-date=05032005