2013-03-14 78 views
29

Có cách nào để đảm bảo tệp đã nhận là hình ảnh trong PHP không?PHP kiểm tra xem tệp có phải là hình ảnh

Kiểm tra tiện ích mở rộng không an toàn với tôi khi bạn có thể tải lên script và thay đổi tiện ích mở rộng của tiện ích đó thành bất kỳ thứ gì bạn muốn.

Tôi cũng đã cố sử dụng getimagesize nhưng có thể có điều gì đó phù hợp hơn cho vấn đề cụ thể đó.

+0

có thể trùng lặp với [kiểm tra loại tệp được tải lên bằng PHP] (http://stackoverflow.com/questions/6755192/uploaded-file-type-check-by-php) và [Chuỗi bảo mật có nội dung tải lên] (http://stackoverflow.com/questions/11061355/security-threats-with-uploads) – deceze

+0

http://stackoverflow.com/questions/173868/how-to-extract-a-file-extension-in-php –

+2

@Pramod Vừa kiểm tra phần mở rộng tệp chính xác * không * đủ. – deceze

Trả lời

15

cách Native để có được những Mimetype:

Đối với PHP < 5.3 sử dụng mime_content_type()
Đối với PHP> 5.3 sử dụng finfo_fopen()

Alternatives để có được Mimetype là exif_imagetypegetimagesize, nhưng những dựa vào có phù hợp libs được cài đặt. Ngoài ra, họ có thể sẽ chỉ trả về hình ảnh mimetypes, thay vì toàn bộ danh sách được đưa ra trong magic.mime.

Trong khi mime_content_type bị xóa khỏi PHP5.3, nó hoạt động tốt hơn bên dưới phiên bản đó. E_STRICT thậm chí sẽ không đưa ra thông báo về việc bị từ chối. Nếu bạn không muốn bận tâm về những gì có sẵn trên hệ thống của mình, chỉ cần bọc tất cả bốn hàm vào một phương thức proxy ủy quyền cuộc gọi hàm tới bất kỳ chức năng nào có sẵn, ví dụ:

function getMimeType($filename) 
{ 
    $mimetype = false; 
    if(function_exists('finfo_fopen')) { 
     // open with FileInfo 
    } elseif(function_exists('getimagesize')) { 
     // open with GD 
    } elseif(function_exists('exif_imagetype')) { 
     // open with EXIF 
    } elseif(function_exists('mime_content_type')) { 
     $mimetype = mime_content_type($filename); 
    } 
    return $mimetype; 
} 
+0

Thật không may, điều này dường như đã không được chấp nhận. – sf89

+0

Tôi vừa cập nhật câu trả lời của mình. Bạn có thể thử điều này –

+0

Sử dụng exif_imagetype có vẻ như những gì tôi đang tìm kiếm. Cảm ơn! – sf89

55

Các getimagesize() nên là cách rõ ràng nhất của việc hiểu xem các tập tin là một hình ảnh:

if(@is_array(getimagesize($mediapath))){ 
    $image = true; 
} else { 
    $image = false; 
} 

bởi vì đây là một mẫu getimagesize() đầu ra:

Array (
[0] => 800 
[1] => 450 
[2] => 2 
[3] => width="800" height="450" 
[bits] => 8 
[channels] => 3 
[mime] => image/jpeg) 
+0

Vâng đây là cảm giác ruột của tôi nhưng tôi đang tìm kiếm một cái gì đó mà sẽ được chính xác phù hợp để có được loại tập tin như bạn có thể lừa phương pháp này. Tôi đã thấy điều này được thực hiện với Gifs (xem tại đây http://ha.ckers.org/blog/20070604/passing-malicious-php-through-getimagesize/). – sf89

+13

Vì 'getimagesize' trả về false khi thất bại, điều này có thể được so sánh với' $ image = getimagesize ($ mediapath)? true: false; ' – neokio

+1

' if ($ array = getimagesize ($ mediapath)) {// true và sử dụng mảng $ nếu được yêu cầu} ' –

10

Sử dụng tiện ích mở rộng tệp và getimagesize chức năng để phát hiện xem tệp đã tải lên có r Định dạng ight chỉ là kiểm tra mức nhập cảnh và nó có thể đơn giản bỏ qua bằng cách tải lên tệp có phần mở rộng thực và một số byte của tiêu đề hình ảnh nhưng nội dung sai.

để bảo mật và an toàn, bạn có thể tạo hình thu nhỏ/thay đổi kích thước (ngay cả với kích thước hình ảnh gốc) hình ảnh đã tải lên và lưu phiên bản này thay vì phiên bản đã tải lên. Cũng có thể tải nội dung tệp đã tải lên và tìm kiếm nó cho các ký tự đặc biệt như <?php để tìm tệp có hình ảnh hay không.

+0

Đó không phải là một chút nặng? Tôi sẽ xem xét nó mặc dù. – sf89

Các vấn đề liên quan