什么是文件上传漏洞
在使用网站时,我们经常遇到一些需要我们上传文件(图片、文档等等)的场景
但网站设计者并没有对上传的文件类型做过滤或过滤可以被攻击者绕过,若攻击者上传了恶意的文件,如一句话木马等,则会对服务器安全性产生影响
总而言之,文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。这种攻击方式是最为直接和有效的,“文件上传” 本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件,如果服务器的处理逻辑做的不够安全,则会导致严重的后果
漏洞利用条件
-
恶意文件可以成功上传 -
恶意文件上传后的路径可知 -
恶意文件可被访问或执行
Web Shell
什么是 Web Shell
Web Shell 就是以 asp、aspx、php、jsp 等网页文件形式存在的一种命令执行环境,也可以将其称做为一种网页后门,攻击者在入侵了一个网站后,通常会将后门文件与网站 Web 服务器目录下正常的网页文件混在一起,然后就可以使用浏览器来访问该后门文件了
实际上,Web Shell 可以使用服务器上支持的任何编程语言进行编程,但最常用 PHP 编写,因为 PHP 在 Web 应用程序中被广泛使用,攻击者可以使用 Web Shell 发出 shell 命令,在 Web 服务器上执行权限提升,以获得向 Web 服务器上传、删除、下载和执行文件的能力
Web Shell 的分类
Web Shell 分为功大马(功能完善的木马)和小马(一句话木马),它们的区别如下:
-
大马:功能完善,直接使用浏览器即可利用 -
小马:功能简单,需要配合客户端使用
文件上传方式
通常一个文件以 HTTP 协议进行上传时,将以 POST 请求发送至 Web 服务器,Web 服务器接收到请求后并同意后,用户与 Web 服务器将建立连接,并传输数据
安全检测方式
文件上传请求报文特征
在介绍如何请求做安全检测之前,我们先来分析一下请求报文的特征,这里截取的是报文头的部分
POST /vul/unsafeupload/clientcheck.php HTTP/1.1
Host: 127.0.0.21
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=---------------------------9501037142524743667159495619
Content-Length: 181104
Origin: http://127.0.0.21
Connection: close
Referer: http://127.0.0.21/vul/unsafeupload/clientcheck.php
Cookie: PHPSESSID=2057hagpp9jp80g50uehr6gacq
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Sec-GPC: 1
-----------------------------9501037142524743667159495619
Content-Disposition: form-data; name="uploadfile"; filename="Snipaste_2023-11-30_14-48-58.png"
Content-Type: image/png
请求头中 Content-Type 存在以下特征:
-
multipart/form-data(表示该请求是一个文件上传请求) -
存在 boundary 字符串(作用为分隔符,以区分POST数据)
POST的内容存在以下特征:
-
Content-Disposition -
name -
filename -
POST 中的 boundary 的值就是 Content-Type 的值在最前面加了两个 –
客户端 javascript 检测 (通常为检测文件扩展名)
在网页上写一段 Javascript 脚本,效验文件上传的后缀名,使用黑/白名单形式,如果上传文件的后缀不被允许,则会弹窗告知,此时文件上传的数据包并没有发送到服务端,所有过程都在前端完成
服务端 MIME 类型检测 (检测 Content-Type 内容)
MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的因特网标准
Content-Type(内容类型),一般是指网页中存在的 Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件,简单来说,Content-Type 标头告诉客户端实际返回的内容的内容类型
常见的媒体格式类型如下:
通过检测 MIME 判断用户上传的文件是不是业务所需的文件后缀,如果不是,则不允许上传该文件
服务端目录路径检测 (检测跟 path 参数相关的内容)
主要是检测路径是否合法:
-
路径格式:路径需要符合操作系统的文件系统规则 -
路径安全:路径不能指向系统关键目录或文件,以防止重要数据被覆盖或泄露 -
路径权限:上传文件的目录应该具有写入权限,但不应该具有执行权限,以防止上传的文件被执行
服务端文件扩展名检测 (检测跟文件 extension 相关的内容)
常规情况下检查filename
字段,一般分为黑/白名单两种形式:
-
白名单:只允许上传某些类型后缀 -
黑名单:不允许上传某些类型后缀
相当于把刚才在前端实现的判断在后端复刻了一遍,不过实现方式不同,相应的绕过方式也不同
服务端文件内容检测 (检测内容是否合法或含有恶意代码)
幻数检测
什么是幻数(Magic number)
幻数,作为文件格式的标志存在于文件的开头。它可以用来标记文件或者协议的格式,很多文件都有幻数标志来表明该文件的格式,以下是常见图片格式的幻术
JPEG 文件头:FFD8FF
PNG 文件头:89504E47
GIF 文件头:47494638
同时,一些文件也存在文件尾部的幻数
JPG 文件:FFD9
PNG 文件:AE 42 60 82
幻数检测浅析
幻术检测主要是检测文件内容开始处的文件幻数,当我们需要绕过这类检测时,只需把可上传文件类型的幻数拼接到我们想上传文件(一般是木马)的文件开头就可以,此外还可以在文件结尾加上格式特有后缀,增加隐匿性
此外,幻数检测还可以使用 JS 在前端实现,原理同样,这里不再赘述
exif_imagetype() 函数检测
exif_imagetype()
函数是 PHP 中的一个函数,从函数名便可以看出,它是一个检验图片类型的函数,它以 filename 作为参数,读取图像的第一个字节并检查其签名,如果发现了恰当的签名则返回一个对应的常量,否则返回FALSE
此外,exif_imagetype()
函数还提供了一些定义常量,我们可以根据回显的数字判断文件类型,常见图片类型常量如下
1:IMAGETYPE_GIF
2:IMAGETYPE_JPEG
3:IMAGETYPE_PNG
简单来说,exif_imagetype()
函数依然是检查文件头,但与幻数检测的原理和实现方式都不同
getimagesize() 函数检测
getimagesize()
函数用于获取图像大小及相关信息,成功返回一个数组,失败则返回FALSE
,本质上还是幻数检测,只是使用特定的函数进行实现,这里不再赘述
文件加载检测(图像渲染测试)
文件加载检测一般是调用API 或函数去进行文件加载测试,对待加载测试的攻击方式依然是代码注入绕过,简单来说文件加载检测依然是对文件本身的片段进行校验,与前面几种方法差别不大,但由文件加载延申出来的二次渲染绕过难度较大
二次渲染相当于把原本属于图像数据的部分抓了出来,再用自己的 API 或函数进行重新渲染,也就是说我们常规的注入手段在渲染的过程中被过滤掉了,判断是否为二次渲染的明显的特征就是上传前和上传后的图片的恶意代码是否被过滤,如被过滤即存在二次渲染行为
总结
文件上传这类漏洞原理较为简单,但在实战中千变万化,需要具体情况具体分析,若想要熟练掌握此漏洞,个人建议从检测角度入手,清楚网站是如何对上传的文件进行检测后,绕过的思路自然便会浮现,最后附上此漏洞的专项练习靶场和个人认为值得学习的文章
-
upload-labs -
Upload-labs 1-21关 靶场通关攻略 -
文件上传漏洞学习 -
浅析文件上传漏洞
原文始发于微信公众号(天禧信安):【Pikachu 靶场精讲】Unsafe Fileupload—前置知识
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论