文件上传漏洞-upload靶场1-2关 通过笔记(区分前段验证和后端验证)
前言
upload是一个文件上传的专用靶场,搭设也非常简单,只需要把相关源码文件放到apache的网站目录下即可使用,或者去github下载一键绿化包进行安装链接如下:
[Releases · c0ny1/upload-labs (github.com)]
下载后按照使用说明安装即可,在安装该靶场时最好安装在虚拟机中,在此也不做过多的解析了,如有不明白可以私聊我。
upload靶场能帮助我们,实践复现文件上传漏洞,帮助我们更好的学习该漏洞形成的原因,该工具一共20关,除了第一关是前段验证,其他19关都是关于后端验证。
upload靶场的难度也是逐步上升,到第十三关就是一个分水岭。
在开始挑战关卡前,我们先了解下什么才是一次成功的攻击:
- webshell要成功的上传到服务器中
- 要知道webshell在服务器中的路径
- 上传的webshell能被正常解析
只有满足这三条条件,才能算一次成功的攻击。
upload第一关(JS验证)
JavaScript简单介绍:
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表单有三个属性分别是:
- enctype属性:表单中用于指定在提交表单数据时使用的编码类型
- 它的值为multipart/form-data:是一种HTTP请求中的数据格式,用于在请求中传输二进制数据或包含非ASCII字符的文本数据。它常用于文件上传或表单提交
- mothod属性:表示这个表单接收数据的方法
- 它的值为post: 使用post方法来接收数据
- onsubmit属性:用于指定在提交表单时执行的 JavaScript 代码
- 它的值为return checkFile():用来指定在表单提交之前执行的 JavaScript 函数
checkFile()
- 它的值为return checkFile():用来指定在表单提交之前执行的 JavaScript 函数
input标签解析:
- <input class=“input_file” type=“file” name=“upload_file”/>
- 该代码可以用于创建一个文件上传的输入字段,允许用户选择本地计算机上的文件并上传到服务器。它的表示name值为upload_file
- <input class=“button” type=“submit” name=“submit” value=“上传”/>
- 创建一个提交按钮,并在用户界面中显示 “上传” 文本。当用户点击此按钮时,表单的提交动作将被触发,将表单数据发送到服务器。
从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 suite抓包
首先我们打开Burp抓取一个upload上传的包
把这个包放到repeater(重放器)中进行分析
在此处我们发现,我们上传了一个名为123.jpg的文件,
Content-Type: image/jpeg 表示我们发送的是一个图片文件
在此我们对我们上传的文件后缀名进行更改
- 如果是前端验证,更改文件后缀名后依旧能正常发送,因为它已经经过了验证。
在修改文件后缀为asp后,也是成功发送给后端服务器,这也能证明它只使用前端验证。
使用burp suite抓包还有一种更为简单有效的方式,直接开启burp suite拦截请求包,然后上传一个受限制的文件,如果burpsuite 没有抓到包的情况,网页出现了提示,那么它就是前端验证,反之它就是属于后端验证。
攻击思路
前端验证最大的缺点,就是它可以被客户端篡改,这文件就在我本地计算机中,我想咋改就咋改,而后端服务器就比较麻烦了,在后面也会详细的去介绍如何成功上传。
前段验证的攻击方法:
1、直接修改源码:
使用浏览器自带的检查工具,找到前端验证的代码,直接删除。
2、使用bp抓包工具:
直接在抓包工具中修改文件后缀名,因为它已经通过了前段的验证,这时候修改对上传的文件毫无影响。
3、使用br禁用网页的js功能
4、使用浏览器自带的禁用js功能(火狐浏览器)
1.在火狐浏览器的url界面中输入 about:config 进入高级设置界面
找到javascript.enabled
将javascript.enabled的true改为false
同样也能达到br抓包禁用的效果,不过在这里不建议使用浏览器的禁用方法,它会把所有的js全部都禁用掉,一些正常的js也会变层无法使用。
最后上传一个简单的webshell脚本,来测试是否成功。
已经成功获取的网站权限!
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
头字段中,用于指定将要发送或接收的数据的类型。
源码分析
$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.'文件夹不存在,请手工创建!';
}
}
通过分析,我们得知这是一个后端验证的示例,用于验证上传的文件是否符合特定的条件。
- $is_upload:用于表示是否成功上传文件,初始值为false。
- $msg:用于存储验证过程中的提示信息,初始值为null。
进入验证过程的条件是用户点击了表单中的"submit"按钮,即$_POST[‘submit’]存在。
验证的逻辑如下:
- 首先,检查指定的上传路径(UPLOAD_PATH)是否存在。如果不存在,将$msg设置为包含错误信息的字符串。
- 如果上传路径存在,继续验证。
- 验证上传文件的类型是否符合要求。此源码要求上传文件的类型必须是"image/jpeg"、"image/png"或"image/gif"之一。
- 如果上传文件的类型符合要求,将临时文件($_FILES[‘upload_file’][‘tmp_name’])移动到指定的上传路径。如果成功移动文件,将、$is_upload设置为true。
- 如果移动文件失败,将$msg设置为包含错误信息的字符串。
- 如果上传文件的类型不符合要求,则提示文件类型不正确,请重新上传
攻击思路
首先还是随意上传一个文件,使用burpsuite来抓包,来判断一下它是使用什么验证方式。
在上传了一个webshell后,发现burpsuite拦截到一个请求包,网页也并没有报错,由此判断它使用的是后段验证的方式。
直接放行后,发现网页报错,文件类型不正确。
分析请求包,在请求体中找到Content-Type字段,它的值是 application/octet-steram它表示表示不具有特定媒体类型的二进制数据。它通常用于传输无法被其他媒体类型明确定义、或者未知的二进制数据。通俗的讲,发送方(本地)不能确定上传文件的具体类型,或者故意将其视为通用的二进制数据类型
Content-Type出现在请求体中,就可以初步怀疑,它是不是后端验证文件的MIME类型,如果我将这个值更改为,后端允许上传的文件名,是否能够完成上传,心动不如行动,我们开始尝试。
更改了Content-Type的值为image/png后,发现文件上传成功了,现在就可以确认后端就是使用了MIME验证,现在我们只要去解析webshell查看是否成功通关
成功解析出phpinfo();函数,成功过关。
总结:
前段验证和后端验证:
-
前端验证:
前端验证是在客户端(例如浏览器)上进行的验证,用于验证用户输入的数据是否符合特定的规则和格式。前端验证一般是通过使用JavaScript等脚本语言来实现的。它的主要目的是提供即时的用户反馈,帮助用户在提交表单或进行其他操作之前发现和纠正输入错误。前端验证可以增强用户体验,减少不必要的网络请求和服务器负担,但它并不能完全信任,因为客户端的验证可以被绕过或篡改。 -
后端验证:
后端验证是在服务器端进行的验证,用于验证从客户端发送的数据是否合法、安全和可信。后端验证通常在服务器端使用编程语言和框架进行实现。它的主要目的是确保接收到的数据符合业务逻辑和安全要求,并保护服务器和应用程序免受潜在的威胁和攻击。后端验证相对于前端验证更可靠,因为服务器有更多的控制权,并且可以进行更严格和全面的验证。
两者区别:文章来源:https://www.toymoban.com/news/detail-680796.html
- 基础位置:前端验证发生在客户端,后端验证发生在服务器端。
- 目的:前端验证主要用于提供即时的用户反馈和验证,后端验证主要用于确保数据的合法性、安全性和可信度。
- 安全性:后端验证更可靠,因为客户端验证可以被篡改或绕过,所以后端验证对于确保数据的安全性更为重要。
- 容错性:前端验证可以提供更快的用户反馈,但它也需要后端验证来确保数据的一致性和完整性。
- 执行顺序:前端验证通常在用户提交数据之前执行,而后端验证在服务器接收到数据后执行。
- 数据传输:前端验证可以减少不必要的网络请求和服务器负担,而后端验证可以过滤和处理来自客户端的不可信数据。
最后奉上一个前段、后端验证流程图。
文章来源地址https://www.toymoban.com/news/detail-680796.html
到了这里,关于文件上传漏洞-upload靶场1-2关 通过笔记(如何区分前段验证和后端验证)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!