文件上传漏洞-upload靶场1-2关 通过笔记(如何区分前段验证和后端验证)

文件上传漏洞-upload靶场1-2关 通过笔记(区分前段验证和后端验证)

前言

upload是一个文件上传的专用靶场,搭设也非常简单,只需要把相关源码文件放到apache的网站目录下即可使用,或者去github下载一键绿化包进行安装链接如下:

[Releases · c0ny1/upload-labs (github.com)]

image-20230822214734727

下载后按照使用说明安装即可,在安装该靶场时最好安装在虚拟机中,在此也不做过多的解析了,如有不明白可以私聊我。

image-20230822214826621

upload靶场能帮助我们,实践复现文件上传漏洞,帮助我们更好的学习该漏洞形成的原因,该工具一共20关,除了第一关是前段验证,其他19关都是关于后端验证。

image-20230823002849979

upload的难度也是逐步上升,第十关是一个分水岭,后面的内容也是非常硬核

在开始挑战关卡前,我们先了解下什么才是一次成功的攻击:

  1. webshell要成功的上传到服务器中
  2. 要知道webshell在服务器中的路径
  3. 上传的webshell能被正常解析

只有满足这三条条件,才能算一次成功的攻击。

upload第一关(JS验证)

image-20230822222434463

javascript是一个前端常用的语言,用它写的代码在一般情况都是属于前端,不过当你使用node.js为服务器环境时候,javascript也可以作为后端语言来使用。

判断思路

在上传webshell时,我们并不知道该网站使用了那些方法来验证上传的文件,所以我们要从分析源码、抓取流量、随意上传一个文件等方法去分析它的验证方式,以便找到适合的方法去进行攻击。

第一种方法:分析源码
            <h3>任务</h3><p>上传一个<code>webshell</code>到服务器。</p></li><li><h3>上传区</h3><form enctype="multipart/form-data" method="post" onsubmit="return checkFile()"><p>请选择要上传的图片:<p><input class="input_file" type="file" name="upload_file"/><input class="button" type="submit" name="submit" value="上传"/></form><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>

以上源码是从该网站中找到的,其中有一个form表单和一个js脚本较为关键,在form表单中又有两个input标签

form表单有三个属性分别是:

  • enctype属性:表单中用于指定在提交表单数据时使用的编码类型
    • 它的值为multipart/form-data:
      • 表单数据会被分割为多个部分(multipart),每个部分都包含一个表单字段的数据。这种编码类型可以同时传输文本数据和二进制数据,比如上传的文件
  • mothod属性:表示这个表单接收数据的方法
    • 它的值为post:
      • 使用post方法来接收数据
  • onsubmit属性:用于指定在提交表单时执行的 JavaScript 代码
    • 它的值为return checkFile():
      • 用来指定在表单提交之前执行的 JavaScript 函数 checkFile()

input标签解析:

  • - 该代码可以用于创建一个文件上传的输入字段,允许用户选择本地计算机上的文件并上传到服务器。它的表示name值为upload_file
  • - 创建一个提交按钮,并在用户界面中显示 "上传" 文本。当用户点击此按钮时,表单的提交动作将被触发,将表单数据发送到服务器。

从下面的js代码中我们发现了 checkFile()的函数,它的第一句,就是使用 document.getElementsByName() 方法来获取带有 name="upload_file" 属性的元素,并通过索引 [0] 来获取第一个匹配的元素,然后使用 .value 属性获取其值,如果没有上传文件,或上传空文件则提示请选择要上传的文件。

在下半段js代码中,首先限定了上传文件后缀,只能上传这三种后缀的文件,又通过调用 file.lastIndexOf(".") 方法,可以获取文件名中最后一个点(.)的索引。然后,通过调用 file.substring() 方法,可以从该索引位置开始截取字符串,得到文件名中的扩展名进行判断,如果上传的文件不符合要求,则提示用户上传正确的格式的文件

通过这一段代码的分析,我们就可以判断它是一个前端验证的文件上传,确定了是前段验证,那么问题就简单了,所谓前端验证都是纸老虎可不是开玩笑的哈哈。

js代码函数分析

document.getElementsByName()

  • 它是JavaScript 中的一个 DOM 方法,用于根据元素的 name 属性获取文档中所有匹配的元素集合。

  • 该方法接收一个字符串参数,表示要获取的元素的 name 属性的值,返回一个类数组对象,包含所有与指定 name 属性匹配的元素。

对象.lastIndexOf()

  • 它是 JavaScript 字符串的方法,用于获取字符串中最后一个出现的指定字符或子字符串的索引位置。

