Về lỗi
CVE-2022-24355 cho phép những kẻ tấn công liền kề mạng thực thi mã tùy ý trên các cài đặt bị ảnh hưởng của bộ định tuyến TP-Link TL-WR940N. Không cần xác thực để khai thác lỗ hổng này. Lỗ hổng cụ thể tồn tại trong quá trình phân tích cú pháp của phần mở rộng tên tệp. Vấn đề là do thiếu xác thực độ dài của dữ liệu do người dùng cung cấp trước khi sao chép nó vào bộ đệm dựa trên ngăn xếp có độ dài cố định. Kẻ tấn công có thể tận dụng lỗ hổng này để thực thi mã trong bối cảnh root. ( www.zerodayinitiative.com )
Sau khi đọc mô tả, mình nghĩ rằng lỗi giống như lỗi tràn bộ đệm phổ biến được kích hoạt bằng cách gửi yêu cầu cho tệp có phần mở rộng tệp rất dài (ví dụ: index.aaaa ………. aaaa). Tuy nhiên, trường hợp này lại khác.
Tạo lại lỗi
Từ hàm init có tên httpd () , để chương trình gọi hàm httpRpmFs () , url yêu cầu phải chứa “/ fs /” hoặc “/ loginFs /”.
Hơn nữa, ip giới thiệu trong yêu cầu phải bằng ip máy chủ để vượt qua kiểm tra bảo mật trong hàm httpDispatcher () .
Bây giờ, về chức năng dễ bị tấn công, httpRpmFs () được sử dụng để đọc và phản hồi nội dung của tệp được yêu cầu nếu nó tồn tại trong thư mục / tmp / hoặc / web /.
Lúc đầu, mình nghĩ rằng lỗ hổng là strcat (v2, v3) nhưng, cả v2 và v3 đều được phân bổ-ed và chỉ được sử dụng trên heap. Vì vậy, mình đã cố gắng so sánh httpRpmFs () này với httpRpmFs () đã cố định. Chúng hầu hết giống nhau, ngoại trừ có một kiểm tra bảo mật mới nếu bạn muốn đọc tệp trong thư mục / tmp /.
Từ manh mối đó, mình đã thực hiện một số yêu cầu đọc mọi tệp trong / tmp / và cuối cùng, nó đã bị lỗi khi mình cố đọc một tệp có tên là passwd . Nhìn vào trình gỡ lỗi, một phần của yêu cầu đã được viết trong ngăn xếp và gây ra tràn.
Hãy quay lại với đoạn mã và tìm hiểu xem điều này có thể xảy ra như thế nào. Tại hàm htttpRpmFs () , sau khi đọc tệp tin thành công, chương trình sẽ đưa ra phản hồi chứa nội dung của tệp tin đó.
Hàm sub_5299E0 () được gọi để phát hiện Loại-Nội dung của phản hồi phù hợp với phần mở rộng tệp. Đây là nơi bắt đầu tràn
Hàm sub_5299E0 () tìm phần mở rộng tên tệp bằng cách tạo một con trỏ trỏ đến cuối đường dẫn tệp. Sau đó, điểm sẽ được di chuyển về phía sau cho đến khi nó gặp ‘.’ tính cách. Cuối cùng, sub_5299E0 () sẽ sao chép tất cả các ký tự sau dấu ‘.’ từng ký tự một cho đến khi nó gặp byte null. Ký tự đã sao chép sẽ được đổi thành khóa trên và được lưu vào ngăn xếp. Trong trường hợp của mình, mật khẩu không có phần mở rộng tệp, con trỏ đã được di chuyển về phía sau, chuyển đường dẫn tệp, đến vùng tiêu đề yêu cầu đã lưu và chỉ dừng lại khi nó gặp phần cuối cùng ‘.’ trong địa chỉ ip của phần Người giới thiệu. Kết quả là, mọi thứ sau khi nó được sao chép để xếp chồng và ghi đè lên các giá trị thanh ghi đã lưu. Sau sub_5299E0 ()kết thúc, các giá trị này được bật trở lại thanh ghi và gây ra sự cố chương trình.
Viết một khai thác
mình không có bộ định tuyến thực, vì vậy mình sử dụng bộ công cụ-phân tích-phần sụn để mô phư phần sụn. Sau khi nghiên cứu một chút, mình thấy rằng ASLR của bộ định tuyến bị tắt theo mặc định, vì vậy mình cũng tắt ASLR trên trình mô phư của mình. Vì chương trình không có bảo vệ, mình sẽ sử dụng lỗi tràn để lưu trữ mã shellcode vào ngăn xếp và chạy nó.
Từ gỡ lỗi ở trên, mình đã tạo một tải trả tiền được lưu trữ trong phần cookie của yêu cầu. Trọng tải chứa bộ đệm 16 byte, một con trỏ ngăn xếp tới shellcode và shellcode.
Mọi thứ trông ok và mình nghĩ điều này sẽ dễ dàng, nhưng yêu cầu chỉ làm cho chương trình bị sập mà không có các trình bao hoặc kết nối trở lại nào. mình đã quay lại gỡ lỗi và phát hiện ra vấn đề là hàm toupper () . Shellcode chứa một số byte trong phạm vi từ 0x61 đến 0x7a (‘a’ thành ‘z’ trong ascii). Các byte này sẽ bị thay đổi khi đi qua hàm toupper () (trừ 0x20) khiến mã shell không hoạt động.
Vì vậy, mình đã tìm thấy một giải pháp để bỏ qua toupper () là mã hóa shellcode trước khi gửi đến bộ định tuyến. May mắn thay, lib pwntool có chức năng XORencode cho trường hợp này. Tuy nhiên, sau khi mã hóa, mã shell vẫn có một byte 0x70.
mình đã cố gắng tháo rời 0x01c07027 và thấy hướng dẫn “ nor $ t6, $ t6, $ zero ”. Để chấm dứt byte hư, mình đã thay đổi mã shell được mã hóa một chút. Vì thanh ghi $ t1 có cùng mục đích với $ t6 và nó không được sử dụng trong cả shellcode và encode, mình đã thay thế thanh ghi $ t6 bằng $ t1 và byte hư đã biến mất.
Hơn nữa, mình đã biết rằng một bộ định tuyến MIPS có đồng tiền đệm bộ nhớ cache để tăng tốc độ truy cập bộ nhớ bằng cách thực hiện đọc và ghi vào bộ nhớ chính một cách không đồng bộ. Sau khi tràn bộ đệm ngăn ghi đè lên địa chỉ trả về được lưu trữ bằng địa chỉ shellcode, bộ xử lý đã hướng việc thực thi đến đúng vị trí vì địa chỉ trả về là dữ liệu. Tuy nhiên, nó thực thi các lệnh cũ vẫn chiếm bộ nhớ cache của lệnh, chứ không phải các lệnh đã được ghi gần đây vào bộ đệm dữ liệu. Để làm cho shellcode hoạt động, mình phải xóa bộ đệm dữ liệu và lệnh bằng cách gọi hàm sleep () . mình đã mượn ROPchain từ mã khai thác cũ ( www.exploit-db.com/exploits/46678 ) và sửa đổi một chút để phù hợp với trường hợp của mình.
Yêu cầu cũng cần chỉnh sửa để phù hợp với tải trọng mới.
Cuối cùng, quá trình khai thác đã hoàn tất và sẵn sàng chạy.
Tác giả: Thanhnc41