สคริปต์อัปโหลดที่ปลอดภัย

Aug 17 2020

ฉันกำลังสร้างเครือข่ายโซเชียลที่ให้ผู้ใช้อัปโหลดรูปโปรไฟล์ ฉันแค่อยากรู้ว่านี่เป็นวิธีที่ปลอดภัยไหม ขอบคุณ.

<?php

include 'includes/header.php';
include 'includes/form_handlers/settings_handler.php';

//$userPic = ''; $date_time = date('Y-m-d_H-i-s');

if(!empty($userLoggedIn)) { if (isset($_FILES['fileToUpload'])) {
        $errors= array(); $file_name = $_FILES['fileToUpload']['name']; $file_size = $_FILES['fileToUpload']['size']; $width = 1500;
        $height = 1500; $file_tmp = $_FILES['fileToUpload']['tmp_name']; $file_type = $_FILES['fileToUpload']['type']; $tmp = explode('.',$_FILES['fileToUpload']['name']); $file_ext=strtolower (end ($tmp)); $extensions = array( "jpeg", "jpg", "png", "gif");

        if(in_array($file_ext,$extensions)=== false){

            $errors[]="extension not allowed, please choose a JPEG or PNG file."; } if ($file_size > 8097152) {

            $errors[] = 'File size must be 2 MB'; } if ($width > 1500 || $height > 1500) { echo"File is to large"; } if(!$errors) {

            $userPic = md5($_FILES["fileToUpload"]["name"]) . $date_time . " " . $file_name;
            $profilePic = move_uploaded_file($file_tmp,"assets/images/profile_pics/" . $userPic); $file_path = "assets/images/profile_pics/" . $userPic; $stmt = $con->prepare("UPDATE users SET profile_pic = ? WHERE username = ?"); $stmt->bind_param('ss', $file_path, $username);
            $stmt->execute(); $stmt->close();

            header('Location: settings.php');
            exit();
 
        }
    }
} else {

    echo "Invalid Username";
}

?>

คำตอบ

5 LiamSorsby Aug 18 2020 at 21:13

นี่เป็นความคิดเห็นส่วนตัวของฉัน แต่ฉันจะพูดต่อไปนี้:

  1. รหัสควรได้รับการจัดรูปแบบโดยส่วนตัวฉันจะมองไปที่PSR-12เนื่องจากมาตรฐานนี้ควรปฏิบัติตามเมื่อเป็นไปได้
  2. move_uploaded_file ไม่ได้ป้องกันการส่งผ่านไดเรกทอรี คุณควรใช้ basename $_FILES['fileToUpload']['tmp_name']และรูปแบบการตรวจสอบความถูกต้องอื่น ๆ
  3. การตรวจสอบนามสกุลไฟล์ด้วยif(in_array($file_ext,$extensions)=== false)ไม่ได้ป้องกันไม่ให้ผู้ใช้อัปโหลดไฟล์ที่เป็นอันตรายเช่นอาจใช้ magic byte เพื่อหลอกให้เซิร์ฟเวอร์คิดว่าเป็นไฟล์บางประเภท คุณควรดูfinfoและตัวอย่างแรกในการอัปโหลดไฟล์
  4. คุณกำลังสร้างอาร์เรย์ของข้อผิดพลาดซึ่งขณะนี้กำลังตรวจสอบในคำสั่ง if และจากนั้นก็ถูกโยนทิ้งไป หากคุณไม่ได้วางแผนที่จะใช้มันคุณอาจจะดีกว่าเพียงแค่กลับออกจากฟังก์ชันก่อนเวลาแทนที่จะดำเนินการต่อ
  5. ขึ้นอยู่กับว่าชื่อไฟล์ที่ไม่ซ้ำกันคุณควรจะใช้อะไรเช่น uniqid(mt_rand(), true)
  6. move_uploaded_file จะแทนที่ไฟล์หากมีอยู่แล้วคุณอาจต้องการตรวจสอบว่ามีอยู่ก่อนที่คุณจะเขียนทับไฟล์ที่มีอยู่ ขึ้นอยู่กับโซลูชันการตั้งชื่อของคุณไม่น่าจะเกิดขึ้นได้มากนัก แต่ภายใต้ภาระงานสูงเป็นเวลานานสิ่งนี้อาจเกิดขึ้นได้บ่อยกว่าที่คุณคิด
  7. คุณกำลังใช้UPDATE users SET profile_pic = ? WHERE username = ?ฉันคิดว่าค่านี้มีอยู่ในฐานข้อมูลเนื่องจากผู้ใช้จำเป็นต้องเข้าสู่ระบบอย่างไรก็ตามหากคุณไม่แน่ใจว่ามีฟิลด์อยู่หรือไม่ (ฉันไม่เห็นฐานข้อมูล) ฉันจะ ใช้เป็นการส่วนตัว: INSERT INTO users (profile_pic, username) VALUES (?,?) ON DUPLICATE KEY UPDATE profile_pic=?, username=?สิ่งนี้จะแทรกลงในตารางหากไม่มีแถว แต่จะอัปเดตหากมี
  8. คุณได้ตั้งค่าตัวแปรโลคัลชื่อ width และ height และกำลังเปรียบเทียบกับค่าเดียวกัน ฉันคิดว่านี่เป็นการตรวจสอบขนาดไฟล์จริง?

ฉันหวังว่านี่จะช่วยได้บ้าง :)