使用PHP

时间:2017-02-26 12:17:14

标签: php

好吧所以我的文件上传有些问题,出于某种原因它说我使用的文件类型无效(我试图上传一张简单的JPEG图片)

继承了我为之奋斗的HMTL

<div id="popup_FileUpload_bg">
    <div id="inner_fillUpload">
        <form action="image-upload.php" method="POST" enctype="multipart/form-data">
            <label>Tekst na slici</label><br/>
            <input id="txt_uploadCustom" name="customFileText" type="text" placeholder="Text..." /><br/><br/>

            <label>Tip postera</label><br/>
            <select name="selectVal">
                <option value="on_pic">Na slici</option>
                <option value="bellow_pic">Ispod slike</option>
                <option value="above_pic">Iznad slike</option>
                <option value="bellow_and_above">Iznad i ispod slike</option>
            </select><br/><br/>

            <label>Kliknite ispod da bi ste ubacili poster</label><br/>
            <input type="file" name="fileToUpload" id="fileToUpload" required><br/><br/>
            <input id="submitFileUploadCustom" type="submit" value="Postavite poster" name="submit">
        </form>
    </div>
</div>

PHP本身

require_once "assets/core/user.php";

use app\user\control as user_c;

if(session_status() == PHP_SESSION_NONE) {
    session_start();
}
$fileNAME = substr(hash('sha512',basename($_FILES["fileToUpload"]["name"])."_".time()),0,10); //I think that this is the problem...
$target_dir = "assets/img/user_uploads/";
$target_file = $target_dir . $fileNAME;
$uploadOk = 1;
$imageFileType = pathinfo($target_file,PATHINFO_EXTENSION);

// Check if image file is a actual image or fake image
if(isset($_POST["submit"])) {
    $check = getimagesize($_FILES["fileToUpload"]["tmp_name"]);
    if($check !== false) {
        $uploadOk = 1;
    } else {
        echo "File is not an image.";
        $uploadOk = 0;
    }
}

// Check file size
if ($_FILES["fileToUpload"]["size"] > 500000) {
    echo "Fajl je preveliki";
    $uploadOk = 0;
}

// Allow certain file formats
if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
&& $imageFileType != "gif" ) {
    echo "Nedozvoljeni tip fajla, mozete ubaciti JPG, JPEG, PNG & GIF kao poster sliku";
    $uploadOk = 0;
}

// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
    echo "<br/>Sorry, your file was not uploaded. "."FILE NAME: ".$fileNAME."<br/> FILE TYPE: ".$imageFileType." <br/> TARGET: ".$target_file;
// if everything is ok, try to upload file
} else {
    if (move_uploaded_file($_FILES["fileToUpload"]['tmp_name'], "assets/img/profiles/".$_SESSION['username'].".".$imageFileType)) {

        //Just adding stuff to MySQL
        $user = new user_c();

        $user->submitUserUpload($_SESSION['username'], $fileNAME, $_POST['customFileText'], $_POST['selectVal'], $imageFileType);

    } else {
        echo "Sorry, there was an error uploading your file.";
    }
}

我已经尝试过调试结果,这就是我所得到的 抱歉,您的文件未上传。

  

文件名:58a0fc9cc0文件类型:目标:   资产/ IMG / user_uploads / 58a0fc9cc0

2 个答案:

答案 0 :(得分:2)

一些提示。

会话

做得好,但你可以做得更好。

if (session_status() === PHP_SESSION_NONE) {
    session_start();
} elseif (session_status() === PHP_SESSION_ACTIVE) {
    session_regenerate_id();
} else {
    throw new \RuntimeException('The PHP session did not start.');
}

安全

您应该将is_uploaded_file()集成到算法中并且更早。另请注意,您可能希望使用multi-byte string functions(mb_ *)来处理文件名。警惕NULL字节和NULL-byte injection(\ 0,等等......)。

至少尝试制作基本文件名过滤器。

private function fileNameFilter($string)
{
    return trim(basename(trim(str_ireplace(['U+0000', '\x00', '\x0', '%00', '\0', 'U+0025', '%25', '%', 'U+000D', "%0a", "\r", 'U+000A', "%0d", "\n", '#', '%2f', '/', '%2f%2f%2e', '../', '%2f%2e', './', ' '],
                                                ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''],
                                                trim(stripslashes(trim(strip_tags(trim(basename($string))))))))));
}

文件类型验证

您开始验证太晚了。 首先使用文件名

执行此操作
basename($_FILES["fileToUpload"]["name"])

首先, 过滤 验证 $_FILES["fileToUpload"]["name"]元素。在尝试使用其任何值之前,请将此作为单独的进程执行。如果文件名太长而且显而易见的黑客怎么办? 信任用户输入。

首先,您的算法会立即尝试获取文件路径的尾随名称组件,然后使用下划线和下划线以及当前时间:

basename($_FILES["fileToUpload"]["name"])."_".time()

// /dir/dir/dir/file.jgp just became file.jpg._191919032450 , etc ...

接下来,您应用散列算法来获取摘要:

hash('sha512',basename($_FILES["fileToUpload"]["name"])."_".time())

//Now, it's 909ujgt43j8534mi349gv5n-934m5uiui53n34-9m9mu-u9

最后,您获取哈希的子字符串。这是您可能需要考虑的地方,以确保您的字符编码是什么等。请记住,始终有mb_substr()。尝试使用两个版本的substr()来测试

