Php 7.4 15 khai thác github

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 __Host- hoặc __Secure-

Người giới thiệu

Nế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

  1. Ở giai đoạn của quá trình ủy quyền, máy chủ gửi gói chuyển đổi xác thực, để thực hiện xác thực với phương thức “mysql_clear_password”. Khách hàng chấp nhận nó và gửi mật khẩu văn bản rõ ràng đến máy chủ. Ở đây lỗi xảy ra. Tệp ext/mysqlnd/mysqlnd_wireprotocol. c

Php 7.4 15 khai thác github

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

    Php 7.4 15 khai thác github

    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
    Lưu ý, byte thứ tư đó luôn là byte rỗng vì máy khách gửi chuỗi mật khẩu kết thúc bằng null

    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
    Trong trình cấp phát PHP 7, so với trình cấp phát glibc, không có siêu dữ liệu size/prev_size cho các khối được giải phóng và không có hợp nhất tiến/lùi

    • Để lưu trữ khối bộ nhớ có kích thước nhỏ (dưới 3072), PHP sử dụng phương pháp tương tự như glibc fastbin. Các khối bộ nhớ trống có cùng kích thước được lưu trữ trong danh sách liên kết đơn lẻ sử dụng cấu trúc zend_mm_free_slot

    Php 7.4 15 khai thác github

    • Các khối bộ nhớ lớn hơn 3072 byte được lưu trữ trên các trang. Một trang là 4096 byte, khối bộ nhớ có thể chiếm nhiều trang, kích thước của nó được làm tròn thành bội số cho kích thước trang. Địa chỉ trang được căn chỉnh thành 0x1000. Khi lưu trữ bộ đệm trên nhiều trang, trang cuối cùng có thể có một số bộ nhớ chưa sử dụng. Ví dụ: khối bộ nhớ có kích thước 0x1f00 chiếm hai trang, trang cuối cùng có 0x100 byte chưa sử dụng. Các trang được lưu trữ trong một đoạn, một đoạn có 512 trang

    Để 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ỉ

    • Viết lại 1 byte. 0x00007f8b822c9600
    • Viết lại 2 byte. 0x00007f8b822c0041
    • Viết lại 3 byte. 0x00007f8b82004141
    • Viết lại 4 byte. 0x00007f8b00414141

    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
    Địa chỉ đoạn lớn được căn chỉnh thành 0x1000 và kích thước được làm tròn thành bội số thành 0x1000. Trang được lấy lần cuối có thể có một số bộ nhớ chưa sử dụng sau bộ đệm và tràn sẽ ghi vào bộ nhớ chưa sử dụng này, điều này không mang lại lợi ích gì cho cuộc tấn công. Để loại bỏ khoảng trống thừa sau bộ đệm, chúng tôi tạo kích thước bộ đệm nhiều lần thành 0x1000. Trong trường hợp này, viết ngoài bộ đệm ghi vào trang tiếp theo. Cách duy nhất để viết lại con trỏ next_free_block là đặt trang được phân bổ cho danh sách liên kết smallbin, chính xác ngay sau các trang được phân bổ cho mật khẩu mysql và gửi mật khẩu có độ dài gấp nhiều lần kích thước trang. Bước tiếp theo là chuẩn bị đống PHP ở trạng thái, trong đó khối bộ nhớ cho mật khẩu sẽ luôn được phân bổ ngay trước khối bộ nhớ cho smallbin

    Php 7.4 15 khai thác github

    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 POST

    Sau 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

    Php 7.4 15 khai thác github

    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
    Tập tin. php-7. 4. 29/ext/bộ lọc/bộ lọc. c Dòng 464

    Php 7.4 15 khai thác github

    Và dòng 474

    Php 7.4 15 khai thác github

    Hai phân bổ khác lấy bộ nhớ cho chuỗi biến POST
    Gửi nhiều lọ POST để phân bổ các trang. Mã từ tập lệnh Python

    Php 7.4 15 khai thác github

    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

    Php 7.4 15 khai thác github

    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

    Php 7.4 15 khai thác github

    Tệp php-7. 4. 29/Zend/zend_alloc_sizes. h

    Php 7.4 15 khai thác github

    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"

    Php 7.4 15 khai thác github

    Trạng thái của các trang chunk trước khi phân tích cú pháp POST

    Php 7.4 15 khai thác github

    Trạng thái của các trang chunk sau khi phân tích cú pháp POST

    Php 7.4 15 khai thác github

    Trang được đánh dấu màu đỏ được dùng cho smallbin 12
    Bạn có thể nhận thấy rằng bộ nhớ được phân bổ cho các biến POST, được đặt trước thùng nhỏ này, hiện đang trống. Các giai đoạn tiếp theo của tập lệnh PHP sau khi phân tích cú pháp POST là phân tích từ vựng, biên dịch opcodes Zend VM. Họ lấy một số trang miễn phí. Trong trường hợp của chúng tôi, tập lệnh có ~50 dòng mã nên không chiếm nhiều bộ nhớ để phân tích cú pháp
    Trạng thái của các trang ngay trước khi cấp phát bộ nhớ cho mật khẩu mysql

    Php 7.4 15 khai thác github

    Bây giờ phân bổ bộ nhớ cho mật khẩu mysql

    Php 7.4 15 khai thác github

    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

    Php 7.4 15 khai thác github

    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)

    Php 7.4 15 khai thác github

    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)

    Php 7.4 15 khai thác github

    0x7f6eac6c0004 – con trỏ đệm
    0x7f6eac6c9000 – trang smallbin bắt đầu

    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

    Php 7.4 15 khai thác github

    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

    Php 7.4 15 khai thác github

    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

    Php 7.4 15 khai thác github

    Xem xét cách các khối miễn phí được đặt trong bộ nhớ

    Php 7.4 15 khai thác github

    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

    Php 7.4 15 khai thác github

    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

    Php 7.4 15 khai thác github

    Cấp phát bộ nhớ cho cấu trúc zend_string

    Php 7.4 15 khai thác github

    Khối bộ nhớ chồng chéo

    Php 7.4 15 khai thác github

    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ả

    Php 7.4 15 khai thác github

    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

    Php 7.4 15 khai thác github

    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
    Bây giờ chunk 1 next_free_slot trỏ đến cấu trúc _zend_mm_free_slot giả bên trong chunk 10

    Php 7.4 15 khai thác github

    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

    Php 7.4 15 khai thác github

    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

    Php 7.4 15 khai thác github

    Thực hiện một số phân bổ trong kết nối Mysql để trả về địa chỉ đích
    Đặt điểm ngắt trên hàm php_output_op và xem quá trình thực thi diễn ra như thế nào

    Php 7.4 15 khai thác github

    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ác

    Php 7.4 15 khai thác github

    Php 7.4 15 khai thác github

    Khố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