对象.substring()

  • 它是 JavaScript 字符串的方法,用于获取字符串中指定索引位置之间的子字符串。
第二种方法抓包

首先我们打开Burp抓取一个upload上传的包

image-20230822233118103

把这个包放到repeater(重放器)中进行分析

image-20230822233247084

在此处我们发现,我们上传了一个名为123.jpg的文件,

Content-Type: image/jpeg 表示我们发送的是一个图片文件

在此我们对我们上传的文件后缀名进行更改

  • 如果是前端验证,更改文件后缀名后依旧能正常发送,因为它已经经过了验证。

image-20230822234556009

在修改文件后缀为asp后,也是成功发送给后端服务器,这也能证明它只使用前端验证

第三种方法:随意上传文件分析

这种方法是最为快捷的,但是判断是否是前段验证或后端验证,这种方法就非常考验我们的经验。

如果是前端验证,它的报错响应速度会非常快,因为它一直在你本地的前端,如果是后端服务器验证,相反它的响应速度就会有一定的延迟,具体还得看网络情况,为什么会有延迟呢,我统计了一下情况供大家参考:

  1. 网络延迟:前端验证是在客户端执行的,而后端验证涉及将数据发送到服务器并等待服务器响应。这意味着在进行后端验证时,会出现网络延迟的情况,这可能会导致更长的验证时间。

  2. 请求处理时间:后端验证涉及将数据发送到服务器上的处理程序,然后由服务器上的应用程序进行验证并返回响应。与前端验证相比,服务器的请求处理时间会更长,因为服务器可能涉及其他任务、处理其他请求或执行其他复杂的验证逻辑。

  3. 数据传输量:后端验证涉及将数据上传到服务器进行处理,这需要将数据通过网络传输到服务器,这可能会涉及较大的数据量,因此相对于前端验证来说可能更慢。

攻击思路

前端验证最大的缺点,就是它可以被客户端篡改,这文件就在我本地计算机中,我想咋改就咋改,而后端服务器就比较麻烦了,在后面也会详细的去介绍如何成功上传。

前段验证的攻击方法:

1、直接修改源码:

image-20230822235836598

使用浏览器自带的检查工具,找到前端验证的代码,直接删除。

2、使用bp抓包工具:

image-20230823000308923

直接在抓包工具中修改文件后缀名,因为它已经通过了前段的验证,这时候修改对上传的文件毫无影响。

3、使用br禁用网页的js功能

image-20230823000846522

image-20230823001103937

4、使用浏览器自带的禁用js功能(火狐浏览器)

1.在火狐浏览器的url界面中输入 about:config 进入高级设置界面

image-20230823001327765

找到javascript.enabled

image-20230823001430901

将javascript.enabled的true改为false

image-20230823001503534

同样也能达到br抓包禁用的效果,不过在这里不建议使用浏览器的禁用方法,它会把所有的js全部都禁用掉,一些正常的js也会变层无法使用。

最后上传一个简单的webshell脚本,来测试是否成功。

image-20230823001929745

已经成功获取的网站权限!


upload第二关(MIME验证)

什么是MIME?

MIME(Multipurpose Internet Mail Extensions)是一种用于标识文件类型的标准。它是在互联网上发送邮件和其他数据的一种常用方式。

MIME 类型由两部分组成:主类型和子类型,之间用斜杠(/)分隔。主类型表示文件的大类别,而子类型表示具体的文件类型。例子如下:

  • 文本文件:text/plain
  • HTML 文件:text/html
  • JPEG 图像文件:image/jpeg
  • PNG 图像文件:image/png
  • JSON 数据文件:application/json
  • PDF 文档:application/pdf

MIME 类型主要用于在 HTTP 协议中指定传输的数据类型,并且还在其他应用程序中进行使用,例如电子邮件、文件上传等。通过使用正确的 MIME 类型,服务器和客户端能够理解传输的数据类型,并进行相应的解析和处理。

MIME 类型还可用于指定数据的字符编码、语言和其他相关信息,这些信息用于确保数据的正确显示和处理。

在 HTTP 协议中,MIME 类型常用于请求报文和响应报文的 Content-Type 头字段中,用于指定将要发送或接收的数据的类型。

判断思路

首先还是随意上传一个文件,来判断一下它究竟是前段验证,还是后端服务器验证。

image-20230823234326872

查看源码发现,from表单也有一个onsubmit属性和第一关的一模一样,难道它也是前段验证?抱着怀疑的我们按第一关的操作,把这个属性删除在尝试上传,看看是否能成功。

