Monday, April 14, 2014

Heartbleed: I'm thinking BIGNUM

On Friday night, I started up my 'heartleech' program slurping down data from www.cloudflarechallenge.com at 30-mbps, then went to bed. The next day, I had over 100-gigabytes of data, but I couldn't find the private key. What was the bug in my code that prevented me from finding it? I spent two days trying to solve this problem, it was very frustrating.

The answer was "byte-order". I was looking for the prime factor in the same way that it'd appear in a DER0-encoded file, which is "big-endian". Instead, the way to look for the key is in little-endian format.

I've misread the OpenSSL code before, but my feeling is that this comes from the "BIGNUM" representation in OpenSSL. RSA key and it's constituent factors are all just integers that are thousands of bits long. Because they don't fit in normal 64-bit integers, they require a special library to manipulate them. The big-endian byte arrays are extracted from the private key file, then converted into the internal representation, at which point you can call functions to add, subtract, multiply, and so on.

The internal representation for OpenSSL is as a series of integers, with low-order integers first. Since the integers on Intel x86 are also little-endian, this means that the internal representation is just byte-swapped from the external form. This would not be the case on something like Solaris SPARC, which has big-endian integers. OpenSSL still stores the array of integers least-significant first, but each integer itself will be big-endian.

My guess is that the reason we can find the prime factors is that there is some BIGNUM memory sitting around that shouldn't be.

What's really annoying is that I started down this BIGNUM path, but then some other people won the www.cloudeflarechallenge.com using Python scripts. I therefore made the assumption that Python used an external big-endian form, so I chose that instead. I then tested my code and successfully found the prime factors when reading from DER encoded private key files. So I knew my code was correct. But then my code didn't find the prime factors in the data I dumped from CloudFlare. Moreover, I couldn't test their Python scripts, because the files I created from the dumps were 13-gigs in size. Their scripts would first read in the entire file before parsing it -- and would barf at 13-gigs. I have some small 400-meg files -- but none of them contain the key. Sigh.



1 comment:

Unknown said...

hi robert
iam jov.
iam so glad to saw your weblog and tools.
today i go to install masscan on my centos server.. and get some error on make file :

make
gcc -g -ggdb -rdynamic -pg -Wall -O3 -o bin/masscan tmp/crypto-base64.o tmp/crypto-blackrock2.o tmp/event-timeout.o tmp/in-binary.o tmp/logger.o tmp/main-conf.o tmp/main-dedup.o tmp/main-initadapter.o tmp/main-listscan.o tmp/main-ptrace.o tmp/main-readrange.o tmp/main-src.o tmp/main-status.o tmp/main-throttle.o tmp/main.o tmp/masscan-app.o tmp/out-binary.o tmp/out-grepable.o tmp/out-null.o tmp/out-redis.o tmp/out-text.o tmp/out-xml.o tmp/output.o tmp/pixie-backtrace.o tmp/pixie-file.o tmp/pixie-threads.o tmp/pixie-timer.o tmp/proto-arp.o tmp/proto-banner1.o tmp/proto-banout.o tmp/proto-dns.o tmp/proto-http.o tmp/proto-icmp.o tmp/proto-netbios.o tmp/proto-ntp.o tmp/proto-preprocess.o tmp/proto-sctp.o tmp/proto-snmp.o tmp/proto-ssh.o tmp/proto-ssl-test.o tmp/proto-ssl.o tmp/proto-tcp-telnet.o tmp/proto-tcp.o tmp/proto-udp.o tmp/proto-x509.o tmp/proto-zeroaccess.o tmp/rand-blackrock.o tmp/rand-lcg.o tmp/rand-primegen.o tmp/ranges.o tmp/rawsock-arp.o tmp/rawsock-getif.o tmp/rawsock-getip.o tmp/rawsock-getmac.o tmp/rawsock-getroute.o tmp/rawsock-pcapfile.o tmp/rawsock-pfring.o tmp/rawsock.o tmp/rte-ring.o tmp/script-ntp-monlist.o tmp/script.o tmp/siphash24.o tmp/smack1.o tmp/smackqueue.o tmp/string_s.o tmp/syn-cookie.o tmp/templ-payloads.o tmp/templ-pkt.o tmp/xring.o -lpcap -lm -lrt -ldl -lpthread
tmp/pixie-threads.o: In function `pixie_cpu_get_count':
/dev/shm/masscan/src/pixie-threads.c:157: undefined reference to `CPU_COUNT'
collect2: ld returned 1 exit status
make: *** [bin/masscan] Error 1



can you help me ?
tanQ robert
best regards.
jov