upload-labs是一个使用php语言编写的,专门收集渗透测试和CTF中遇到的各种上传漏洞的靶场。每一关都包含着不同上传方式。 [TOC] 20关都练会了那么也就基本掌握了php文件上传漏洞的各种方法了 项目地址:***.com 搭建了两个环境,分别是:
- docker安装的linux环境
- 绿色安装的win2003版本
pass01:前端js限制(双杀)
- 适合操作系统 windows、linux通用,不区分系统 不区分web中间件
- 如何测试 提交错误后缀文件后,控制台无数据交互产生,说明文件类型验证是通过前端页面验证的
- 如何绕过 直接禁用js、修改页面函数、bp抓包
pass02:mime类型限制(双杀)
- 适合操作系统 windows、linux通用,不区分系统 不区分web中间件
- 如何测试
上传php文件抓包,将
Content-Type: application/octet-stream改为Content-Type: image/jpeg后提交 能提交成功,且能正常访问,说明只是限制了mime文件类型 - 如何绕过 可以直接抓包修改mime类型 也可先将php文件改名为jpg,上传抓包后将文件名改回去
pass03:文件后缀限制不严格(双杀)
- 适合操作系统 windows、linux通用,不区分系统 不区分web中间件
- 如何测试 错误提示:“提示:不允许上传.asp,.aspx,.php,.jsp后缀文件! ” 上传文件后,文件会被改名,但后缀不变
- 如何绕过 以php为例,不光是php后缀可执行,还有php2、php3、php4、php5都可执行 所以文件后缀验证不严格时,可以用这些后缀绕过
pass04:文件后缀限制不严格(双杀)
- 适合操作系统 windows、linux通用,不区分系统 仅限于web中间件为apache,且
- mod_rewrite模块开启
- AllowOverride All
- 如何测试
上传php各种后缀均无效,说明文件后缀过滤更严格了
发现web中间件是apache,但未过滤
.htaccess格式文件 - 如何绕过
上传一个htaccess文件,文件中允许任何文件当php文件执行
然后再将
123.php改名为123.jpg后上传,访问改文件可执行phpinfo - htaccess文件内容
$ cat 1.htaccess <FilesMatch ""> SetHandler application/x-httpd-php </FilesMatch>htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
pass05:大小写限制不严格(仅win)
- 适合操作系统 仅windows可用,因为windowns不区分文件写,而linux会严格区分
- 如何测试
各种后缀限制严格了,包括
.htaccess格式 但是大小写为区分,且上传的大写文件名不现在 - 如果绕过
将
123.php改为123.phP后上传,上传后可正常访问使用
pass06:空格绕过(仅win)
- 适合操作系统 仅windows可用,在windows下,如果新建文件“123.php ”,实际会被存储为”123.php“
- 如何测试 各种后缀限制严格,大小写也不行,可以考虑windows特性绕过
- 为什么能绕过 通过分析源码,发现是代码中没有处理文件后缀中的空格,导致在windows下的该漏洞
pass07:空格加点绕过(仅win)
- 适合操作系统 仅windows可用,在windows下,如果新建文件“123.php .”,实际会被存储为”123.php“
- 如何测试 各种后缀限制严格,大小写也不行,可以考虑windows特性绕过
- 为什么能绕过 通过分析源码,发现代码对文件名首尾进行了去空操作,但未处理文件名后的点
pass08: ::$DATA绕过(仅win)
- 适合操作系统
仅windows可用,利用了Windows文件流特性绕过
如果
文件名+"::$DATA",会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持"::$DATA"之前的文 - 如何测试 各种后缀限制严格,大小写也不行,可以考虑windows特性绕过
- 为什么能绕过 通过分析源码,发现是代码中过滤了点和前后空格,但未处理DATA流,导致在windows下的该漏洞
pass09:点空格点绕过(仅win)
- 适合操作系统 仅windows可用,在windows下,如果新建文件“123.php. .”,实际会被存储为”123.php“
- 如何测试 各种后缀限制严格,大小写也不行,可以考虑windows特性绕过
- 为什么能绕过
通过分析源码,发现代码对文件名首尾进行了去空,也限制了DATA流和空格加点,但未处理
. .这种形式
pass10:关键字替换绕过(双杀)
- 适合操作系统 不区分操作系统,通用
- 如何测试 上传文件发现文件后缀中若包含php等关键字,这些关键字会被替换为空,典型的字符替换
- 如何绕过
仅需将上传的文件
123.php,改为123.pphphp,中间的php被替换为空后,剩下的文件名变回123.php
pass11:可控目录00截断(双杀)
- 适合操作系统 不限操作系统(linux搭不起低版本环境,待验证),但对中间件有要求
- php版本要小于5.3.4
- php.ini中的配置
magic_quotes_gpc=OFF - 如何测试 上传截包后,发现上传路径在head头中可控,可以尝试00截断
- 如何绕过
截包后,head中的路径
../upload/改为../upload/1.php%00,提交 回显上传路径为***.com但实际上文件为***.com,后续被截断了
pass12:可控目录00截断(双杀)
- 适合操作系统 不限操作系统(linux搭不起低版本环境,待验证),但对中间件有要求
- php版本要小于5.3.4
- php.ini中的配置
magic_quotes_gpc=OFF - 如何测试 上传截包后,发现上次路径在body中可控,可以尝试00截断 上一个pass的%00不能成功,尝试另外一种00截断
- 如何绕过
截包后,body中的路径
../upload/,改为../upload/1.php切换为16进制,找到php代表70 68 70将后一个16进制数改为00 再上传,结果同pass11一样
pass13:文件包含加图片马(双杀)
本pass提供远程文件包含漏洞,只需要想办法上传图片马
1. 适合操作系统
不限操作系统
2. 如何测试
页面做了白名单,仅允许上传gif、jpg、png三种文件
尝试直接将123.php改名为123.jpg后上传拒绝
说明后端重新不光判断后缀名,还用了检测函数检测文件类型
3. 如何绕过
用copy命令做个真正的图片马即可copy 1.jpg/b + 1.php/b 1.jpg
或者修改包头,添加gif图片头:GIF89a
4. 绕过后分析:
分析源码,是截取文件前两个字符,判断文件类型是否是gif、jpg、png或位置
pass14:文件包含加图片马(双杀)
本pass提供远程文件包含漏洞,只需要想办法上传图片马 1. 绕过方法 同pass13,图片马或改包头都可以 2. 绕过后分析 分析源码,是用了getimagesize函数检测文件是否是图片,其实也是看包头
pass15:文件包含加图片马(双杀)
本pass提供远程文件包含漏洞,只需要想办法上传图片马 1. 绕过方法 同pass13,图片马或改包头都可以 2. 绕过后分析 分析源码,是用了exif_imagetype()函数检测文件是否是图片,其实也是看包头
pass16:文件包含加图片马(双杀)
本pass提供远程文件包含漏洞,只需要想办法上传图片马
1. 如何测试
发现图片马可以上传,改包头的文件不能上传
上传的图片,会被函数重写一次,导致图片马失效
2. 如何绕过
针对这种会重写的功能,思路是多尝试几个图片,对比上传前后图片,找出里面未变化的部分
将此部分改为一句话马再上传(我为实现)
3. 源码分析
先检测了文件后缀与检查了mime类型是否匹配
再根据图片类型,调用专门的检测函数如imagecreatefromjpeg检测是否是该型文件
最后用strval函数重写图片文件
pass17:先存再检再删(双杀)
- 源码分析 本pass困难,分析源码得知是先将文件存储,再检测该文件是否合法,不合法的删除。
- 如何绕过 既然会先存储,那么通过程序快速重传这个文件,达到一直可以访问的目的
- 麻蛋,没成功,改源码sleep才行
pass18:先存再检再改名(双杀)
- 利用条件 中间件为apache,且存在解析漏洞
- 源码分析 本pass困难,还是分析源码,发现会先将文件存放,再改名
- 如何绕过
截包,将
123.php改为123.php.7z,然后连续重复提交 直到提示:"文件已经被上传,但没有重命名" 再利用解析漏洞访问该文件即可
pass19:文件名00截断(双杀)
- 适合操作系统 不限操作系统(linux搭不起低版本环境,待验证),但对中间件有要求
- php版本要小于5.3.4
- php.ini中的配置
magic_quotes_gpc=OFF - 如何测试
页面需要上传文件名,且需要输入文件上传后的新文件名,参数可控
上传截包后,将
upload-19.jpg改为upload-19.php尝试00截断,%00不能成功,16进制00截断成功 也可以利用windows特性,在文件名后加点,如upload-19.php.
pass20:数组文件名绕过(仅win)
- 适合操作系统 仅windows系统
- 源码分析检查过程 先检查mime类型,只能为jpeg、png、gif 再设置文件名,若将要保存的文件名存在就用,若为空就用上传文件的文件名 再检查文件名是否为数组,不是数组则用点号分割为数组 再检查文件名数组的最后值(即文件后缀)是否是jeg、png、gif 最后再将数组第0位与数组总个数-1位(正常情况下即后缀)重新用点拼接为新文件名并保存文件
- 绕过思路
需要绕过【判断是否为数组】这一步,那么需要提交的时候就提交为数组
一个很正常的数组(如
a=["123",".","php"]),其a[-1]=a[count(a)-1]手动指定数组下标(如a[0]="123",a[2]="php"),则a[-1]!=a[count(a)-1] - 如何绕过
截包后,将
seve_name复制一份 将第一份save_name的文件名改为UPLOAD-20.php,用数组0 将第二份save_name的文件名改为jpg,用数组除1外的任何下标 组后构造出来的文件名为UPLOAD-20.php.,结合windows特性绕过了 ```sh #原始包################# -----------------------------20346769815764617441374724817 Content-Disposition: form-data; name="upload_file"; filename="phpinfo.php" Content-Type: image/jpeg
-----------------------------20346769815764617441374724817 Content-Disposition: form-data; name="save_name"
upload-20.jpg
#改名,复制,加数组后的包############# -----------------------------20346769815764617441374724817 Content-Disposition: form-data; name="upload_file"; filename="phpinfo.php" Content-Type: image/jpeg
-----------------------------20346769815764617441374724817 Content-Disposition: form-data; name="save_name[0]"
upload-20.php -----------------------------20346769815764617441374724817 Content-Disposition: form-data; name="save_name[-1]"
jpg -----------------------------20346769815764617441374724817 ```