文件上传(一)

一、文件上传概述

1.1、原理

        在存在文件上传功能的页面,若没有对上传的文件进行检测、验证以及过滤。可能会导致恶意用户上传恶意脚本文件,被获取服务端的权限。

1.2、文件上传代码常用函数

$_FILES数组内容如下: 
$_FILES['myFile']['name'] 客户端文件的原名称。 
$_FILES['myFile']['type'] 文件的 MIME 类型,需要浏览器提供该信息的支持,例如"image/gif"。 
$_FILES['myFile']['size'] 已上传文件的大小,单位为字节。 
$_FILES['myFile']['tmp_name'] 文件被上传后在服务端储存的临时文件名,一般是系统默认。可以在php.ini的upload_tmp_dir 指定,但 用 putenv() 函数设置是不起作用的。

move_upload_file(filename,destination)函数:将上传的文件移动到指定位置

preg_match():执行正则表达式

二、文件上传漏洞绕过

2.1、前端JS限制绕过

原理:浏览器通过JS代码对上传的文件进行格式验证

绕过方式:

        1》可以通过Burp抓包修改上传文件的格式

        2》修改JS其中关键的检测函数,或者直接禁用JS

漏洞代码分析:

<script type="text/javascript">
    function checkFile() {
        var file = document.getElementsByName('upload_file')[0].value;
        if (file == null || file == "") {
            alert("请选择要上传的文件!");
            return false;
        }
        //定义允许上传的文件类型
        var allow_ext = ".jpg|.png|.gif";
        //提取上传文件的类型
        var ext_name = file.substring(file.lastIndexOf("."));
        //判断上传文件类型是否允许上传
        if (allow_ext.indexOf(ext_name) == -1) {
            var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
            alert(errMsg);
            return false;
        }
    }
</script>

上述JS函数只允许“.jpg | .png | .gif”的图片格式上传。

2.2、服务端MIME类型验证

MIME简介:

        content-type属性:定义服务端发送给客户端MIME的类型。

        浏览器能处理的所有资源都有对应的MIME类型。

        浏览器根据所接受数据的MIME类型判断用什么方式处理。

        MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

检测原理:服务端通过对MIME类型格式的验证进行过滤。

绕过方式:通过Burp抓包修改Content-Type属性的值来进行检测绕过。

漏洞代码分析:

if (isset($_POST['submit'])) {
    if (file_exists($UPLOAD_ADDR)) {
        if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
            if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
                $img_path = $UPLOAD_ADDR . $_FILES['upload_file']['name'];
                $is_upload = true;}

2.3、文件头绕过

原理:不同的文件存在的文件头格式不同,服务端代码通过检测上传文件的文件头格式来判断是否存在恶意上传。

绕过方式:在上传的恶意文件中修改或添加服务端允许上传的对应文件头。

常见的文件头:

        JPEG:0xFFD8FF

        PNG: 0x89504E470D0A1A0A

        GIF: 47 49 46 38 39 61 (GIF89a)

漏洞代码分析:

function isImage($filename){
    $types = '.jpeg|.png|.gif';
    if(file_exists($filename)){
        $info = getimagesize($filename);
        $ext = image_type_to_extension($info[2]);
        if(stripos($types,$ext)){
            return $ext;
        }else{
            return false;
        }

2.4、.htaccess文件上传

原理:.htaccess文件上传是利用.htaccess文件可以对服务器进行配置的功能,实现将扩展名为.jpg .png等文件当作PHP文件解析的过程。

.htaccess基础

       .htaccess文件(分布式配置文件)提供了一种基于每个目录进行配置更改的方法。她是包含一个或多个配置指令的文件,放在特定的文档目录中,文件的指令适用于该目录及其所有子目录。

       .htaccess是Web服务器的一个配置文件,可以通过.htaccess文件实现web服务器中的文件的解析方式、重定向等配置。

.htaccess文件上传配置

(1)指定文件名:

<Files test.jpg>ForceType application/x-httpd-php SetHandler application/x-httpd-php</Files>

(2)指定文件后缀:

AddType application/x-httpd-php.jpg

2.5、文件截断上传

原理:PHP的版本低于5.3.4时,会把它当作结束符,导致后面的数据直接被忽略,造成文件上传被截断。当上传路径可控时,可以通过%00截断进行木马上传。

绕过方式:

通过可控的上传路径,将恶意脚本后面通过%00截断。

漏洞代码:

$img_path=$_GET['save_path']."/".rand(10,99).date("YmdHis").".".$file_ext;    //代码

?save_path=../upload/+rand(生成随机文件名)        //文件保存路径
?save_path=../upload/1.php%00+rand文件           //通过%00截断后rand生成的随机文件名无效

2.6、竞争条件上传

竞争条件:指多个线程在没有进行锁操作或者同步操作的情况下同时访问同一个共享代码、变量、文件等,运行的结果依赖于不同线程访问数据的顺序。

原理:文件上传时,先上传、再检测、不合条件时再删掉的场景,攻击者利用多线程并发不断上传一个可以写webshell的脚本,然后马上访问这个刚上传的文件,当服务端判断并删除的时间大于客户端线程访问的时间时,客户端可以在删除之前访问到这个脚本并成功运行写入webshell。

漏洞分析:

if(isset($_POST['submit'])){
    $ext_arr = array('jpg','png','gif');
    $file_name = $_FILES['upload_file']['name'];
    $temp_file = $_FILES['upload_file']['tmp_name'];
    $file_ext = substr($file_name,strrpos($file_name,".")+1);
    $upload_file = UPLOAD_PATH . '/' . $file_name;

    if(move_uploaded_file($temp_file, $upload_file)){
        if(in_array($file_ext,$ext_arr)){
             $img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;
             rename($upload_file, $img_path);
             $is_upload = true;
        }else{
            $msg = "只允许上传.jpg|.png|.gif类型文件!";
            unlink($upload_file);
        }

PS:(本文使用代码出自upload-lab靶场)。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的文件上传的示例代码: HTML 文件: ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>文件上传示例</title> </head> <body> <form enctype="multipart/form-data" method="post"> <input type="file" name="file"> <input type="submit" value="上传"> </form> </body> </html> ``` Java 后端代码: ```java import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import static spark.Spark.*; public class FileUploadExample { public static void main(String[] args) { staticFiles.location("/public"); // 设置静态文件目录 post("/upload", (request, response) -> { Part filePart = request.raw().getPart("file"); // 获取上传的文件 String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString(); // 获取文件名 Path filePath = Paths.get("./uploads/" + fileName); // 保存的文件路径 try (InputStream inputStream = filePart.getInputStream()) { Files.copy(inputStream, filePath); // 将文件保存到指定路径 } catch (IOException e) { e.printStackTrace(); } response.status(200); // 设置响应状态码 return "上传成功!"; }); } } ``` 在上述代码中,我们使用 Spark 框架来实现后端逻辑,静态文件目录设置为 public,上传文件的请求路径为 /upload。在上传文件的处理逻辑中,我们先获取上传的文件和文件名,然后将文件保存到指定路径,最后返回上传成功的消息。请注意,需要在服务器上创建一个文件夹 uploads,用于保存上传的文件。 这只是一个简单的文件上传示例,实际应用中还需要考虑安全性、上传文件大小限制等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值