portswigger 文件上传漏洞
知识储备
文件上传漏洞的原理
知其然,知其所以然
简单的说,文件上传漏洞发生在具有文件上传功能的模块,文件上传后总是会被保存在服务器的某个地方,当文件上传操作与保存操作处理不当时,文件上传漏洞就由此产生。
例如,上传的文件可以是一个可执行文件,该文件通过各种手段被上传后再想办法执行,攻击者则会获得webshell从而操作 web 服务。
文件上传漏洞的危害
- 服务器被控制
- 客户端被劫持
- 敏感信息泄露
- 恶意文件托管
- 未经授权操作
- 拒绝服务攻击
简单记忆串联:一旦通过文件上传漏洞上传了可执行文件并执行从而获得 webshell 后,hack 可以控制服务器,从而未经授权进行操作、获取敏感信息、甚至托管恶意文件,
更不用说访问服务器的客户端会被劫持,而最简单的,hack 可以让该服务器挂掉拒绝服务。
常见的文件上传漏洞检测方法与绕过手段
客户端检测
- 前端验证
原理:在网页上写一段Javascript脚本,校验上传文件的后缀名,有白名单形式也有黑名单形式。
绕过:如果是使用 js 验证的可以尝试禁用 js,或者先修改文件类型然后通过 burp 抓包再把文件类型改回来
服务器端检测
- MIME类型检测
原理:检测Content-Type
绕过:修改Content-Type,或者上传.png(允许的类型),然后再抓包修改 filename 改为原来需要的后缀
- 目录路径检测
原理:检测 path 参数相关内容判断路径是否合法等
绕过:使用0x00截断((但需要php5.3.4以下,以及magic_qoute_gpc为off)
- 文件内容检测
文件幻数检测(文件开头)
原理:幻数 magic number,它可以用来标记文件或者协议的格式,很多文件都有幻数标志来表明该文件的格式。
.jpg FF D8 FF E0 00 10 4A 46 49 46
.gif 47 49 46 38 39 61
.png 89 50 4E 47
绕过:
方法1,上传一句话,捉包,加上图片类型的文件头;
方法2,上传图片马,改后缀,或者直接在可上传的图片内容后加上一句话木马。
文件加载检测(代码注入)
原理:
一种是对上传的图片文件进行渲染/加载测试;
还有是对上传的图片文件进行二次渲染。
绕过:
对于第一种:使用代码注入的方法,使用winhex在不破坏文件本身的渲染情况下找一个空白区进行填充代码,一般会是图片的注释区;
对于第二种:对文件加载器进行攻击,常见的就是溢出攻击;上传自己的恶意文件后,服务器上的文件加载器会主动进行加载测试,加载测试时被溢出攻击执行 shellcode,比如 access/mdb 溢出。
- 文件扩展名检测
原理:
文件拓展名检测主要分为黑名单检测和白名单检测的方式。
黑名单,即在程序中定义了特定的文件后缀名为不可上传的;
白名单,即在程序中定义了允许上传的后缀名。
绕过:
文件名大小写绕过
如:. Php…;Jsp;*.aSP *.AsP…
名单列表绕过
如:
php2,php3,php5,phtml; aspx、ascx、
ashx、cer、asa;
特殊文件名绕过
windows文件名最后不能有.或空格,可设为 *.php. 或 *.php+
0x00截断绕过
如:*.php(0x00).jpg 或 *.php%00.jpg
利用文件包含漏洞
由于PHP包含的所有文件都会以PHP文件的形式来执行,所以当网站同时存在文件包含漏洞和文件上传功能时,即使上传处不存在上传漏洞,依旧可以结合包含漏洞获得webshell。
利用服务器解析漏洞
Apache
Apache(1.x,2.x)解析文件的原则:Apache在解析文件名的时候是从右向左读,如果遇到不能识别的扩展名则跳过,rar、gif等扩展名是Apache不能识别的,因此就会直接将类型识别为php,从而达到了注入php代码的目的。
IIS
IIS6.0下主要是有两个解析漏洞:
一个是目录解析,如果网站目录中有一个 *.asp/ 的文件夹,那么该文件夹下面的一切内容都会被 IIS 当作 asp 脚本来执行,如/xx.asp/xx.jpg;
另一个就是文件解析,IIS在解析文件名的时候会将分号后面的内容丢弃,如xx.asp;.jpg,可通过此漏洞上传shell,对服务器危害较大。
IIS6.0 默认的可执行文件除了asp还包含这三种 :
/test.asa
/test.cer
/test.cdx
IIS 7.0/7.5/Nginx < 8.03,默认 Fast-CGI 开启。如果直接在 url 中图片地址(.jpg)后面输入/.php,会把正常图片解析为 php 文件。本质:PHP CGI的漏洞,在PHP的配置文件中有一个关键的选项cgi.fix_pathinfo在本机中位于C:wampbinphpphp5.3.10php.ini,默认是开启的,当URL中有不存在的文件,PHP就会向前递归解析。
Nginx
空字节漏洞,影响版本:0.5、0.6、0.7<=0.7.65、0.8<= 0.8.37
也就是当Fast-CGI执行php时,http://127.0.0.1/1.jpg.php 会把1.jpg文件(木马文件)当做php文件来执行。
.htaccess文件攻击
.htaccess文件
.htaccess文件(或者"分布式配置文件"),全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
若是如下的.htaccess配置,则可以令所有的文件都以PHP文件来执行:
<FileMatch "a.jpg"> SetHandler application/x-httpd-php </FilesMatch>
其他检测机制
- 先上传后检测
原理
一开始允许任意上传文件,上传后再检测,若是恶意文件则删除;
绕过
条件竞争绕过,通过上传一个内容为生成一句话木马的脚本,由于服务器检测出文件为恶意文件并删除存在极短的时间差,利用burpsuite或其他工具不断的上传和访问该文件,若是竞争成功,则会生成一句话木马从而躲避了服务器的检测。
文件上传漏洞防御方案
- 文件类型、后缀、大小、路径检测
- 前端验证:js 验证文件扩展名、大小
- 后端检测:MIME 类型,设置白名单、重命名上传文件
- 文件内容解析
- 文件上传目录修改权限
- 无执行权限
- 读写权限分离
- 最小权限运行服务器
- 优化php.ini配置
靶场通关
靶场链接
第一关
可以看到第一关的描述是上传一个 php 文件然后获取/home/carlos/secret中的通关密码
- 首先找到文件上传点
点击 My account 使用改题目提供的账号密码 wiener:peter 登录即可找到上传点
- 上传一个 php 文件试试看
<?php echo file_get_contents('/home/carlos/secret'); ?>
// file_get_contents() 把整个文件读入一个字符串中
发现上传成功,说明目前上传的文件没有被限制
- 访问(执行)刚刚上传的文件
由于刚刚上传的是个「头像」,所以我们回到个人主页看看这个「头像」保存在哪里
使用 F12 大法轻松找到
访问该链接
可以发现访问成功,说明文件确实是成功上传并且可以利用的
- 提交
复制ofpXe8nN1aQxTJa77y3in64iinYKNMyD
点击 submit solution 并提交
第二关
第二题的要求和第一题的一样,但是从题目上看就知道对「文件上传」加了限制,需要修改文件类型
- 首先我们测试一下 php 文件能不能上传成功
依旧是先登录 wiener:peter 然后上传文件:
<?php echo file_get_contents('/home/carlos/secret'); ?>
// file_get_contents() 把整个文件读入一个字符串中
发现不行,并且提示文件类型不符合(白名单规则)
- 使用 burp 抓包修改请求头信息
我们回到上传页面,再次 upload,通过 burp 的拦截功能修改请求头信息
通过修改 Content-Type 属性的值,将其改为白名单内的类型:image/png
可以发现上传成功了
- 和题 1 一样访问(执行)上传的 php 文件并提交答案
第三关
题目提示是需要通过目录遍历来完成的
- 上传 php 文件
和 1、2 关一样,我们先上传文件:
<?php echo file_get_contents('/home/carlos/secret'); ?>
// file_get_contents() 把整个文件读入一个字符串中
可以发现文件轻松上传了
- 找到文件所在处并执行该文件
按照前面两关的思路,我们先找到该图片显示的地方,试图找到一些路径的线索
但当我们通过 F12 找到路径并访问时,却发现上传的文件以文本的形式显示了,并没有被执行
说明访问该目录下的文件,回显信息是以文本的形式展现的,并不会直接执行该文件
因此我们考虑把文件不上传到这而是上传到别处,比如它的父级目录
+使用 burp 修改文件上传目录
先把上传文件的 POST 请求包抓到并送去 repeater
在 Content-Disposition 中找到 filename,并将其值添加../
发现似乎路径并没有被修改,../被吞掉了一样
对/进行 URL 编码
发现../显示了出来
我们再按照前几关的方法,通过 F12 找到路径,并且访问一下该文件
ok,php 文件执行成功,可以提交答案了
第四关
题目描述信息是通过绕过黑名单进行文件上传
- 先直接上传 php 文件测试一下
可以发现,我上传的 bpup04.php 文件上传失败,并提示不能上传 php 文件
- 使用 burp 尝试绕过文件类型限制,再上传.htaceess使该文件以 php 的形式执行
我们将刚刚发送的 POST 请求发送到 repeater
修改 Content-Disposition,把filename值改为 bpup04.png
修改 Content-Type,把 text/php 改为 image/png
发送
上传成功
上传一个.htaccess文件(命名就是.htaccess)
<FilesMatch "bpup04.png">
SetHandler application/x-httpd-php
AddHandler php5-script .png
</FilesMatch>
- 访问该文件
可以提交答案了
第五关
通过混淆文件扩展名上传
- 尝试一下
直接上传 php 文件,不行
修改成Content-Type: image/png 不行
上传.htaccess文件,不行
初步判断这里使用了白名单
- 使用%00截断绕过
如图修改参数
上传成功
访问一下
可以提交了
第六关
这关检测的是上传文件开头,查看是否符合要求
- 尝试一下
直接上传个 php 文件,不行
同时这里提到了not a valid image
尽管我们把文件后缀改成.png,修改Content-Type也是无效的
说明这里确实是检测了上传文件
我们再尝试一下把普通的 png 图片修改后缀为 php 文件再上传
发现上传成功,也就是说这里并没有其他的限制,只是单纯地检测文件上传内容,而且应该使用了文件幻数检测
- 伪造含有图片开头信息的 php 文件并上传
在命令行使用该命令将一张普通的图片和我们需要的 php 文件输出为含有图片文件开头信息标志的 php 文件
cat aaa.png bpup06.php > bpupp06.php
我们把生成的文件上传
上传成功
- 访问文件
最后面一小串就是我们需要的答案了
第七关
题目描述是使用条件竞争绕过,通过上传一个内容为生成一句话木马的脚本,由于服务器检测出文件为恶意文件并删除存在极短的时间差,利用burpsuite或其他工具不断的上传和访问该文件,若是竞争成功,则会生成一句话木马从而躲避了服务器的检测
<?php echo file_get_contents('/home/carlos/secret'); ?>
上传肯定是失败的了
我们再随便上传一个 png 图片,再访问这个图片
由此我们得到 POST 请求和 GET 请求
我们先在 Burp 的 BAPP下载 Turbo Intruder
然后把上传 php 文件的 POST 请求发送到 Turbo Intruder
我们再在 Turbo Intruder 下方构造脚本,并把 POST 请求和 GET 请求内容粘贴过来
需要注意的是 POST 请求为上传的php文件请求,GET 为访问该 php 文件的请求(修改头部为GET /files/avatars/bpup07.php HTTP/1.1)
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint, concurrentConnections=10,)
request1 = '''你的POST请求,不需要把三引号去掉,最后一行需要有一行空行'''
request2 = '''你的GET请求,不需要把三引号去掉,最后一行需要有一行空行'''
# the 'gate' argument blocks the final byte of each request until openGate is invoked
engine.queue(request1, gate='race1')
for x in range(5):
engine.queue(request2, gate='race1')
# wait until every 'race1' tagged request is ready
# then send the final byte of each request
# (this method is non-blocking, just like queue)
engine.openGate('race1')
engine.complete(timeout=60)
def handleResponse(req, interesting):
table.add(req)
点击底部的Attack
状态为 200 的就是答案了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!