KHAI THÁC LỖI OPENSSL HEARTBLEED

20:02:00

Khai thác lỗi OpenSSL Heartbleed trên Windows

Lỗi này tới thời điểm này có thể được coi là đã được hầu hết những nơi trọng yếu sửa chữa rồi. Vì vậy tôi cung cấp rộng rãi công cụ exploit lỗi nguy hiểm này trên nền Windows cho mọi người nghiên cứu
Heartbleed là gì ? Tại sao nó lại nguy hiểm như vậy ?
Những mô tả cụ thể về Bug này bạn có thể đọc ở đây : Hearbleed.com . Ở đây bài viết tóm tắt lại một số ý chính và dành nhiều hơn vào việc phân tích bug.
Heartbleed là một lỗi khá nhỏ liên quan tới logic xử lý của OpenSSL đối với cơ chế hearbeat của giao thức TLS. Bug này xuất hiện trên OpenSSL phiên bản 1.0.1 tới 1.0.1f . Điểm khá đặc biệt là những phiên bản OpenSSL này lại được thấy khá nhiều trong thời gian gần đây, một phần là do chuyên gia bảo mật thường khuyến cáo bộ phận phát triển sản phẩm triển khai TLS 1.1 và 1.2 . Thực tế quá trình phát triển của TLS 1.2 chỉ mới đạt khoảng 30% tiến độ của dự án SSL Pulse. Do đó khá nhiều site đã dính phải lỗi này. 

Vấn đề ở đây khá đơn giản : Có một lỗ hổng rất nhỏ liên quan tới việc kiểm tra ràng buộc trong đoạn code có vai trò handle thông điệp TLS heartbeat. Bằng cách lợi dụng điểm yếu này, kẻ tấn công có thể gửi request tới TLS server làm Server xử lý tràn qua vùng nhớ riêng (lên tới 64KB) mà OpenSSL dùng để lưu trữ các dữ liệu đặc biệt như private key, qua đó kẻ tấn công có thể lấy được các thông tin như :

·         Server private keys
·         TLS Session keys
·         Session ticket keys
·         Các dữ liệu nhạy cảm khác : ví dụ Password, Cookie...


64KB Dữ liệu lấy về từ server bị lỗi OpenSSL heartbleed ( công cụ coi ở phần hướng dẫn khai thác )

Bất cứ phần thông tin nào liệt kê phía trên đều cho phép kẻ tấn công giải mã dữ liệu trong phiên SSL hoặc ăn trộm các thông tin nhạy cảm. Tuy nhiên, kịch bản lấy được private key của server là kịch bản tồi tệ nhất. Khi đã có được private key, kẻ tấn công có thể thực hiện giải mã các session đã thực hiện trao đổi trước đó (nếu như sử dụng cơ chế bắt tay non-PFS ) hoặc tiến hành mạo danh server để kết nối với client. Nguy hiểm nhất là khi việc khai thác không để lại bất kỳ dấu vết gì.

Tới đây chắc chắn bạn nghĩ "Wow, lỗi nghe khá hay đấy nhưng có thực tôi cần quan tâm tới nó ko ? " . Câu trả lời là "Có" . Tin hay không thì tùy bạn nhưng thực tế là một phần đáng kể hạ tầng internet cũng như các kết nối trực tuyến hiện nay mà bạn đã và đang dùng phụ thuộc vào OpenSSL. Bao gồm cả những website chứa các thông tin cá nhân của bạn, của bạn bè bạn.. blah blah.. . Và đáng lo hơn là ngành công nghiệp giao dịch trực tuyến hiện nay càng ngày lệ thuộc vào OpenSSL.

Khắc phục bằng cách nào ?
Tuy khá khó chịu, nhưng bạn cần thiết nên thực hiện các bước sau :
1. Kiểm tra xem server của mình có bị dính lỗi đó không ? 
Bạn có thể vào một số trang kiểm tra trực tuyến như filippo.io‎ hoặc tự tay kiểm tra bằng đoạn bash sau 


echo -e "quit \n" | openssl s_client -connect yourserver:port -tlsextdebug 2>&1 | grep heartbeat