image-20230823235053202

删除该属性后,尝试上传文件,任然提示文件类型不正确,此时我们就拿出最终绝招,用bp抓个数据包,也按照第一关的方法,去尝试是否能成功上传。

image-20230823235639207

我们上传一个jpeg的图片文件,经过bp后把后缀名改为php,然后放行,看看是否能够成功上传。

image-20230823235952163

居然成功上传了,难道它也是前段验证?那为什么我们删除验证的js脚本函数后,又不能成功上传呢?带着这些疑问,我又开始抓包研究。

image-20230824001327255

在此我有了发现,在第一关我开启Bp抓包的时候,上传一个任意文件,如果上传的文件类型错误,bp就抓不到数据包,而是在网页中直接弹出一个警告框

image-20230824001522759

而到了第二关,我上传一个随意文件时,Bp能抓到一个请求包,并在Content-Type中显示了当前上传文件的类型,text/plain,在此我就可以判断第二关的验证是后端服务器,下面是我画的一张前端验证、后端验证的流程图。

image-20230824004345678

总结一下思路,

  • 如果是前段验证,当bp开启抓包的时候,文件类型错误,将抓不到任何请求包。
  • 如果是服务器后端验证,无论是否成功,Bp都能抓到对应的响应包。
  • 这也就是前段验证和后端验证的最大区别。

攻击思路:

当我们分清楚前端验证和后端验证的区别后,就可以开始分析如何在后端验证的情况,上传一个webshell。

在判断思路中,我们使用第一关的攻击思路,上传一个图片格式的文件,用bp抓包并修改文件后缀,能够成功将webshell上传到站点,但是使用其他格式缺总是失败,而且我们还发现上传不同类型的文件,content-Type的值也是不一样的,这一点证明的后端服务器,可能是开启了一个白名单模式,只有指定的文件类型才能成功上传,那么我们是否可以用bp抓包,对content_type的值进行篡改,来实现攻破后端服务器验证的关卡呢?心动不如行动,我们一起来实践一下。

image-20230824005546942

首先我们先上传一个webshell,后缀为php,在用bp抓住这个包,使用repeter进行验证我们的想法。

image-20230824005726006

我们只修改Content-type的值尝试,能不能正常上传。

image-20230824005801650

果然和我想的一样,只要我们修改了Content-type的值为图片类型,我们就可以上传任意文件,包括webshell。再来尝试上传的webshell是否能正常解析。

image-20230824010024661

使用post方法进行传参,能够成功执行phpinfo();函数,这叫代表我们已经成功闯过了第二关,也就初步了掌握了文件上传的基础技巧,后面还有18个关卡,我们还要继续努力。

后端源码分析
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {if (file_exists(UPLOAD_PATH)) {if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']            if (move_uploaded_file($temp_file, $img_path)) {$is_upload = true;} else {$msg = '上传出错!';}} else {$msg = '文件类型不正确,请重新上传!';}} else {$msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';}
}

在解析源码前,我们先看看这串源码中,使用了哪些函数
  1. isset():用于检查变量或表单字段是否已设置和存在。
  2. file_exists():用于检查指定文件或目录是否存在。
  3. $_POST:是一个包含通过 POST 方法提交的表单字段和值的关联数组。在这里,$_POST['submit'] 用于检查表单是否通过提交按钮进行了提交。
  4. $_FILES:是一个包含通过文件上传的文件信息的关联数组。在这里,$_FILES['upload_file'] 包含了关于上传文件的信息,如文件名、临时路径、文件大小、文件类型等。
  5. move_uploaded_file():用于将上传的文件移动到目标位置。

以下是对代码的解释和说明:

在这段代码中,首先定义了一个布尔变量 $is_upload 并初始化为 false,用于表示文件是否成功上传。还定义了一个变量 $msg ,用于存储上传过程中的提示信息。

通过使用 isset($_POST['submit']) 检查表单是否通过提交按钮进行了提交。

使用 file_exists(UPLOAD_PATH) 来检查指定的上传目录是否存在。UPLOAD_PATH 是一个用于存储上传文件的目录路径。

使用 $_FILES['upload_file']['type'] 来获取上传文件的 MIME 类型(例如:image/jpegimage/pngimage/gif)。

通过使用 $_FILES['upload_file']['tmp_name'] 获取上传文件的临时路径。

通过使用 $_FILES['upload_file']['name']UPLOAD_PATH 来创建存储上传文件的目标路径。

