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