2. Nếu phát hiện ra vấn đề thì điều đầu tiên bạn cần làm là recompile lại OpenSSL với option 
-DOPENSSL_NO_HEARTBEATS . Đối với các gói cài đặt từ RedHat hay Debian thì hiện cũng đã có bản vá. Bạn cần nhanh chóng cập nhật. 

3. Hầu hết mọi người thường bỏ qua bước này. Khi mà các code exploit bug này đã phổ biến trên internet thì muốn hay không bạn cũng phải đặt giả thiết rằng server của mình có thể đã bị exploit. Vậy nên bạn cần phải revoke lại toàn bộ certificate hiện tại và generate cert mới.


Đi sâu hơn về Bug Heartbleed 

Cơ chế TLS Hearbeat được thiết kế để cho phép kết nối vẫn được lưu giữ trong trường hợp không có dữ liệu trong kênh truyền. Heartbeat messages sẽ được gửi từ một đầu kết nối (Peer_1) với dữ liệu bất kỳ và độ dài payload. Đầu kia (Peer_2) sau khi nhận được message sẽ trả lời chính xác phần dữ liệu bất kỳ mà nó nhận được từ peer_1.
RFC 6520 
When a HeartbeatRequest message is received and sending a HeartbeatResponse is not prohibited as described elsewhere in this document, the receiver MUST send a corresponding HeartbeatResponse message carrying an exact copy of the payload of the received HeartbeatRequest.
 Cấu trúc của request trên được RFC 6520 định nghĩa như sau (lưu ý phần 2 bytes chứa độ dài payload):
  struct {
      HeartbeatMessageType type;
      uint16 payload_length;
      opaque payload[HeartbeatMessage.payload_length];
      opaque padding[padding_length];
   } HeartbeatMessage;
Từ đây nó sẽ dẫn chúng ta đến mấu chốt của bug này . Nguồn gốc của nó chính là từ commitnày ở trên git.  Và chúng ta để ý ở phần của file t1_lib.c

/* Read type and payload length first */
+       hbtype = *p++;
+       n2s(p, payload);
+       pl = p;
+
+       if (s->msg_callback)
+               s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
+                       &s->s3->rrec.data[0], s->s3->rrec.length,
+                       s, s->msg_callback_arg);
+
+       if (hbtype == TLS1_HB_REQUEST)
+               {
+               unsigned char *buffer, *bp;
+               int r;
+
+               /* Allocate memory for the response, size is 1 bytes
+                * message type, plus 2 bytes payload length, plus
+                * payload, plus padding
+                */
+               buffer = OPENSSL_malloc(1 + 2 + payload + padding);
+               bp = buffer;
+              
+               /* Enter response type, length and copy payload */
+               *bp++ = TLS1_HB_RESPONSE;
+               s2n(payload, bp);
+               memcpy(bp, pl, payload);
+              
+               r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding);

Phân tích kỹ hơn. Đầu tiên :

/* Read type and payload length first */
hbtype = *p++;
n2s(p, payload);
pl = p;

Byte đầu tiên chứa Heartbeat type. Hàm 
n2s đẩy giá trị 2 byte từ sang payloadp chính là biến chứa độ dài payload. Lưu ý, biến p hoàn toàn không kiểm tra ràng buộc đầu vào.
Đọc tiếp phần sau ta thấy :

unsigned char *buffer, *bp;
int r;
/* Allocate memory for the response, size is 1 byte
 * message type, plus 2 bytes payload length, plus
 * payload, plus padding
 */
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
bp = buffer;

Chúng ta thấy rằng , ở đây chương trình cấp phát một vùng nhớ theo yêu cầu của request từ client có kích thước lên tới (1+2+16+65535) , hơn 64KB. 
Biến bp trở thành pointer để truy xuất vào vùng nhớ này.

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

Hàm s2n là hàm đảo của n2s. Nó sẽ lấy một giá trị bằng 16 bit trong payload và đẩy vào 2 bytes bp.  Như vậy là đã đẩy chính xác độ dài payload của request. 
Sau đó hàm memcpy() sẽ chép payload bytes từ pl (phần dữ liệu đầu vào request) sang bp là con trỏ tới buffer. Sau đó chính vùng nhớ đó sẽ trả ngược về chính xác cho peer client. Vậy Bug ở đâu ?