使用 move_uploaded_file($temp_file, $img_path) 将上传的临时文件移动到目标路径。

当移动文件成功时,将 $is_upload 设置为 true,如果移动文件失败,则将 $msg 设置为 ‘上传出错!’。

如果上传文件的类型不是 ‘image/jpeg’、‘image/png’ 或 ‘image/gif’,将 $msg 设置为 ‘文件类型不正确,请重新上传!’。

如果上传目录不存在,将 $msg 设置为 UPLOAD_PATH 所指定的目录路径后面跟上 ‘文件夹不存在,请手工创建!’。

这个代码片段主要用于处理文件上传过程,并设置content-type的值为image/jpeg、png、gif,也就是说只要请求头中的content-type字段的值是上诉的文件类型,都可以成功上传。
文件移动到目标路径。

当移动文件成功时,将 $is_upload 设置为 true,如果移动文件失败,则将 $msg 设置为 ‘上传出错!’。

如果上传文件的类型不是 ‘image/jpeg’、‘image/png’ 或 ‘image/gif’,将 $msg 设置为 ‘文件类型不正确,请重新上传!’。

如果上传目录不存在,将 $msg 设置为 UPLOAD_PATH 所指定的目录路径后面跟上 ‘文件夹不存在,请手工创建!’。

这个代码片段主要用于处理文件上传过程,并设置content-type的值为image/jpeg、png、gif,也就是说只要请求头中的content-type字段的值是上诉的文件类型,都可以成功上传。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/107224.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于SSM+vue框架的校园代购服务订单管理系统源码和论文

基于SSMvue框架的校园代购服务订单管理系统源码和论文070 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 摘 要 在新发展的时代&#xff0c;众多的软件被开发出来&#xff0c;给用户带来了很大的选择余地&am…

git及GitHub的使用

