前言
upload-labs 文件上传靶场通过,跳转Blog :https://gryffinbit.top/2022/09/16/upload-labs%E9%9D%B6%E5%9C%BA%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0/
Web文件上传方法总结
表单上传
这是传统的form表单上传,使用form表单的input[type=”file”]
控件,可以打开系统的文件选择对话框,从而达到选择文件并上传的目的,它的好处是多浏览器兼容,它是web开发者最常用的一种文件上传方式。
表单的代码如下:
1 | <form method="post" action="http://uploadUrl" enctype="multipart/form-data"> |
以下是表单上传几个关键点:
method=”post”
: 采用post方式提交数据enctype=”multipart/form- data”
:采用multipart格式上传文件,此时request头会显示Content-Type:multipart/form-data; boundary=—-WebKitFormBoundaryzr34cwJ67R95KQC9
action
:标明上传的服务端处理地址type=”file”
:使用input的file控件上传- 如果是多文件批量上传,可以将
input[type=”file”]
的name属性设置为如:name=”file[]”
- accept属性是HTML5的新属性,它规定了可通过文件上传提交的文件类型
- 上传的触发事件可以是:
input[type=”file”]
的onChange触发,也可以由一个独立的按钮的onClick使整个表单提交,此时还可以用input[type=”hidden”]带一些其它的参数,比如Token来源验证等等。
Ajax 无刷新上传
Ajax无刷新上传的方式,本质上与表单上传无异,只是把表单里的内容提出来采用ajax提交,并且由前端决定请求结果回传后的展示结果,不用像直接表单上传那样刷新和跳转页面。
html代码片段如下:
1 | <form> |
javascript代码片段如下:
1 | $("#file").on("change", function(){ |
使用file控件的change来触发上传事件,当然也可以使用某个按钮来触发表单提交。提交数据时,用到了FormData对象来发送二进制文件,FormData构造函数提供的append()方法,除了直接添加二进制文件还可以附带一些其它的参数, 作为XMLHttpRequest实例的参数提交给服务端。
使用jQuery提供的ajax方法来发送二进制文件,还需要附加两个参数:
processData: false
// 不要对data参数进行序列化处理,默认为truecontentType: false
// 不要设置Content-Type请求头,因为文件数据是以 multipart/form-data 来编码
截图粘贴上传
截图粘贴上传的核心思想是,监听粘贴事件,然后获取剪切板中的数据,如果是一张图片,则触发上传事件。系统剪切版的数据在不同浏览器保存在不同的位置
- IE内核:windows.clipboardData
- 其它:e.originalEvent.clipboardData
1 | $("textarea").on("paste", function(e){ |
拖拽上传
拖拽上传的方式,支持的浏览器比较少,因为它用到了HTML5的两个新的属性(API)一个是Drag and Drop,一个是File API。
上传域监听拖拽的三个事件:dragEnter、dragOver和drop,分别对应拖拽至、拖拽时和释放三个操作的处理机制,当然你也可以监听dragLeave事件。
HTML5的File API提供了一个FileList的接口,它可以通过拖拽事件的e.dataTransfer.files来传递的文件信息,获取本地文件列表信息。
File API在HTML5规范中只是草案,在 W3C 草案中,File 对象只包含文件名、文件类型和文件大小等只读属性。但部分浏览器在草案之外提供了一个名为 FileReader 的对象,用以读取文件内容,并且可以监控读取状态,它提供的方法有: “readAsBinaryString” ,”readAsDataURL” ,”readAsText” ,”abort” 等。
1 | // dragenter |
拖拽上传过程中的几个关键点:
- 在drop事件触发后通过e.dataTransfer.files获取拖拽文件列表,在jQuery中是e.originalEvent.dataTransfer.files
- 拖拽上传仅支持图片,文件对象中file.type标识了文件类型。
- 由于可能是多图拖拽,所以可以遍历图片上传,这里用了Underscore的each方法。
- 这里用readAsDataURL读取文件内容为二进制文件,你还可以将其转换为Base64方式上传,只是http协议里面存在对非二进制数据的上传大小限制为2M。
- 上传的过程跟前面的方式相同,即:创建FormData对象并发起Ajax请求。
拍照上传
拍照上传可以是PC上的摄像头拍照上传也可以是手机等移动设备的拍照上传。
上传文件时必须做好文件的安全性,除了前端必要的验证,如文件类型、后缀、大小等验证,重要的还是要在后台做安全策略。
这里我列举几个注意点:
- 后台需要进行文件类型、大小、来源等验证
- 定义一个.htaccess文件,只允许访问指定扩展名的文件。
- 将上传后的文件生成一个随机的文件名,并且加上此前生成的文件扩展名。
- 设置上传目录执行权限,避免不怀好意的人绕过如图片扩展名进行恶意攻击,拒绝脚本执行的可能性。
Web文件上传绕过形式
判断方法
上传点
- 上传头像
- 上传相册
- 上传附件
- 添加文章图片
- 前台留言资料上传
- 编辑器文件上传
后缀绕过
- PHP
- Php2, php3, php5, phtml, pht
- asp
- Asa, cer, cdx
- Aspx
- ascx, ashx, asac
- jsp
- jsp, jspx, jspf
绕过类型
- Content-Type绕过
- 前端绕过
- 文件解析规则绕过
- Windows环境特性绕过
- 文件名大小写绕过
- 双写绕过
- 点空格绕过
- 文件头绕过
- 条件竞争绕过