Lỗ hổng CVE trong các hàm xử lý ảnh của PHP đang cho thấy rủi ro bảo mật đáng kể với các hệ thống đọc và phân tích JPEG phía máy chủ. Hai lỗi bộ nhớ trong getimagesize và iptcembed có thể dẫn đến rò rỉ dữ liệu nhạy cảm từ heap hoặc gây denial-of-service khi xử lý tệp JPEG được tạo đặc biệt.
CVE-2025-14177 Trong Hàm Getimagesize
CVE-2025-14177 được theo dõi với CVSS 6.3 và ảnh hưởng đến chức năng getimagesize khi xử lý các segment JPEG APP trong chế độ đọc nhiều chunk. Đây là một lỗ hổng CVE có thể làm lộ thông tin khi PHP đọc metadata từ ảnh do kẻ tấn công kiểm soát.
Tham chiếu chi tiết tại NVD.
Phiên Bản Bị Ảnh Hưởng
- PHP 8.1.* trước 8.1.34
- PHP 8.2.* trước 8.2.30
- PHP 8.3.* trước 8.3.29
- PHP 8.4.* trước 8.4.16
- PHP 8.5.* trước 8.5.1
Nguyên nhân nằm ở hàm php_read_stream_all_chunks, nơi dữ liệu được ghép nối không đúng khi đọc segment ứng dụng JPEG. Khi xử lý các segment chứa EXIF hoặc IPTC, bộ nhớ heap chưa khởi tạo có thể bị sao chép ra ngoài.
Lỗi xảy ra vì con trỏ buffer không được tăng sau mỗi lần đọc. Kết quả là chunk tiếp theo ghi đè lên đầu buffer, trong khi phần đuôi vẫn giữ giá trị chưa khởi tạo và có thể rò rỉ sang dữ liệu trả về.
Cách Khai Thác
Kẻ tấn công có thể tạo tệp JPEG với segment APP1 lớn, được thiết kế để buộc quá trình đọc đi qua nhiều chunk với kích thước mặc định 8.192 byte. Khi ứng dụng gọi getimagesize qua php://filter hoặc cơ chế đọc nhiều chunk tương tự, dữ liệu heap chưa khởi tạo có thể được đưa vào mảng $info[‘APPn’].
Bề mặt tấn công đặc biệt đáng chú ý ở các điểm upload công khai, hệ thống quản lý nội dung tạo thumbnail, dịch vụ webmail và image CDN thực hiện phân tích ảnh phía server. Với điều kiện kiểm soát dữ liệu đầu vào, kẻ tấn công từ xa có thể kích hoạt remote code execution theo chuỗi phụ thuộc, hoặc ít nhất là làm lộ thông tin từ bộ nhớ tiến trình.
Lỗ Hổng CVE Trong Iptcembed
Hàm iptcembed cũng chứa một lỗ hổng CVE nghiêm trọng khác liên quan đến heap buffer overflow. Cơ chế lỗi xuất phát từ việc cấp phát buffer đầu ra dựa trên một kết quả fstat duy nhất, nhưng vẫn tiếp tục đọc dữ liệu cho đến khi gặp EOF mà không kiểm tra dung lượng còn trống.
Trường hợp nguy hiểm nhất xuất hiện với các kiểu file không chuẩn như FIFO, pipe và socket. Với những kiểu này, trường st_size trả về giá trị 0, khiến buffer được cấp phát quá nhỏ so với luồng dữ liệu thực tế.
Điểm Yếu Kỹ Thuật
Trong quá trình xử lý, dữ liệu đầu vào được chép vào spoolbuf mà không xác thực giới hạn vùng nhớ. Khi luồng chứa nhiều dữ liệu hơn mức đã cấp phát, thao tác ghi vượt biên sẽ xảy ra, dẫn tới out-of-bounds write và phá hủy heap.
Lỗ hổng còn tạo ra điều kiện TOCTOU khi với file thông thường, kích thước có thể thay đổi giữa thời điểm gọi fstat và lúc hoàn tất đọc. Đây là một rủi ro bảo mật đáng chú ý vì parser có thể chuyển sang chế độ “đọc đến EOF” mà không có giới hạn tương ứng.
Kịch Bản Khai Thác
Kẻ tấn công có thể đưa dữ liệu lớn vào cấu trúc JPEG được thiết kế đặc biệt để kích hoạt chế độ đọc toàn bộ luồng. Khi parser xử lý các marker như M_APP13 hoặc M_SOS, nó chuyển sang php_iptc_read_remaining và sao chép liên tục cho đến EOF.
Hàm php_iptc_get1 tăng con trỏ ghi poi cho mỗi byte nhưng không kiểm tra biên của spoolbuf_end. Đây là điều kiện trực tiếp dẫn đến heap corruption.
Cơ Chế Ảnh Hưởng Trong PHP
Cả hai lỗi đều khai thác điểm yếu trong quản lý bộ nhớ của Zend Engine khi xử lý marker JPEG. Với CVE-2025-14177, đường đi lỗi bắt đầu từ việc cấp phát bằng emalloc trả về vùng nhớ chưa khởi tạo, sau đó php_stream_read ghi vào cùng địa chỉ đích mà không cộng offset theo số byte đã đọc.
Với iptcembed, lỗi phát sinh khi parser làm việc với dữ liệu IPTC nhúng trong JPEG và không kiểm soát độ dài buffer đích trong quá trình sao chép từng byte.
Minh Họa Hành Vi Lỗi
// Mô tả logic lỗi ở mức khái niệm
buffer = emalloc(size);
while (read_now > 0) {
php_stream_read(stream, buffer, read_now);
// Thiếu: buffer += read_now;
}
// Mô tả lỗi ghi tràn trong luồng IPTC
while (data_remaining) {
*poi++ = byte;
// Thiếu kiểm tra: poi < spoolbuf_end
}
Chuỗi Khai Thác Và IOC
Các bằng chứng khai thác được mô tả bằng JPEG tối thiểu chứa segment APP1 lớn, kết hợp heap spraying bằng chuỗi marker để cố định nội dung trong bộ nhớ. Khi tệp được đọc qua php://filter, quá trình xử lý nhiều chunk có thể làm lộ chuỗi kiểm thử như LEAK-MARKER-123!.
- IOC: Tệp JPEG chứa APP1 lớn bất thường.
- IOC: Chuỗi marker thử nghiệm LEAK-MARKER-123! xuất hiện trong dữ liệu rò rỉ.
- IOC: Đường dẫn xử lý qua php://filter hoặc luồng đọc nhiều chunk.
- IOC: Môi trường có FIFO, pipe hoặc socket khi dùng iptcembed.
Trong bài kiểm tra iptcembed, kịch bản sử dụng hai terminal với named pipe cho thấy buffer được cấp phát từ giá trị st_size = 0, sau đó dữ liệu đầu vào vượt quá kích thước thực tế và bị AddressSanitizer phát hiện là heap buffer overflow.
Bản Vá Bảo Mật Và Phiên Bản Đã Sửa
Nhóm phát triển PHP đã sửa CVE-2025-14177 bằng cách cập nhật php_read_stream_all_chunks để tăng con trỏ buffer sau mỗi lần đọc, đảm bảo dữ liệu được nối tuần tự. Một bài kiểm tra hồi quy ext/standard/tests/image/gh20584.phpt cũng được thêm vào để ngăn lỗi tái phát.
Với iptcembed, mã nguồn được bổ sung tham số spoolbuf_end cho các hàm php_iptc_get1 và php_iptc_put1, nhằm ép kiểm tra biên trước khi ghi. Khi buffer đầy, hàm trả về EOF thay vì ghi ra ngoài vùng nhớ.
Phiên Bản Cần Cập Nhật
- 8.1.34 trở lên
- 8.2.30 trở lên
- 8.3.29 trở lên
- 8.4.16 trở lên
- 8.5.1 trở lên
Tổ chức cần kiểm kê toàn bộ host và container đang chạy PHP, ưu tiên các điểm upload công khai, CMS thumbnailer, webmail và image CDN. Việc cập nhật bản vá nên được thực hiện ngay trên các phiên bản đã được sửa lỗi để giảm nguy cơ bảo mật từ các tệp JPEG được tạo độc hại.










