加入收藏 | 设为首页 | 会员中心 | 我要投稿 成都站长网 (https://www.028zz.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

文件上传漏洞总结

发布时间:2022-09-30 05:32:38 所属栏目:PHP教程 来源:未知
导读: 常见的上传漏洞原理及一些简单绕过方法总结。
文件上传漏洞概述
几乎每个网站中都会有上传文件的地方,上传头像、视频、压缩包等等......代码写的不严谨,没有对上传的文件的文件名、文件类

常见的上传漏洞原理及一些简单绕过方法总结。

文件上传漏洞概述

几乎每个网站中都会有上传文件的地方,上传头像、视频、压缩包等等......代码写的不严谨,没有对上传的文件的文件名、文件类型等等进行严格限制的话,攻击者如果成功上传了恶意脚本文件就可以达到控制网站等目的。

常见上传漏洞分类客户端javascript校验

JavaScript校验是在浏览器进行的,也就是在数据发送到服务器之前,因此很容易绕过。




    
    Document





上面的js代码在上传文件时进行了文件后缀和文件大小的限制。

PHP文件上传_php文件上传代码_php 上传doc docx文件

我们选择的文件不在允许的文件后缀中就会弹出此提示框,绕过也很简单。

在浏览器设置中禁用JavaScript即可。

php文件上传代码_php 上传doc docx文件_PHP文件上传

PHP文件上传_php文件上传代码_php 上传doc docx文件

这样便可以绕过前端js验证,如果后端代码没有做限制的话即可上传成功。

服务端content-type字段校验(MIME)

关于MIME的介绍请自行百度百度,限制的地方是数据包中的content-type字段。

php上传代码:

<?php  
    if(isset($_GET['a'])){
        echo '  ';
        $a = $_GET['a'];
        if($a==1){
        //获取文件的大小  
        $file_size=$_FILES['myfile']['size'];  
        if($file_size>2*1024*1024) {  
            echo "文件过大,不能上传大于2M的文件";  
            exit();  
        }  
        $file_type=$_FILES['myfile']['type'];  
        echo $file_type;  
        if($file_type!="image/jpeg" && $file_type!='image/pjpeg') {  
            echo "文件类型只能为jpg格式";  
            exit();  
        }  
        //判断是否上传成功(是否使用post方式上传)  
        if(is_uploaded_file($_FILES['myfile']['tmp_name'])) {  
            //把文件转存到你希望的目录(不要使用copy函数)  
            $uploaded_file=$_FILES['myfile']['tmp_name'];  
            //我们给每个用户动态的创建一个文件夹  
            $user_path=$_SERVER['DOCUMENT_ROOT']."/up";  
            //判断该用户文件夹是否已经有这个文件夹  
            if(!file_exists($user_path)) {  
                mkdir($user_path);  
            }  
            //$move_to_file=$user_path."/".$_FILES['myfile']['name'];  
            $file_true_name=$_FILES['myfile']['name'];  
            $move_to_file=$user_path."/".$file_true_name;  
            //echo "$uploaded_file   $move_to_file";  
            if(move_uploaded_file($uploaded_file,iconv("utf-8","gb2312",$move_to_file))) {  
                echo $_FILES['myfile']['name']."上传成功";  
            } else {  
                echo "上传失败";  
            } 
        } else {  
            echo "上传失败";  
        }  
        }
    }
?>

代码中只允许image/jpeg和image/pjpeg这两种类型,其他类型则上传失败。

PHP文件上传_php 上传doc docx文件_php文件上传代码

我们可以拦截数据包,修改content-type字段即可绕过MIME验证。

PHP文件上传_php 上传doc docx文件_php文件上传代码

php文件上传代码_php 上传doc docx文件_PHP文件上传

成功上传。

文件内容头校验

一些上传的地方会检测文件内容头判断是不是允许上传的文件类型PHP文件上传,不同类型的文件文件头也是不一样的。例如jpg图片:

PHP文件上传_php 上传doc docx文件_php文件上传代码

验证文件头的代码:

<?php
class FileTypeValidation
{
    // 文件类型,不同的头信息
    private static $_fileFormats = Array(
    'jpeg' => 'FFD8FF',
    'jpg' => 'FFD8FF',
    );
    /**
    * 检查文件类型
    *
    * @param string $filePath 文件路径
    * @param string $fileExt 文件扩展名
    *
    * @return boolean
    */
    public static function validation($filePath, $fileExt)
    {
    // 文件格式未知
    if (!isset(self::$_fileFormats[$fileExt]))
    {
    return false;
    }
    $length = strlen(self::$_fileFormats[$fileExt]);
    $bin = self::_readFile($filePath, $length);
    $fileHead = @unpack("H{$length}", $bin);
    // 判断文件头
    if (strtolower(self::$_fileFormats[$fileExt]) == $fileHead[1])
    {
    return true;
    }
    return false;
    }
    /**
    * 读取文件内容
    *
    * @param string $filePath 文件路径
    * @param integer $size
    *
    * @return string
    */
    private function _readFile($filePath, $size)
    {
    $file = fopen($filePath, "rb");
    $bin = fread($file, $size);
    fclose($file);
    return $bin;
    }
}
if(isset($_GET['a'])){
        echo '  ';
        $a = $_GET['a'];
        if($a==1){
        //获取文件的大小  
        $file_size=$_FILES['myfile']['size'];  
        if($file_size>2*1024*1024) {  
            echo "文件过大,不能上传大于2M的文件";  
            exit();  
        }  
        $file_type=$_FILES['myfile']['type'];  
        echo $file_type;  
        if($file_type!="image/jpeg" && $file_type!='image/pjpeg') {  
            echo "文件类型只能为jpg格式";  
            exit();  
        }  
        //判断是否上传成功(是否使用post方式上传)  
        if(is_uploaded_file($_FILES['myfile']['tmp_name'])) {  
            //把文件转存到你希望的目录(不要使用copy函数)  
            $uploaded_file=$_FILES['myfile']['tmp_name'];  
            $x = FileTypeValidation::validation($uploaded_file, 'jpg');
            if(!$x){
                echo "文件头验证失败";  
                exit(); 
            }
            //我们给每个用户动态的创建一个文件夹  
            $user_path=$_SERVER['DOCUMENT_ROOT']."/up";  
            //判断该用户文件夹是否已经有这个文件夹  
            if(!file_exists($user_path)) {  
                mkdir($user_path);  
            }  
            //$move_to_file=$user_path."/".$_FILES['myfile']['name'];  
            $file_true_name=$_FILES['myfile']['name'];  
            $move_to_file=$user_path."/".$file_true_name;  
            //echo "$uploaded_file   $move_to_file";  
            if(move_uploaded_file($uploaded_file,iconv("utf-8","gb2312",$move_to_file))) {  
                echo $_FILES['myfile']['name']."上传成功";  
            } else {  
                echo "上传失败";  
            } 
        } else {  
            echo "上传失败";  
        }  
        }
    }
?>

上面代码验证了文件头符合jpg类型的才可以上传成功。我们先随便上传一个文件。

php 上传doc docx文件_PHP文件上传_php文件上传代码

上传失败,这时最简单的方法就是制作一张图片马,把脚本代码插入到图片文件的后面,这样文件头依然是原文件的文件头。

PHP文件上传_php文件上传代码_php 上传doc docx文件

php 上传doc docx文件_PHP文件上传_php文件上传代码

成功上传。

后缀名黑名单校验

顾名思义后缀黑名单就是明确指出了哪些后缀不允许上传,同样也是有一些方法可以绕过的。

后缀黑名单代码:

<?php  
    if(isset($_GET['a'])){
        echo '  ';
        $a = $_GET['a'];
        if($a==1){
        $file_size=$_FILES['myfile']['size'];  
        if($file_size>2*1024*1024) {  
            echo "文件过大,不能上传大于2M的文件";  
            exit();  
        }  
        $file_type=$_FILES['myfile']['type'];  
        echo $file_type;  
        if($file_type!="image/jpeg" && $file_type!='image/pjpeg') {  
            echo "文件类型只能为jpg格式";  
            exit();  
        }  
        //判断是否上传成功(是否使用post方式上传)  
        if(is_uploaded_file($_FILES['myfile']['tmp_name'])) {  
            $file = $_FILES['myfile']['name'];
            $hou = substr(strrchr($file, '.'), 1);
            if($hou == "php"){
                echo "不允许上传php";  
                exit();  
            }
            //把文件转存到你希望的目录(不要使用copy函数)  
            $uploaded_file=$_FILES['myfile']['tmp_name'];  
            //我们给每个用户动态的创建一个文件夹  
            $user_path=$_SERVER['DOCUMENT_ROOT']."/websec/up";  
            //判断该用户文件夹是否已经有这个文件夹  
            if(!file_exists($user_path)) {  
                mkdir($user_path);  
            }  
            //$move_to_file=$user_path."/".$_FILES['myfile']['name'];  
            $file_true_name=$_FILES['myfile']['name'];  
            $move_to_file=$user_path."/".$file_true_name;  
            //echo "$uploaded_file   $move_to_file";  
            if(move_uploaded_file($uploaded_file,iconv("utf-8","gb2312",$move_to_file))) {  
                echo $_FILES['myfile']['name']."上传成功";  
            } else {  
                echo "上传失败";  
            } 
        } else {  
            echo "上传失败";  
        }  
        }
    }
?>  
  
  
  
上传你的File吧  
  
文件上传
请选择你要上传文件:

上面代码限制了不允许后缀为php的文件上传。

php文件上传代码_php 上传doc docx文件_PHP文件上传

代码中没有统一大小写,这时我们可以使用大小写绕过。

php文件上传代码_php 上传doc docx文件_PHP文件上传

windows文件名不区分大小写,文件中的代码依然可以正常解析执行。

也可以尝试00截断等方法。 00截断利用限制

PHP<5.3.29,且GPC关闭

后缀名白名单校验

很好理解,白名单是明确限制了只允许哪些后缀上传,其他的都不允许,一般白名单要比黑名单安全的多,但也可以结合解析漏洞、00截断等方法尝试绕过。

还有一些其他情况如检测文件内容、二次渲染等等。 同样绕过方法也还有很多,如上传特殊可解析后缀、上传.htaccess、双后缀名、伪协议等等,各种骚姿势可以根据情况自己慢慢挖掘。

不是每个上传点都存在可以绕过的上传漏洞,获得权限的方法不止一种,无法突破的也不要钻牛角尖。

(编辑:成都站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!