文章目录 git在本地仓库的使用github使用创建仓库https协议连接(不推荐&#xff0c;现在用起来比较麻烦)ssh连接&#xff08;推荐&#xff09;git分支操作冲突处理忽略文件 git在本地仓库的使用 1.在目标目录下右键打开git bash here 2.创建用户名和邮箱(注&#xff1a; 下载完…

网络编程套接字(2): 简单的UDP网络程序

文章目录 网络编程套接字(2): 简单的UDP网络程序3. 简单的UDP网络程序3.1 服务端创建(1) 创建套接字(2) 绑定端口号(3) sockaddr_in结构体(4) 数据的接收与发送接收发送 3.2 客户端创建3.3 代码编写(1) v1_简单发送消息(2) v2_小写转大写(3) v3_模拟命令行解释器(4) v4_多线程版…

[论文阅读笔记26]Tracking Everything Everywhere All at Once

论文地址: 论文 代码地址: 代码 这是一篇效果极好的像素级跟踪的文章, 发表在ICCV2023, 可以非常好的应对遮挡等情形, 其根本的方法在于将2D点投影到一个伪3D(quasi-3D)空间, 然后再映射回去, 就可以在其他帧中得到稳定跟踪. 这篇文章的方法不是很好理解, 代码也刚开源, 做一…

兵力集中更容易进攻获胜

我兵力集中&#xff0c;敌兵力分散&#xff0c;进攻可胜 【安志强趣讲《孙子兵法》第21讲】 【原文】 进而不可御者&#xff0c;冲其虚也&#xff1b;退而不可追者&#xff0c;速而不可及也。 【趣讲白话】 进攻时&#xff0c;敌人无法抵御&#xff0c;那是攻击了敌人空虚的地方…

小程序input的placeholder不垂直居中的问题解决

input的placeholder不垂直居中&#xff0c;input设置高度后&#xff0c;使用line-height只能使输入的文字垂直居中&#xff0c;但是placeholder不会居中&#xff0c;反而会偏上。 首先placeholder样式自定义 有两种方法&#xff0c;第一种行内样式&#xff1a; <input ty…

大彩串口屏使用记录

写在最前面 屏幕型号 DC10600M070 IDE VisualTFT&#xff08;官方&#xff09; VSCode&#xff08;lua编程&#xff09; 用之前看一下官方那个1小时的视频教程就大概懂控件怎么用了&#xff0c;用官方的软件VisualTFT很简单 本文只是简单记录遇到的一些坑 lua编辑器 VisualTF…

uview ui 查看版号

版本查询2种方式 有两种方式可以查询到正在使用的uView的版本&#xff1a; // 通过console.log打印的形式 console.log(uni.$u.config.v);// 可以查阅uView的配置文件得知当前版本号&#xff0c;具体位置为&#xff1a; /uview-ui/libs/config/config.js

Linux centos7 bash编程(小练习)

一、打印九九乘法口诀 这一个for循环嵌套的小练习&#xff0c;难度不大。提供一种写法&#xff0c;供参考&#xff1a; #!/bin/bash # 文件名&#xff1a;99table.sh # 打印输出九九乘法口诀表 for i in {1..9} do for ((j1;j<$i;j)) do …

R-Meta分析核心技术教程

详情点击链接&#xff1a;全流程R-Meta分析核心技术教程 一&#xff0c;Meta分析的选题与检索 1、Meta分析的选题与文献检索 1)什么是Meta分析 2)Meta分析的选题策略 3)精确检索策略&#xff0c;如何检索全、检索准 4)文献的管理与清洗&#xff0c;如何制定文献纳入排除标准 …

【Git】测试持续集成——Git+Gitee+PyCharm

文章目录 概述一、使用Gitee1. 注册账号2. 绑定邮箱3. 新建仓库4. 查看项目地址 二、安装配置Git1. 下载安装包2. 校验是否安装成功。3. 配置Git4. Git命令5. Git实操 三、PyCharmGit1. 配置Git2. Clone项目3. 提交文件到服务器4. 从服务器拉取文件 概述 持续集成&#xff08;…

开源在物联网(IoT)中的应用

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

react解决死循环方法?

使用useeffect&#xff08;副作用&#xff09;方法结束这个操作 1、导入useeffect、useState 2、把下方代码写入&#xff1a;里面填写的是你要终止某个东西的代码 注意&#xff1a;不可不写&#xff0c;也可以写依赖或不写

基于Python+djangoAI 农作物病虫害预警系统智能识别系统设计与实现(源码&教程)

1.背景 随着科技的发展&#xff0c;机器学习技术在各个领域中的应用越来越广泛。在农业领域&#xff0c;机器学习技术的应用有助于提高农作物的产量和质量&#xff0c;降低农业生产的成本。本文针对农作物健康识别问题&#xff0c;提出一种基于机器学习方法的农作健康识别系统&…

Spring Boot整合RabbitMQ之路由模式(Direct)

RabbitMQ中的路由模式&#xff08;Direct模式&#xff09;应该是在实际工作中运用的比较多的一种模式了&#xff0c;这个模式和发布与订阅模式的区别在于路由模式需要有一个routingKey&#xff0c;在配置上&#xff0c;交换机类型需要注入DirectExchange类型的交换机bean对象。…

JMeter性能测试(上)

一、基础简介 界面 打开方式 双击 jmeter.bat双击 ApacheJMeter.jsr命令行输入 java -jar ApacheJMeter.jar 目录 BIN 目录&#xff1a;存放可执行文件和配置文件 docs目录&#xff1a;api文档&#xff0c;用于开发扩展组件 printable-docs目录&#xff1a;用户帮助手册 li…

docker harbor私有库

目录 一.Harbor介绍 二.Harbor的特性 三.Harbor的构成 四.Harbor构建Docker私有仓库 4.2在Server主机上部署Harbor服务&#xff08;192.168.158.25&#xff09; 4.2.1 这时候这边就可以去查看192.168.158.25网页 4.3此时可真机访问serverIP 4.4通过127.0.0.1来登陆和推送镜…

vue 中 axios 的安装及使用

vue 中 axios 的安装及使用 1. axios 安装2. axios使用 1. axios 安装 首先&#xff0c;打开当前的项目终端&#xff0c;输入 npm install axios --save-dev验证是否安装成功&#xff0c;检查项目根目录下的 package.json,其中的 devDependencies 里面会多出一个axios及其版本…

Linux(基础篇二)

Linux基础篇 Linux基础篇二5. 系统管理5.1 Linux中的进程和服务5.3 systemctl5.4 运行级别CentOS 6CentOS 7 5.5 关机重启命令 Linux基础篇二 5. 系统管理 5.1 Linux中的进程和服务 计算机中&#xff0c;一个正在执行的程序或命令&#xff0c;被叫做“进程”(process) 启动之…

OpenCV实战(基础知识三)

简介 OpenCV是一个流行的开源计算机视觉库&#xff0c;由英特尔公司发起发展。它提供了超过2500个优化算法和许多工具包&#xff0c;可用于灰度、彩色、深度、基于特征和运动跟踪等的图像处理和计算机视觉应用。OpenCV主要使用C语言编写&#xff0c;同时也支持Python、Java、C…