$fileNAME = substr(hash('sha512',basename($_FILES["fileToUpload"]["name"])."_".time()),0,10);

// Now, it is i40tl502l-

此时,pathinfo()无法为您提供所需的输出。

$target_dir = "assets/img/user_uploads/";
$target_file = $target_dir . $fileNAME;
$uploadOk = 1;
$imageFileType = pathinfo($target_file,PATHINFO_EXTENSION); //Not going to work.

用于确定文件类型的其他技术包括打开文件并检查它。在Stackoverflow上搜索以获得有关验证上传文件的良好答案。

验证想法(不完整):

以下是我使用filter_var_array()在$ _FILES超全局上进行验证的一部分(仅一部分)。在我到达这一点之前,我清理了用户输入元素。我的过程相当健壮,但我认为我是在说明我的观点。

//Blacklisting Regular Expression.
private $nameRegex    = '/(?>\A[0-9A-Za-z-_]{1,250}?\.[A-Za-z]{1,4}\z){1}?/u';
private $typeRegex    = '/(?>\A[a-z]{1,20}\/[0-9A-Za-z.-]{1,50}\z){1}?/u';
private $tmpNameRegex = '/(?>\A[\/\\A-Za-z:_-]{2,255}\z){1}?/u';

public function setNamedPHPFilterInstructions()
{
    foreach (array_keys($this->filteredInputArray) as $file) {
        $this->phpFieldValidationArray[$file]['error']    = ['filter'  => FILTER_VALIDATE_INT,
                                                             'flags'   => FILTER_REQUIRE_SCALAR,
                                                             'options' => ['min_range' => 0, 'max_range' => 0]];

        $this->phpFieldValidationArray[$file]['size']     = ['filter'  => FILTER_VALIDATE_INT,
                                                             'flags'   => FILTER_REQUIRE_SCALAR,
                                                             'options' => ['min_range' => $this->fileProps[$file]['minSize'], 'max_range' => $this->fileProps[$file]['maxSize']]];

        $this->phpFieldValidationArray[$file]['type']     = ['filter'  => FILTER_VALIDATE_REGEXP, 
                                                             'flags'   => FILTER_REQUIRE_SCALAR, 
                                                             'options' => ['regexp' => $this->typeRegex]];

        $this->phpFieldValidationArray[$file]['name']     = ['filter'  => FILTER_VALIDATE_REGEXP, 
                                                             'flags'   => FILTER_REQUIRE_SCALAR, 
                                                             'options' => ['regexp' => $this->nameRegex]];

        $this->phpFieldValidationArray[$file]['tmp_name'] = ['filter'  => FILTER_VALIDATE_REGEXP, 
                                                             'flags'   => FILTER_REQUIRE_SCALAR, 
                                                             'options' => ['regexp' => $this->tmpNameRegex]];
    }

    return;
}

验证的其他想法包括。

private function hasGoodErrorCodes()
{
    $errorCodes = [];

    //Gather submitted error codes.
    foreach ($_FILES as $file => $properties) {
        $errorCodes[] = $properties['error'];
    }

    //Compare error codes accordingly.
    foreach ($errorCodes as $value) {
        if (!(($value >= UPLOAD_ERR_OK) && ($value <= UPLOAD_ERR_EXTENSION) && ($value !== 5))) {  //There is no 5 error code.
            throw new SecurityException('Invalid file upload error code!');
        }
    }

    return true;
}

private function hasGoodFileSizes()
{
    $fileSizes  = [];
    $fileLimits = [];

    //Gather submitted file sizes.
    foreach ($_FILES as $file => $properties) {
        $fileSizes[$file] = $properties['size'];
    }

    //Gather pre-established file size limits.
    foreach ($this->maxControlCharsArray as $file => $limit) {
        $fileLimits[$file] = $limit['size'];
    }

    //Compare submitted file sizes to their associated size limits.
    foreach ($fileSizes as $file => $size) {
       if (!($size <= $fileLimits[$file])) {
            throw new SecurityException('An uploaded file exceeds upload limits!');
       }
    }

    return true;
}

private function hasGoodMimeTypeLengths()
{
    $mimeTypeLengths = [];
    $mimeTypeLimits = [];

    //Gather submitted mime type lengths.
    foreach ($_FILES as $file => $properties) {
        $mimeTypeLengths[$file] = mb_strlen($properties['type'], 'UTF-8');
    }

    //Gather pre-established mime type length limits.
    foreach ($this->maxControlCharsArray as $file => $limits) {
        $mimeTypeLimits[$file] = $limits['type'];
    }

    //Compare submitted mime type lengths to their associated limits.
    foreach ($mimeTypeLengths as $file => $length) {
       if (!($length === $mimeTypeLimits[$file])) {
            throw new SecurityException('Mime type length exceeds limits!');
       }
    }

    return true;
}

答案 1 :(得分:0)

看看

+\([0-9]+\) //ending with an integer

然后看看

if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg" && $imageFileType != "gif" )

然后

$imageFileType = pathinfo($target_file,PATHINFO_EXTENSION);

和$ filename是

$target_file = $target_dir . $fileNAME;

所以...在&#34;如果&#34;被解雇了文件名没有扩展名,所以&#34;如果&#34;总是给你假的。

尝试改变

$fileNAME = substr(hash('sha512',basename($_FILES["fileToUpload"]["name"])."_".time()),0,10); //I think that this is the problem...