Trong các phiên bản PHP trước 7. 4. 31, 8. 0. 24 và 8. 1. 11, lỗ hổng cho phép những kẻ tấn công mạng và cùng trang web đặt cookie không an toàn tiêu chuẩn trong trình duyệt của nạn nhân. Cookie này được các ứng dụng PHP coi là cookie Show Người giới thiệuNếu biến liên tục được đặt thành 1, pemalloc_rel sử dụng __zend_malloc và phân bổ bộ nhớ trên heap glibc. Các lớp/hàm khác nhau để khởi tạo kết nối mysql có thể đặt cờ liên tục thành 0 hoặc 1. Ví dụ: lớp PDO luôn đặt liên tục thành 1. Theo mặc định pfc→cmd_buffer. chiều dài là 0x1000
pfc→cmd_buffer. chiều dài là chiều dài của bộ đệm được cấp phát bởi mysqlnd để lưu gói auth theo mặc định, nó là 0x1000. gói → auth_data_len là độ dài của mật khẩu được gửi bởi khách hàng. Nếu độ dài của pfc->cmd_buffer. bộ đệm không đủ để lưu trữ mật khẩu đã nhận, bộ đệm mới được cấp phát bằng mnd_emalloc. mnd_emalloc sử dụng bộ nhớ trên heap PHP Chúng tôi muốn bộ đệm được đặt trên heap PHP (không phải heap glibc). Để cấp phát bộ nhớ với mnd_malloc, hãy gửi mật khẩu có độ dài > 0x1000. Đặt con trỏ p thành bộ dịch chuyển con trỏ bộ đệm theo MYSQLND_HEADER_SIZE (4 byte) và sao chép gói → auth_data_len byte vào nó. Chúng tôi ghi đè 4 byte sau con trỏ bộ đệm Trình quản lý bộ nhớ PHPĐể tạo khai thác tràn heap, một số kiến thức về trình quản lý bộ nhớ PHP có thể giúp ích
Để biết thêm tài liệu về trình cấp phát PHP 7, hãy truy cập một số liên kết [1] [2] Sử dụng kỹ thuật tấn công fastbin cho bộ cấp phát PHP. Với lỗi này, chúng tôi có thể ghi đè tối đa 4 byte, byte thứ tư luôn là byte rỗng. next_free_block trỏ tới khối bộ nhớ trống tiếp theo trong danh sách được liên kết và có địa chỉ như. 0x00007f8b822c9640. Chúng tôi tìm cách xây dựng khai thác ổn định mà không cần bruteforce và bỏ qua ASLR. Tùy chọn ghi đè địa chỉ
Chúng tôi không thể dự đoán địa chỉ trên máy chủ nơi phân bổ trang smallbin, do đó, cách đơn giản để bỏ qua việc ngẫu nhiên hóa địa chỉ là chỉ viết lại một byte cuối cùng (với byte rỗng). Vì vậy, chúng tôi giảm tràn 4 byte thành tràn từng cái một Làm cách nào để chuẩn bị đống cho ứng dụng web PHP? Chuẩn bị đống bằng phân tích cú pháp POSTSau khi sửa lỗi, hãy tìm các dòng mã nơi bộ nhớ được phân bổ cho các vars POST. PHP thực hiện ba lần cấp phát bộ nhớ để phân tích cú pháp một POST var. Tập tin. php-7. 4. 29/main/php_variables. c dòng 320 Việc phân bổ này là tạm thời, sau khi phân tích khối bộ nhớ được giải phóng trên dòng 328 Và dòng 474 Hai phân bổ khác lấy bộ nhớ cho chuỗi biến POST Khi quá trình phân tích cú pháp POST bắt đầu, nhiều thùng nhỏ trống và việc lấy bộ nhớ từ các thùng nhỏ trống dẫn đến việc phân bổ các trang mới cho danh sách được liên kết với thùng nhỏ. Tệp php-7. 4. 29/Zend/zend_alloc. c Gửi các lọ POST để lấy bộ nhớ từ smallbin 12. Bộ nhớ có kích thước 129 đến 160 được lấy từ thùng này Tệp php-7. 4. 29/Zend/zend_alloc_sizes. h Sau khi phân bổ bộ nhớ cho các vars POST, chúng tôi muốn giải phóng nó và sử dụng thêm cho bộ đệm mật khẩu. Chúng tôi có thể giải phóng bộ nhớ khi đặt lại cùng một khóa trong dữ liệu POST với các giá trị khác. Mẹo nhỏ là ghi đè không phải tất cả các biến (miễn phí không phải tất cả các trang được lấy). Có một điều kiện trong vòng lặp "for" trong mã khai thác. Điều này được thực hiện để chuẩn bị cho các nhóm trang miễn phí liên tiếp - "khoảng trống" Trạng thái của các trang chunk trước khi phân tích cú pháp POST Trạng thái của các trang chunk sau khi phân tích cú pháp POST Trang được đánh dấu màu đỏ được dùng cho smallbin 12 Bây giờ phân bổ bộ nhớ cho mật khẩu mysql Khi tìm kiếm bộ nhớ cho các khối lớn, bộ cấp phát PHP7 sử dụng thuật toán phù hợp nhất. Trang bắt đầu được tìm kiếm để lấp đầy khoảng trống phù hợp nhất. Tệp php-7. 4. 29/Zend/zend_alloc. c Bộ cấp phát có “khoảng trống” của các trang trống với độ dài khác nhau (5,2,9,309) Gửi mật khẩu có độ dài 0x8ffd và lấy “gap” bắt đầu từ trang 192 (độ dài phù hợp nhất là 9 trang) 0x7f6eac6c0004 – con trỏ đệm Tấn công Fastbin và rò rỉ bộ nhớBây giờ chúng ta có thể ghi đè byte cuối cùng của next_free_slot bằng null. Trước khi thực thi mã, khai thác luôn làm rò rỉ bộ nhớ. Để bị rò rỉ bộ nhớ, chúng ta cần sửa đổi cấu trúc biến PHP trong bộ nhớ. Cấu trúc phù hợp nhất cho việc này là "zend_string" [3] Tệp php-7. 4. 29/Zend/zend_types. h Trong PHP7, nội dung chuỗi được thêm vào cuối cấu trúc zend_string. Ghi đè giá trị “len” và biến đầu ra bằng “echo”. Ghi đè cấu trúc có thể đạt được bằng các kỹ thuật chồng lấp heap Smallbin được chuẩn bị ở giai đoạn mà các biến POST được phân tích cú pháp. Hãy nhớ rằng khi phân tích dữ liệu POST, PHP thực hiện hai lần cấp phát bộ nhớ cho một biến. Gửi 7 biến POST từ 'hi1' đến 'hi7' để cấp phát bộ nhớ từ smallbin. Vì vậy, 7 * 2 = 14 khối được phân bổ. Sau những phân bổ này, đoạn 15 miễn phí và trở thành phần đầu của danh sách liên kết 12 của smallbin. Sau khi 'hi1' var bị ghi đè trong POST bằng "null", đoạn 1 và đoạn 2 đã được giải phóng. Đoạn 1 trỏ đến đoạn 15 (có địa chỉ 0x7f6eac6c98c0). Dump danh sách liên kết của smallbin 12 trước khi heap tràn Với tràn từng cái một, viết lại đoạn 1 next_free_slot byte cuối cùng từ c0 đến 00. Bây giờ chunk 1 điểm tới 0x7f6eac6c9800 Xem xét cách các khối miễn phí được đặt trong bộ nhớ Tiếp tục lấy bộ nhớ từ thùng nhỏ này dẫn đến cấp phát bộ nhớ tại địa chỉ 0x7f6eac6c9800 và đoạn 14 trùng nhau Tìm cách lấy một số khối từ thùng nhỏ. Đừng quên chúng tôi đã mở kết nối mysql với máy chủ mà chúng tôi hoàn toàn kiểm soát. Máy khách mysqlnd PHP có nhiều lệnh gọi emalloc trong mã phân tích câu trả lời từ máy chủ thành lệnh CHỌN. Chỉ cần đọc mô tả giao thức Mysql để viết máy chủ mysql lừa đảo [4]. Tệp php-7. 4. 29/ext/mysqlnd/mysqlnd_wireprotocol. c Sử dụng macro ZVAL_STRINGL để phân bổ các khối bộ nhớ có kích thước bất kỳ. Hãy nhớ rằng, dữ liệu chuỗi đó được thêm vào cuối cấu trúc zend_string. Khi PHP tạo chuỗi có độ dài N byte, nó cấp phát bộ nhớ cho N + 25 byte. Mã từ khai thác Python Cấp phát bộ nhớ cho cấu trúc zend_string Khối bộ nhớ chồng chéo cấu trúc zend_string bị thay đổi. Bây giờ chúng ta có thể rò rỉ con trỏ từ đống Nhận thực thi mãSử dụng tấn công fastbin để ghi bộ nhớ tùy ý. Gửi 5 lọ POST từ 'hi1' đến 'hi5' để phân bổ các khối từ 1 đến 10 trong thùng nhỏ. Chunk 11 trở thành phần đầu của danh sách liên kết smallbin. Lưu ý rằng biến 'hi5' chứa cấu trúc _zend_mm_free_slot giả Ghi đè một số lọ POST bằng 'null' để giải phóng bộ nhớ. Đoạn 1 trỏ đến đoạn 11 trong danh sách liên kết smallbin Với lỗi tràn từng cái một, ghi đè lên byte cuối cùng của đoạn 1 con trỏ next_free_slot, từ 40 đến 00 Tìm kiếm con trỏ để ghi đè để thực thi mã. Mục tiêu tốt là cơ chế đệm đầu ra PHP. Nó hoạt động mỗi khi một số dữ liệu được xuất ra trang web (ví dụ: với "echo" hoặc "var_dump") [5]. Trong bộ đệm đầu ra PHP được thực hiện bằng các mô-đun SAPI. Apache2 có mô-đun SAPI riêng [6], nằm trong tệp php-7. 4. 29/sapi/apache2handler/sapi_apache2. c Tệp php-7. 4. 29/chính/đầu ra. c Nếu bộ đệm đầu ra không bị tắt (trong trường hợp Apache2), đầu ra sẽ được xử lý bởi trình xử lý đầu ra. định nghĩa bài văn. ngoài. dữ liệu là chuỗi được truyền cho đầu ra. sapi_module. ub_write là gọi lại nằm trong mảng toàn cầu. Đó là một mục tiêu tốt để ghi đè lên địa chỉ "hệ thống". Chuẩn bị cấu trúc chunk giả với địa chỉ ghi đè Kết xuất thùng rác nhỏ sau khi ghi đè từng cái một Thực hiện một số phân bổ trong kết nối Mysql để trả về địa chỉ đích RCX trỏ đến hệ thống và RDI có chuỗi bằng lệnh bash. Chúng ta làm được rồi Một cách tiếp cận khai thác đống khácKhối bộ nhớ có kích thước lớn hơn 2Mb được đặt tên là khối lớn. PHP sử dụng lệnh gọi hệ thống mmap khi phân bổ bộ nhớ cho các khối lớn và tạo cấu trúc zend_mm_huge_list để lưu trữ thông tin về khối lớn. Kích thước của cấu trúc này là 0x18 byte và nó được đặt trong thùng nhỏ. Cấu trúc được chèn vào phần đầu của heap → danh sách liên kết đơn Huge_list. Việc hủy ánh xạ các khối lớn có siêu dữ liệu bị hỏng có thể dẫn đến chồng chéo với các khối khác. Cách tiếp cận này khó khai thác từ xa hơn, nhưng cho phép ghi đè nhiều dữ liệu hơn. Xem thêm chi tiết về phương pháp này tại đây |