PHP文件上传安全

文件上传漏洞等危害

攻击者上传shell脚本,借助脚本控制服务器,随意执行命令。

漏洞举例

<?php

    $dir = 'uploads/';
    $file = $dir . basename($_FILES['file']['name']);
    move_upload_file( $_FILE['file']['tmp_name'], $file);
?>

如果攻击者上传如脚本文件file.php

<?php
    system($_GET['shell']);
?>

则可以通过http://host/uploads/file.php?shell=ls -la,查看服务器目录信息,并且可以执行任何shell命令。

过滤上传文件类型和文件扩展名

<?php
    if( $_FILEs['file']['type'] != 'image/gif' ){
        die('类型错误');
    }
?>

但是如果攻击者通过修改POST数据包中的Content-Type:text/plain字段为Content-Type:image/git,则可跳过检验成功上传,所以还需检查文件扩展名。

<?php
    $whiteList = [
        '.jpg', '.gif', '.png', '.jpeg',
    ];

    $ext = substr( $_FILES['file']['name'], -4 );
    if( !in_array( $ext, $whiteList ) ){
        die('类型错误');
    }
?>

综合防护

  1. 白名单限制文件类型
  2. 白名单限制文件扩展名
  3. 随机文件名
  4. 上传目录放到项目可执行目录之外
  5. 禁止上传文件的执行权限
  6. 如果可以的话,通过php.ini配置禁用危险函数: disable_function = system,exec,scandir,shell_exec等
<?php

class FileSecurity
{
    const DIR = '/data/uploads/';

    private $whiteExt = [
        '.jpg', '.gif', '.png', '.jpeg',
    ];
    private $whiteType = [
        'image/jpg', 'image/gif', 'image/png', 'image/jpeg',
    ];
    private $nameChars = [
        'a', 'b', 'c', 'd', 'e', 'f', 'g',
        'h', 'i', 'j', 'k', 'l', 'm', 'n',
        'o', 'p', 'q', 'r', 's', 't', 'u',
        'v', 'w', 'x', 'y', 'z',
        'A', 'B', 'C', 'D', 'E', 'F', 'G',
        'H', 'I', 'J', 'K', 'L', 'M', 'N',
        'O', 'P', 'Q', 'R', 'S', 'T', 'U',
        'V', 'W', 'X', 'Y', 'Z',
        '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
    ];

    public function filter($file, $type)
    {
        if ( !in_array($type, $this->whiteType) ){
            return false;
        }

        $ext = substr($file, -4);
        if ( !in_array($ext, $this->whiteExt) ){
            return false;
        }
    }

    public function getFileName()
    {
        $len = count($this->nameChars) - 1;
        shuffle($this->nameChars);
        $name = '';
        for ($i = 0; $i < $len; $i++){
            $name .= $this->nameChars[ mt_rand(0, $len) ];
        }
        return $name;
    }

    public function chmod($file)
    {
        $file = self::DIR . $file;
        @chmod($file, 0444);
    }
}
?>
发布了253 篇原创文章 · 获赞 47 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/why444216978/article/details/104733341