File Uploader
Niezabezpieczony file uploader
File uploader jest krytycznym punktem aplikacji, a jego nieodpowiednie zabezpieczonie może doprowadzić do poważnych konsekwencji, jak przeciążenie systemu plików, a nawet przejęcie systemu.
W niezabezpieczonej wersji właściwości plików, takie jak typ lub rozmiar, nie są rzetelnie sprawdzane. Przykład niewystarczającego zabezpieczenia stanowi poniższy kod.
< input type="file" name="fileToUpload" id = "fileToUpload" accept="image/*" >
Podjęto próbę ograniczenia typu przesyłanych plików, za pomocą atrybutu "accept". Aby obejść to zabezpieczenie wystarczy skorzystać z narzędzia DevTools i usunąć ten fragment kodu HTML, a następnie przesłać plik niebędący obrazem. Co więcej, nie został ograniczony maksymalny rozmiar pliku, zatem atakujący móglby spróbować obciążyć serwer wieloma plikami o dużym rozmiarze.
Przykład file uploadera, którego jedne zabezpieczenie stanowi atrybut HTML znajduje się poniżej.
Zabezpieczony file uploader
Aby uniknąć ingerencji użytkownika w zabezpieczenia systemu, nie należy umieszczać ich w sekcji dostępnej dla użytkownika za pomocą narzędzi deweloperskich. Poniżej przedstawione zabezpieczenia wykonywane są po stronie serwera.
Pierwszym krokiem jest sprawdzenie typu przesyłanego pliku. W przykładowym kodzie poniżej celem jest upewnienie się, że plik jest obrazem.
$correct = 0;
@$check_error = getimagesize($_FILES["fileToUpload"]["tmp_name"]);
// Checking if an actual image
if( $check_error!== false) {
// Image
$correct = 1;
} else {
// Not an image
$correct = 0;
}
// Check the extension
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
$uploaded_type = $_FILES[ 'fileToUpload' ][ 'type' ];
if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
&& $imageFileType != "gif" && ( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' )) {
//Wrong extension
$correct = 0;
}
Funkcja getimagesize() sprawdza typ MIME przesyłanego pliku i zwraca wartość false, jeśli nie jest on typem obrazu. Funkcja pathinfo() umożliwia uzyskanie informacji o ścieżce pliku, a następnie wyłuskanie informacji o rozszerzeniu w celu porównania z dozwolonymi rozszerzeniami obrazów.
W celu pozbycia się metadanych, wówczas można na nowo zakodować obraz za pomocą funkcji imagecreateformjpg() lub imagecreatefrompng().
if( $uploaded_type == 'image/jpeg' ) {
$img = imagecreatefromjpeg( $uploaded_tmp );
imagejpeg( $img, $temp_file, 100);
}
else {
$img = imagecreatefrompng( $uploaded_tmp );
imagepng( $img, $temp_file, 9);
}
imagedestroy( $img );
Kolejnym krokiem jest sprawdzenie, czy rozmiar pliku mieści się w określonych granicach.
// Check the size
if ($_FILES["fileToUpload"]["size"] > 100000) {
//Too large
$correct = 0;
}
Zaprezentowana poniżej poprawiona wersja file uploadera spełnia wszystkie opisane powyżej wymagania, co czyni ją znacznie bezpieczniejszym rozwiązaniem.