Cuộc chiến White Box và Black Box trong truy tìm lỗ hổng bảo mật ở thiết bị IoTs
Năm trước, Zero Day Initiative đã công bố hai lỗ hổng bảo mật nghiêm trọng vượt qua xác thực, là ZDI-20-1176 (ZDI-CAN-10754) và ZDI-20-1451 (ZDI-CAN-11355) ảnh hưởng đến nhiều sản phẩn NETGEAR. Cả hai lỗ hổng này đều nằm trong máy chủ web mini_httpd và được phát hiện bởi chuyên gia bảo mật NHH đến từ Công ty An ninh mạng Viettel và một chuyên gia ẩn danh khác. Cả hai lỗ hổng này đều có nguyên nhân gốc rễ tương tự và được định vị rất gần nhau. Tuy nhiên, hai nhà nghiên cứu đã xác định các lỗ hổng tương tự này trong hai nhóm bộ định tuyến khác nhau và có cách tiếp cận không trùng lặp trong quá trình nghiên cứu.
Do đó, bài viết sẽ so sánh, đối chiếu cách hai chuyên gia bảo mật nghiên cứu , tiếp cận cùng một vấn đề nhưng với phương thức hoàn toàn khác biệt: White box và Blackbox. Phương thức nghiên cứu cũng có thể coi là chiến thuật được các chuyên gia lựa chọn trong quá trình nghiên cứu lỗ hổng bảo mật nhắm tối ứu hóa thời gian cũng như hiệu quả đạt được.
Thông tin về các lỗ hổng bảo mật (Vulnerabilities)
Nhờ các yêu cầu của giấy phép public GNU (GPL), NETGEAR đã công khai các mã nguồn firmware của họ. Hai lỗ hổng này có thể được hiểu theo cách đơn giản nhất bằng cách phân tích mã nguồn firmware do NETGEAR cung cấp. Trong bài này, chúng tôi sẽ phân tích GPL firmware phiên bản 1.0.0.72 của bộ định tuyến (router) NETGEAR R6120.
Dựa trên mã nguồn firmware, chúng ta có thể thấy máy chủ web hoạt động trên phiên bản 1.24 của mini_http open-source project. Các lỗ hổng bảo mật chỉ nằm trong code proprietary (code custom) của NETGEAR nên không ảnh hưởng đến phiên bản máy chủ web gốc.
Hàm main () nằm trong mini_http.c. Hàm này chịu trách nhiệm thiết lập các sockets, SSL handler và listen-loop. Để xử lí đồng thời các yêu cầu HTTP, máy chủ web tự fork khi nhận được kết nối TCP để xử lí từng kết nối riêng lẻ trong một tiến trình con. Đây là hàm main () đã chỉnh sửa của mini_http từ mã nguồn firmware GPL của NETGEAR:
Hàm handle_request () bắt đầu từ dòng 1502, sau đó sẽ tiếp quản và xử lí tất cả quá trình xử lí HTTP sau khi fork.
Đầu tiên, hàm khởi tạo một số biến và tiếp tục đọc trong dòng yêu cầu của một yêu cầu HTTP từ socket tại dòng 1608 bằng cách sử dụng hàm helper get_request_line(). Sau đó, hàm handle_request () tiến hành sử dụng strpbrk() để tách phương thức yêu cầu HTTP khỏi dòng yêu cầu. Phần còn lại của dòng yêu cầu được lưu trữ trong đường dẫn có tên biến ở dòng 1611 và hàm tiếp tục xử lí đường dẫn yêu cầu và yêu cầu.
Mọi thứ trở nên thú vị và đáng chú ý bắt đầu từ dòng 2106, trong đó, đầu tiên câu lệnh if đa điều kiện sẽ kiếm tra xem đường dẫn có khớp với một trong các chuỗi trong mảng no_check_passwd_paths hay không. Điều này được thể hiện tại dòng 409 với path_exists() (được thể hiện trong sc_util.c). Câu lệnh if cũng kiểm tra xem biến đường dẫn có chứa chuỗi con “PNPX_GetShareFolderList” hay không. Nếu một trong hai điều kiện này được đáp ứng, biến need_auth được đặt thành 0. Biến need_auth thực hiện đúng chức năng như tên gọi. Khi được đặt thành 0, nó sẽ bỏ qua việc xác thực. Đoạn mã sau sẽ cho biết cách mảng chuỗi no_check_passwd_paths được xác định:
Một người đọc tinh ý và có trình độ sẽ phát hiện ra lỗ hổng bảo mật từ thời điểm này. Từ main () đến handle_request (), chương trình không tính đến việc xử lí trường hợp khi HTTP parameter nằm trong HTTP method, target hoặc HTTP version. Nếu kẻ tấn công gửi một yêu cầu HTTP với tham số yêu cầu chứa bất kì chuỗi nào trong mảng no_check_passwd_paths, kẻ tấn công có thể đáp ứng điều kiện if được xác định tại dòng 2016 và bỏ qua xác thực.
POC và quá trình khai thác lỗi
Nhà nghiên cứu ẩn danh đã cung cấp một PoC đơn giản để mô tả lỗ hổng bảo mật (ZDI-20-1176):
PoC này cho phép kẻ tấn công xem trang sau xác thực passwordrecovered.htm mà không cần phải thực hiệu quá trình xác thực POC có thể được kiểm tra đơn giản chỉ bằng điều hướng đến đường dẫn trên trong trình duyệt.
Cuối cùng, nhà nghiên cứu ẩn danh đã cung cấp thêm một PoC cho phép kẻ tấn công xem mật khẩu admin của thiết bị định tuyến và giành toàn quyền kiểm soát, điều khiển thiết bị.
Đối với ZDI-20-1451, chuyên gia NHH nhận thấy rằng chương trình chưa thực sự phân tích cú pháp phiên bản HTTP trong biến đường dẫn và họ chỉ cần nối nó vào cuối phiên bản HTTP trong một yêu cầu và đáp ứng điều kiện if được xác định tại dòng 2110 để bỏ qua xác thực thì strstr () chất phát sẽ khớp với “PNPX_GetShareFolderList”.
Sau đó, chuyên gia NHH đã xâu chuỗi lỗ hổng này bằng một lệnh injection sau xác thực ZDI-20-1423 (ZDI-CAN-11653) để giành toàn quyền kiểm soát thiết bị.
Ưu điểm và giới hạn trong phương pháp săn tìm lỗ hổng bảo mật Whitebox và Blackbox của hai chuyên gia sẽ được phân tích ở bài viết phần tiếp theo.
"Kiểm thử hộp đen (Black box testing) là một phương pháp kiểm thử phần mềm mà việc kiểm tra các chức năng của một ứng dụng không cần quan tâm vào cấu trúc nội bộ hoặc hoạt động của nó. Mục đích chính của kiểm tra hộp đen chỉ là để xem phần mềm có hoạt động như dự kiến trong tài liệu yêu cầu và liệu nó có đáp ứng được sự mong đợi của người dùng hay không."
"Kiểm thử hộp trắng hay thử nghiệm kết cấu là loại thử nghiệm được thực hiện để kiểm tra cấu trúc code. Nó còn được gọi là thử nghiệm hộp trắng hoặc thử nghiệm hộp kính. Loại thử nghiệm này đòi hỏi người test phải có kiến thức về code. Do đó, phần lớn là do các lập trình viên, nhà phát triển phần mềm thực hiện."
Nguồn: Zerodayinitiative
Black box và white box
Trong khi bài report của nhà nghiên cứu ẩn danh tiếp cận lỗi theo hướng đánh giá mã nguồn (white-box), bài report của 1sd3d lại tiếp cận theo hướng dịch ngược chương trình – reverse engineering (Black-Box), sử dụng Ghidra và trình biên dịch ngược của nó. Do vậy, ta có thể suy đoán được tại sao khi khai thác các lỗ hổng, họ thực hiện theo cách khác nhau và phát hiện các lỗ hổng trên tập các Router khác nhau.
Đoạn code lỗi ZDI-20-1451 nằm trong preprocessor #ifdef PNPX. Khi tiếp cận theo hướng white – box, sẽ tương đối khó để xác nhận rằng liệu chỉ thị PNPX đã được khai báo tại thời điểm biên dịch hay chưa, và rất có thể đoạn code lỗi sẽ không được biên dịch vào bản firmware cuối cùng. Trên thực tế, đoạn code này đúng là không được biên dịch vào firmware cho Router không dây NETGEAR R6120.
Do đó, sẽ hiệu quả hơn nếu sử dụng 1 đoạn script nhằm tìm kiếm phần code bị lỗi ZDI trong bộ source code. Dễ thấy, chuyên gia ẩn danh lựa chọn khai thác mảng no_check_paswd_path, thứ không được đóng gói trong bất kỳ chỉ thị tiêng xử lý nào.
Khi tiếp cận theo hướng dịch ngược chương trình blackbox, bạn sẽ nhìn được thứ mà CPU thấy. Tuy nhiên, với câu lệnh goto, đi cùng với định lý de Morgan và việc thiếu các tên biến sẽ thường bị thay đổi khiến cho logic của các lỗ hổng bị ẩn đi trong đoạn mã biên dịch ngược. ZDI-20-1451 là lỗi có thể được xác định rõ ràng hơn trong 2 lỗi khi ta nghiên cứu đoạn mã biên dịch ngược của researcher.
Chuỗi “PNPX_GetShareFolderList” giúp cho việc tìm kiếm một lỗ hổng đã biết trên firmware của các thiết bị khác nhau trở nên dễ dàng hơn, khi mà bạn chỉ cần dùng lệnh strings đối với file binary và tìm kiếm chuỗi đặc trưng đó là đủ. Mặt khác, viết một đoạn script để tìm kiếm lỗi ZDI-20-1176 trong một trình phân dịch chắc chắn sẽ cần nhiều thủ thuật và chuyên môn hơn.
Kết luận
Mỗi phương pháp đều có những ưu điểm và nhược điểm riêng. Trong trường hợp cụ thể này, cả hai đều hướng đến một mục đích, nhưng có cách tiếp cận khác nhau trong quá trình khai thác. Điều này chứng minh rằng không có phương pháp nào làhoàn toàn vượt trội. Tuy nhiên, hoàn toàn có khả năng rằng sẽ chỉ có một phương pháp giúp bạn đi xa hơn trong hành trình tìm kiếm những lỗ hổng tiếp theo. Và vì thế, nắm vững kỹ năng sử dụng cả hai phương pháp sẽ mang lại rất nhiều lợi ích về lâu dài.
Trong một thế giới phát triển nhanh chóng, mọi giới hạn liên tục bị phá vỡ, cùng với chu trình phát triển phần mềm gấp gáp, các nhà phát triển hệ thống NETGEAR lẽ ra cần phảilàm tốt hơn công việc đánh giá code trước khi lỗ hổng này bị phát hiện. Khai báo biến cục bộ no_need_check_password_page bên cạnh biến need_auth đã loại bỏ hoàn toàn tính bảo mật của chương trình đi. May mắn là NETGEAR đang dần dần loại bỏ những nền tảng code lỗi thời này trong các sản phẩm và firmware mới của họ.
Chú thích
Thông thường, việc suy đoán phương pháp nghiên cứu sẽ dựa vào bài report kỹ thuật của lỗ hổng. Có một lưu ý quan trọng, đó là các nhà nghiên cứu có thể sẽ không phân tách rõ ràng nghiên cứu blackbox và whitebox của họ, thay vào đó họ đưa toàn bộ nội dung và so sánh vào trong bài blog của họ. Trong trường hợp đó, ít nhất bạn sẽ học được một số kiến thức về cả 2 lỗi trên bộ định tuyến.
Nguồn: Zerodayinitiative