Client kiểm soát p và pl
Trong trường hợp client không gửi chính xác payload bytes thì sao ? Nếu phần pl chỉ có độ lớn là 1byte ? Dĩ nhiên, lệnh memcpy sẽ lấy lấn sang vùng nhớ kế cận trong 1 record ssl và cùng 1 tiến trình.
Rõ ràng là có nhiều thứ "kế cận" quanh đó. 
Có 2 phương án cấp phát động vùng nhớ với malloc (ít ra là ở *nix) là sử dụng sbrk(2) và mmap(2). Nếu vùng nhớ được cấp phát bởi sbrk, thì sau đó nó sẽ sử dụng quy tắc heap-grows-up và giới hạn những gì có thể đọc được, mặc dù vậy nếu một loạt request gửi lên (nhất là gửi đồng thời) thì chuyện sẽ khác.
Dĩ nhiên phần vùng nhớ cấp phát cho bp sẽ không quyết định tất cả. Mà phần cấp phát cho plmới ảnh hưởng nhiều. Gần như toàn bộ vùng nhớ sẽ được cấp phát bởi sbrk vì ngưỡng giới hạn của mmap trong malloc. Tuy nhiên một số dữ liệu khá thú vị (ví dụ như user info, session id..) sẽ được cấp từ mmap và hoàn toàn có thể truy xuất được từ pl
Tóm lại là vùng nhớ cấp phát cho pl sẽ quyết định những gì bạn có thể khai thác được :).
Cách Fix cho Heartbeat Extention
Phương án fix ở đây đơn thuần là bổ sung thêm ràng buộc cho pl


/* Read type and payload length first */
if (1 + 2 + 16 > s->s3->rrec.length)
    return 0; /* silently discard */
hbtype = *p++;
n2s(p, payload);
if (1 + 2 + payload + 16 > s->s3->rrec.length)
    return 0; /* silently discard per RFC 6520 sec. 4 */
pl = p;

//Đoạn giải thích chuyên sâu về kỹ thuật trên đây chúng tôi copy và biên tập ( chỉnh sửa những chỗ dịch sai ) từ bài dịch gốc trên http://exploitx.org/ ( không rõ lý do tại sao nhưng bài đã bị xoá )

---------------------------------------


Hướng dẫn Khai thác lỗi OpenSSL Heartbleed trên Windows & Mac:


Tải về công cụ khai thác OpenSSL Heartbleed exploit tool (Open-SSL-Heartbleed-exploit-tool.zip) tại: Đây

Trong gói này có sẵn 2 file binary, một sử dụng trên máy Mac, 1 sử dụng cho Windows. Giải nén ra là có thể dùng ngay

Cách dùng:

Dùng commandline ( cmd.exe hay terminal ), di chuyển vô thư mục mới giải nén chạy lệnh để khai thác
Mac:
OpenSSLHeartbleedExploit-mac <website_domain>:443

Windows:

OpenSSLHeartbleedExploit-win.exe <website_domain>:443

vd:
Mac:
OpenSSLHeartbleedExploit-mac www.cloudflarechallenge.com:443

Windows:

OpenSSLHeartbleedExploit-win.exe www.cloudflarechallenge.com:443

Tool sẽ khai thác lỗi và lấy về 64KB dữ liệu từ máy chủ bị lỗi OpenSSL Heartbleed. Lặp lại command này nhiều lần để liên tục lấy dữ liệu về. Dưới đây là hình minh hoạ khi tool hoạt động




xnohat - HVA


Điều khoản miễn trừ: chúng tôi không chịu trách nhiệm đối với bất kỳ hành động nào của bất kỳ ai khi sử dụng các kiến thức được cung cấp trong bài viết này cho mục đích sai trái. Nếu bạn vi phạm pháp luật, bạn sẽ phải tự chịu trách nhiệm

Chúc các bạn thành công

Share this

Related Posts

Previous
Next Post »