文件上传

知识点

首先来介绍一下文件上传漏洞及其原理

简介

1、文件上传漏洞简介

文件上传漏洞是指由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致的用户可以越过其本身权限向服务器上上传可执行的动态脚本文件。

  • 这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。
  • 这种攻击方式是最为直接和有效的,“文件上传”本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。
  • 如果服务器的处理逻辑做的不够安全,则会导致严重的后果。

文件上传漏洞本身就是一个危害巨大的漏洞,WebShell更是将这种漏洞的利用无限扩大。大多数的上传漏洞被利用后攻击者都会留下WebShell以方便后续进入系统

2、文件上传漏洞原理:

在文件上传的功能处,若服务端脚本语言未对上传的文件进行严格验证过滤,导致恶意用户上传恶意的脚本文件时,就有可能获取执行服务端命令的能力,这就是文件上传漏洞

文件上传漏洞对Web应用来说是一种非常严重的漏洞。

  • 一般情况下,Web应用都会允许用户上传一些文件,如头像、附件等信息
  • 如果Web应用没有对用户上传的文件进行有效的检查过滤,那么恶意用户就会上传一句话木马Webshell,从而达到控制Web网站的目的。

img

3、文件上传漏洞的高危触发点

存在文件上传功能的地方都有可能存在文件上传漏洞,比如相册、头像上传,视频、照片分享。论坛发帖和邮箱等可以上传附件的地方也是上传漏阔的高危地带,另外像文件管理器这样的功能也有可能被攻击者所利用。

值得注意的是,如果移动端也存在类似的操作的话,那么相同的原理,也存在文件上传漏洞的风险。

img

前端检测

  • 主要是通过javascript代码进行检测,非常容易进行绕过。

1.原理:

  Web应用系统虽然对用户上传的文件进行了校验,但是校验是通过前端javascript代码完成的。

  • 由于恶意用户可以对前端javascript进行修改
  • 或者是通过抓包软件**篡改上传的文件**,就会导致基于js的校验很容易被绕过。

img

2.判断:

如何判断当前页面使用前端is的验证方式:

前端验证通过以后,表单成功提交后会通过浏览器发出─条网络请求

  • 如果前端验证不成功,则不会发出这项网络请求
  • 可以在浏览器的网络元素中查看是否发出了网络请求。

3.绕过方法:

  • 删除或者禁用js:火狐浏览器-->about:config-->JavaScriptenable-false (ajax)
  • 使用代理上传文件,Burp Suite;上传符合要求的文件类型,抓包修改文件类型

3.1 删除js绕过:

直接删除代码中onsubmit事件中关于文件上传时验证上传文件的相关代码即可:

例如这个例子:

img

  • 或者可以不加载所有js
  • 还可以将html源码copy一份到本地,然后对相应代码进行修改,本地提交即可。

3.2 burpsuite抓包

直接用burpsuite拦截

  • 发送到repeater后将文件头类型修改
  • 或者修改MINI类型即可

后端检测

一.后缀名检测漏洞:

大致原理:

 通常是针对文件的扩展名后缀进行检测,主要是通过黑白名单进行过滤检测,

  • 名单:如果不符全过滤规则则不允许上传
  • 名单:只允许符合规定后缀名的文件上传

img

1.黑名单

1.1原理:

 黑名单检测:一般有个专门的 blacklist 文件,里面会包含常见的危险脚本文件。 例如: fckeditor 2.4.3 或之前版本的黑名单:

img

1.2 绕过方法:
1.2.1解析漏洞
  • .htaccess文件解析漏洞- apache解析漏洞
  • IIS7.0 | IIS7.5 | Nginx的解析漏洞
  • IIS6.0解析漏洞
1.2.2截断上传
  • 截断类型:PHP%00截断
  • 截断原理:由于00代表结束符,所以会把00后面的所有字符都截断
  • 截断条件:PHP版本小于5.3.4,PHP的magic_quotes_gpc为OFF状态
1.2.3大小写绕过

比如:aSppHp之类。

1.2.4黑名单扩展名的漏网之鱼

比如: asacer之类 asp: asa cer aspx jsp: jspx jspf php: php php3 php4 php5 phtml pht exe: exee

1.2.5利用Windows的命名机制

shell.php. shell.php空格 shell.php:1.jpg shell. php::$DATA shell.php:1.jpg 在windows中,后缀名后面的点和空格都会被删除掉。

1.2.6双写绕过

有时候在检测时,后台会把敏感字符替换成空格,这个时候,我们可以使用双写进行绕过。比如:pphphp

2.白名单:

2.1原理:

​ 白名单检测:一般有个专门的 whitelist 文件,里面会包含的正常文件:Jpg png GIF

2.2绕过方法:
2.2.1解析漏洞
  • .htaccess文件解析漏洞
  • apache解析漏洞
  • IIS7.0 | IIS7.5 | Nginx的解析漏洞
  • IIS6.0解析漏洞
2.2.2截断上传
  • 截断类型:PHP%00截断
  • 截断原理:由于00代表结束符,所以会把00后面的所有字符都截断
  • 截断条件:PHP版本小于5.3.4,PHP的magic_quotes_gpc为OFF状态

二.MIME检测:

1.什么是MIME:

MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。

绕过上传限制-服务端绕过MIME检测:

img

2. 常见的MIME类型:

  • text/plain (纯文本)

  • text/html (HTML文档)

  • text/javascript (js代码)

  • application/xhtml+xml (XHTML文档)

  • image/gif (GIF图像)

  • image/jpeg (JPEG图像)

  • image/png (PNG图像)

  • video/mpeg (MPEG动画)

  • application/octet-stream (二进制数据) application/pdf (PDF文档)

3. 检测方式:

    在文件上传过程中,服务端会针对我们的上传的文件生成一个数组,这个数组其中有一项就是这个文件的类型file_type;服务端对文件进行检测时,就是通过检测脚本中的黑白名单和这个数组中的file_type进行对比,如果符合要求就允许上传这个文件。

img

4. MIME绕过的原理:

  • 部分Web应用系统判定文件类型是通过content-type字段
  • 黑客可以通过抓包,将content-type字段改为常见的图片类型
  • 如改成image/gif,从而绕过校验。

三.00截断:

1.原理:

 虽然web应用做了校验,但是由于文件上传后的路径用户可以控制

  • 攻击者可以利用手动添加字符串标识符0X00的方式来将后面的拼接的内容进行截断,导致后面的内容无效
  • 并且后面的内容又可以帮助我们绕过黑白名单的检测。

2.绕过思路:

  在C语言中,空字符有一个特殊含义,代表字符串的拼接结束。这里我们使用的是php语言,属于高级语言,底层靠C语言来实现的,也就是说空字符的字符串拼接结束功能在PHP中也能实现。但是我们在URL中不能直接使用,这样会造成无法识别。

  • 我们通过查看ASCII对照表,发现ASCII对照表第一个就空字符,它对应的16进制是00
  • 这里我们就可以用16进制的00来代替空字符,让它截断后面的内容。

使用burpsuite进行抓包,因为这里是通过URL进行传递的文件上传后存储路径,所以需要对16进制00进行URL编码,编码的结果就是%00,通过这种方式,就可以%00截断后面的内容,让拼接的文件名不再进行生效:

img

四.文件头检测漏洞:

1.原理:

  在每一个文件(包括图片,视频或其他的非ASCII文件)的开头(十六进制表示)实际上都有一片区域来显示这个文件的实际用法,这就是文件头标志。我们可以通过16进制编辑器打开文件添加服务器允许的文件头以绕过检测

2.常见的文件头:

注意:下面的文件头的格式是16进制的格式:

  • gif:47 49 46 38 39 61

  • png:89 50 4E 47 0D 0A 1A 0A

  • jpg:FF D8 FF E0 00 10 4A 46 49 46

3.操作

  • 在进行文件头绕过时,我们可以把上面的文件头添加到我们的一句话木马内容最前面,达到绕过文件头检测的目的。

五.内容检测图片马绕过:

1.漏洞原理:

 一般文件内容验证使用getimagesize函数检测,会判断文件是否是一个有效的文件图片.

  • 如果是,则允许上传
  • 否则的话不允许上传。

本实验就是将一句话木马插入到一个[合法]的图片文件当中,然后用webshell管理工具进行远程连接。

2.图片马制作:(重点)
  • 准备一张图片,这里为1.png

  • 一个一句话木马,记为2.php

  • 通过以下命令合成一个图片马3.png

命令如下:

1
2
3
copy 1.png/b + 2.php/a 3.php  
/b:指定以二进制格式复制、合并文件,用于图像或者声音类文件
/a:指定以ascii格式复制、合并文件用于txt等文本类文件

这样子就可以复制从而制作出图片木马了:

img

注:

这条命令的意思是:通过copy命令,把a.png图片文件,以二进制文件形式添加到a.php文件中,以ASCII文本文件形式输出为3.php文件。

3.解析图片马:

 一般解析图片马需要结合解析漏洞或者文件包含才能解析图片马

解析漏洞

一..htaccess文件解析漏洞:

1.漏洞利用前提::

  web具体应用没有禁止.htaccess文件的上传,同时web服务器提供商允许用户上传自定义.htaccess文件

2.原理:

.htaccess文件(或者"分布式配置文件") ,全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法

​ 也就是在一个特定的文档目录中放置一个包含一个或多个指令的文件,以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。

3 利用方式:

上传覆盖.htaccess文件,重写解析规则,将上传的带有脚本马的图片以脚本方式解析。

4 .htaccess文件内容:

.htaccess文件解析规则的增加,是可以按照组合的方式去做的,不过具体得自己多测试。

1
2
3
4
解释<FilesMatch "evil.gif">
SetHandler application/x-httpd-php #在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行
AddHandler php5-script .gif #在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行
</FilesMatch>

二.Apache解析漏洞:

1 漏洞原理:

Apache 解析文件的规则是从右到左开始判断解析,如果后缀名不可识别文件解析,就再往左判断。比如test.php.a.b的“.a”和“.b”这两种后缀是apache不可识别解析,apache就会把test.php.a.b解析成test.php

2 影响版本:

apache 1.x apache 2.2.x

3.IIS6.0`解析漏洞:

IIS6.0解析漏洞分两种: 1、目录解析: 以xx.asp命名的文件夹里的文件都将会被当成ASP文件执行。 2、文件解析: xx.asp;.jpg 像这种畸形文件名在;后面的直接被忽略,也就是说当成xx.asp文件执行。

IIS6.0 默认的可执行文件除了asp还包含这三种 .asa .cer .cdx

三.IIS7.0 | IIS7.5 | Nginx的解析漏洞:

1.原理:

Nginx拿到文件路径(更专业的说法是URI/test.jpg/test.php后,一看后缀是.php,便认为该文件是php文件,转交给php去处理。php一看/test.jpg/test.php不存在,便删去最后的/test.php,又看/test.jpg存在,便把/test.jpg当成要执行的文件了,又因为后缀为.jpgphp认为这不是php文件,于是返回Access denied。   这其中涉及到php的一个选项:cgi.fix_pathinfo,该值默认为1,表示开启。开启这一选项PHP可以对文件路径进行修理

举个例子,当php遇到文件路径/1.jpg/2.txt/3.php时

  • 若/1.jpg/2.txt/3.php不存在,则会去掉最后的/3.php,
  • 然后判断/1.jpg/2.txt是否存在,
  • 若存在,则把/1.jpg/2.txt当做文件/1.jpg/2.txt/3.php
  • 若/1.jpg/2.txt仍不存在,则继续去掉/2.txt,以此类推。

2.漏洞形式:

1
www.xxxxx.com/UploadFiles/image/1.jpg/1.php

四.另外两种解析漏洞:

1
www.xxxxx.com/UploadFiles/image/1.jpg%00.php` `www.xxxxx.com/UploadFiles/image/1.jpg/%20\0.php

条件竞争漏洞

  条件竞争漏洞是一种服务器端的漏洞,由于服务器端在处理不同用户的请求时是并发进行的,因此,如果并发处理不当或相关操作逻辑顺序设计的不合理时,将会导致此类问题的发生。

上传文件源代码里没有校验上传的文件,文件直接上传,上传成功后才进行判断:如果文件格式符合要求,则重命名,如果文件格式不符合要求,将文件删除。

由于服务器并发处理(同时)多个请求,假如a用户上传了木马文件,由于代码执行需要时间,在此过程中b用户访问了a用户上传的文件,会有以下三种情况:

  • 访问时间点在上传成功之前,没有此文件。
  • 访问时间点在刚上传成功但还没有进行判断,该文件存在。
  • 访问时间点在判断之后,文件被删除,没有此文件。

二次渲染漏洞

1.二次渲染原理:

        在我们上传文件后,网站会对图片进行二次处理(格式、尺寸要求等),服务器会把里面的内容进行替换更新,处理完成后,根据我们原有的图片生成一个新的图片并放到网站对应的标签进行显示。

2.绕过:

​ 配合文件包含漏洞: 将一句话木马插入到网站二次处理后的图片中,也就是把一句话插入图片在二次渲染后会保留的那部分数据里,确保不会在二次处理时删除掉。这样二次渲染后的图片中就存在了一句话,在配合文件包含漏洞获取webshell。

​ 可以配合条件竞争: 这里二次渲染的逻辑存在漏洞,先将文件上传,之后再判断,符合就保存,不符合删除,可利用条件竞争来进行爆破上传

3.判断

如何判断图片是否进行了二次处理?

  对比要上传图片与上传后的图片大小,使用16进制编辑器打开图片查看上传后保留了哪些数据,查看那些数据被改变。

靶场

CTFHub

CTFHub上面的题不多也不难,很适合基础入门

image-20240308230822227

无验证

  • 首先这是作为一道入门题,没有任何的过滤和验证

image-20240308231135690

  • 那我们就来练习一下蚁剑的使用以及一句话木马的制作吧
1
2
3
<?php
@eval($_POST['password']);
?>
  • 注意,这个木马很可能会被电脑本身的防火墙给拦截

  • 下面我们将一个木马文件上传

image-20240308231442039

  • 因为没有任何验证,所以可以直接提交

image-20240308231514349

image-20240308231537486

  • 将文件的相对路径复制到url后面(记得加个**/**)

image-20240308231710017

  • 然后用蚁剑打开

image-20240308232124558

  • 进入服务器可以看到我们刚才添加的php文件

image-20240308232224025

  • 说明文件上传成功了

image-20240308232443210

  • 返回上一级,就可以找到flag啦

image-20240308232510305

前端验证

  • 首先我们打开一个php文件并尝试上传,发现不能上传:

image-20240308233156622

  • 查看源代码可以知道,这是因为存在白名单验证,只有jpg、png、gif的文件才能通过验证
  • 我们可以通过抓包,上传一个jpg格式的文件(这个本质其实是是php木马文件修改后缀名而成),并在bp中改回它的后缀名 即php,也就是将其还原
  • 注意这里的顺序:

image-20240308233434772

  • 只要将文件名的后缀修改即可
  • 发送请求后发现文件成功上传了

image-20240308233518137

  • 将刚刚上传的文件的相对路径复制到url后面

image-20240308233609615

  • 打开蚁剑 复制url
  • 测试连接,连接通过说明上传成功且能通过蚁剑来访问

image-20240308233642534

  • 可以看到,这里是我们刚刚上传的文件
  • 其中包括一个用来抓包的jpg文件的修改后还原的php文件

image-20240308233702483

  • 同样的,在目录中寻找flag的位置

image-20240308233716887

  • 这样子就可以获取flag了·

image-20240308233730453

MINI验证

  • 进入靶场

image-20240308234921579

  • 用一个php文件上传看看,显然验证不通过

image-20240308234930327

  • 于是采用抓包的方式,先上传一个jpg文件:

image-20240308235123352

  • 通过burp suite进行抓包:
  • 可以看到 这里的MINI类型已经是jpg类型的了(因为我们上传的文件 虽然内容是eval 但是格式或者说后缀名是jpg类型的)

image-20240308235147505

  • 既然Content-Type(也就是MINI类型)符合,那么只要改回文件的后缀名,就可以将其还原成php木马了

image-20240308235220170

image-20240308235238281

  • 点击发送 可以看到文件已经上传成功 并回显了文件的相对路径

image-20240308235256044

  • 将相对路径复制到原来网页url的后面

image-20240308235357979

  • 打开蚁剑尝试连接

image-20240308235429091

  • 这样就进入它的服务端了,并且可以看到我们刚刚上传的文件

image-20240308235453775

  • 同理 找到html下的flag

image-20240308235504379

image-20240308235542511

.htaccess

  • 这道题是通过上传htaccess文件达到绕过的目的

image-20240309142214285

  • 我们先扔一个php文件试试

image-20240309142240546

  • 嗯 显然上传不了 因为文件类型被限制 验证不通过

image-20240309142244012

  • 那么我们上传一个正经的jpg文件看看

image-20240309142304677

  • 欸 发现可以上传

image-20240309142307246

  • 于是我们就利用htaccess文件的特性,上传一个jpg类型的木马
  • htaccess会在服务器将这个jpgphp的形式解析,从而达到绕过的效果
  • 当然了 首先我们得先上传一个htaccess过去 放到它的下载路径里面

image-20240309142348285

  • 嗯 成功上传htaccess文件

image-20240309142349695

  • 这边给一下htaccess文件的内容
1
AddType application/x-httpd-php .jpg
  • 这段代码的意思就是将jpg类型的文件以php的形式解析
  • 下面就可以上传我们的木马了(虽然是jpg类型)
  • 对了 如果没有htaccess文件 这里我们也是可以把这个jpg类型的小木马上传的,但是这样子上传过去的木马是不能正常使用的 充其量也只是一个没有啥内容的图片

image-20240309142601713

  • 好的 上传成功

image-20240309142544001

  • 将文件的相对路径copy过去

image-20240309142550160

  • 复制域名,用蚁剑打开

image-20240309142607040

  • 发现连接成功!说明木马能正常使用

image-20240309142612288

打开文件列表我们可以看到

  • 我们上传的仍然是一个jpg类型文件!!!
  • 只是htaccess会将它以php的形式解码 相当于发挥了原有的木马性能

image-20240309142812444

  • 可以试一下 如果把这个htaccess文件删除
  • 那么这个jpg类型的木马就使用不了了

image-20240309142817562

  • 可见 会报错 因为识别不到能用的木马程序

image-20240309142840369

  • 好了 拿下flag

image-20240309142844389

双写绕过

  • 首先上传一个jpg类型的木马 并用burp suite抓包

image-20240309160023189

  • 我们先来尝试一下修改文件后缀类型 改为php类型
  • 发现上传过去的文件失去了php后缀
  • 说明该题对php进行了滤过

image-20240309160028313

  • 尝试用双写后缀进行绕过
  • 注意 双写不是随便双写就可以的噢
  • 发现上传的文件成功还原成了php类型

image-20240309160033755

  • 复制相对地址

image-20240309160036146

  • 连接蚁剑

image-20240309160038422

  • 可以看到这里有三个文件
  • 第二个是用于抓包时上传过去的jpg类型的木马
  • 第一个是尝试修改后缀名为php时 上传的文件 可以看到这个文件的php被滤过了,否则上传的应该是Super_Moose.php
  • 第三个文件则是通过双写绕过上传的php文件 (原本上传的Super_Moose.pphphp)

image-20240309160040274

  • 最后在目录中找到flag

image-20240309160057825

*00截断

  • 了解一下00截断原理
  • 00代表结束符,所以会把00后面的所有字符都截断
  • 用**%00**就可以实现php文件的正常执行

image-20240309153853348

  • 上传一个jpg类型的木马 并抓包

image-20240309153858472

  • 可以看到抓包后页面如下:

image-20240309153905616

  • 那么我们需要怎么做呢:
  • 只需在post请求中加上“文件名**.php%00**”

image-20240309153917580

  • 这样子就上传过去的就是php类型的文件了!
  • 访问一下试试

image-20240309153921487

  • 连接成功!

image-20240309153923308

  • 可以看到,我们上传过去的Super_Moose.jpg变成了Super_Moose.php
  • 这是因为%00对后面的内容就进行了拦截 就只剩下前面的**.php**了

image-20240309153925432

  • 获得flag

image-20240309142844389

**文件头检查

所谓文件头检查,就是检查图片文件的头部中特有的信息

我们可以:

  1. 在木马前加入一行代表图片的文件头信息
  2. 或者上传一个图片,然后在图片里植入木马

这里我用第二种方法进行演示:

  • 首先呢 我们需要制作一个最简单的png图片(真正的正经图片 not木马)
  • 用电脑自带的画图工具画一下 然后保存成png格式就可以了
  • 接下来上传这个png图片 并用BurpSuite抓包如下:

image-20240309192458670

  • 拦截下来 这些都是图片的编码
  • 我们找到图片文件的最后一段

image-20240309192503048

  • 第一步:在这个地方加上一句话木马(回不回车都行)

image-20240309192507142

  • 第二步:将后缀名png改为php

image-20240309192510342

  • 修改如下:

image-20240309192514040

  • 点击发送 发现文件成功上传

image-20240309192515996

  • 复制相对路径 copy

image-20240309192531404

  • 连接蚁剑 成功连接!

image-20240309192652524

  • 在这边可以看到我们上传的php文件

image-20240309192655508

  • 找到flag所在路径

image-20240309192702559

  • 获取flag

image-20240309192704914

Upload-labs

Pass-01

  • 进入靶场注意到右上角可以查看源代码

image-20240319222404850

  • 看一下源码

image-20240319222424474

  • 简单的前端校验绕过
  • 把一个一句话木马后缀名php先改成jpg,进行抓包

image-20240319223756676

  • 将后缀名jpg改回php

image-20240319223901556

  • 可以看到现在文件可以成功上传了

  • 尝试连接蚁剑

image-20240319224140030

  • 成功连接,添加数据

image-20240319224559028

Tips

如果文件上传上传之后找不到文件路径怎么办?

  • 我们可以在原页面查看源代码
  • 在源代码中搜索我们上传的文件
  • 即可得到文件路径

image-20240319224904939

Pass-02

  • 查看源代码

image-20240319225019832

  • 可以看到 为mine类型

用同样的方法即可

  • 先抓包

image-20240319225245826

  • 注意到这里的mime类型以及是jpg格式

image-20240319225320854

  • 因此识别通过,可以绕过验证
  • 把后缀名改回php即可解析

image-20240319225446805

  • 连接蚁剑

image-20240319225634724

  • 成功添加

image-20240319225710725

Pass-03

  • 查看源代码

image-20240319230045007

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array('.asp','.aspx','.php','.jsp');
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //收尾去空

if(!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file,$img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
  1. 定义变量:
    • $is_upload 是一个布尔变量,用于表示文件是否成功上传,默认为 false
    • $msg 是一个字符串变量,用于存储上传过程中的消息,默认为 null
  2. 检查是否提交了表单:
    • 使用 isset() 函数检查是否存在名为 submit 的 POST 参数,以确定是否提交了表单。
  3. 检查上传路径是否存在:
    • 使用 file_exists() 函数检查上传路径是否存在,其中 UPLOAD_PATH 是一个常量,表示上传文件的目标路径。
    • 如果上传路径不存在,则将错误消息存储在 $msg 变量中。
  4. 检查文件后缀名:
    • 定义了一个名为 $deny_ext 的数组,包含不允许上传的文件后缀名(.asp.aspx.php.jsp)。
    • 获取上传文件的原始文件名,并使用 trim() 函数去除文件名末尾的空格。
    • 使用 strrchr() 函数获取文件名中的后缀名(包括点)。
    • 使用 strtolower() 函数将后缀名转换为小写。
    • 使用 str_ireplace() 函数去除后缀名中的字符串 ::$DATA(如果存在)。
    • 使用 trim() 函数去除后缀名首尾的空格,并将结果存储在 $file_ext 变量中。
  5. 检查文件后缀名是否允许上传:
    • 使用 in_array() 函数检查 $file_ext 是否存在于 $deny_ext 数组中。
    • 如果 $file_ext 不在 $deny_ext 数组中,则继续执行下面的代码。
  6. 处理上传文件:
    • 获取上传文件的临时文件路径,存储在 $temp_file 变量中。
    • 构造目标文件的路径,包括上传路径、当前日期时间和一个随机数,并将后缀名添加到文件名中,存储在 $img_path 变量中。
    • 使用 move_uploaded_file() 函数将临时文件移动到目标路径。
    • 如果移动文件成功,则将 $is_upload 设置为 true,表示文件成功上传。
    • 如果移动文件失败,则将错误消息存储在 $msg 变量中。
  7. 处理不允许上传的文件后缀名:
    • 如果 $file_ext 存在于 $deny_ext 数组中,则将错误消息存储在 $msg 变量中。
  8. 处理上传路径不存在的情况:
    • 如果上传路径不存在,则将错误消息存储在 $msg 变量中,提醒用户手动创建上传路径。
  • 可见为简单的黑名单过滤
  • 我们抓包后将后缀名改为php3绕过

image-20240319230502063

  • 由于php被列为黑名单,于是改为php3

image-20240319230541959

  • 成功上传

image-20240319230552135

  • 尝试连接蚁剑

image-20240319230954238

  • 报错,回看源代码

  • $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; 文件路径被重新命名

  • 我们可以在网页源代码中找到重命名后的文件路径

image-20240326083427899

Pass-04

  • 先来看一下源代码

image-20240321121109527

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".ini");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //收尾去空

if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '此文件不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
  • 典型的黑名单绕过
  • 下面采用多种方式来绕过这一题

.hatccess

  • 只要黑名单中没有将.htaccess的后缀名过滤掉,就能使用这种文件进行攻击
  • 原理其实就是通过上传恶意构造的.htaccess``文件,从而修改apache的配置,使得apache在解析特定后缀名的文件时 会当成其他后缀文件类型来解析

  • 这种文件是apache的一种配置文件,包含三行代码
1
2
3
<FilesMatch "">
SetHandler application/x-httpd-php
</FilesMatch>

注记:

  • 第一行""内留空表示上传给apache任意的文件类型,都如下操作:
  • 当成php文件来解析,至这是第二行php的效果

不过 其实只写这样一行就可以了

1
AddType application/x-httpd-php .jpg
  • 意思是把jpg文件当成php文件解析

下面我们来具体操作一下:

  • 先上传一个jpg为后缀的一句话木马

image-20240321123304908

  • 这个时候木马显然是不能被执行的
  • 我们只需要再上传一个.htaccess文件,相当于修改了apache的配置

image-20240321123416408

  • 现在我们来试着连接蚁剑

image-20240321123818960

  • 可以看到 神奇的事情发生了,虽然后缀名仍是jpg,但可以执行木马

image-20240321123851230

  • 服务端查看我们上传的文件,后缀名仍是jpg
  • 只是我们通过上传.htaccess文件,修改了apache的配置,使得jpg文件被当成php文件来解析

分号配合iis解析漏洞

另一种方法是通过分号来命名文件,可以达到绕过的效果

  • 这其实是windou2032上的IIS服务的解析漏洞
  • 使用前提是要开启IIS服务端

冒号配合PHP和Windows环境的叠加特性

还有一种方法就是利用PHP和Windows环境的叠加特性

  • 在Windows直接修改文件名称加上冒号 肯定是行不通的
  • 所以我们先以jpg后缀上传一句话木马
  • 抓包修改文件名称 加上冒号即可

原理就是Windows环境会将冒号后面的内容去除

1
Moose4.php:.jpg
  • .jpg可以绕过验证
  • 而:则会去除后面部分 只留下Moose4.php
  • 这样就能执行木马了

Pass-05

Pass-06

  • 首先我们查看源代码
  • 很明显地注意到没有改为小写的函数

image-20240324194925665

  • 于是采用大小写绕过的方式
  • 这次用bp的内嵌浏览器

image-20240324194815514

  • 上传一个jpg后缀的一句话木马

image-20240324194819214

  • 抓包后将后缀jpg改为Php

image-20240324194824327image-20240324194828442

  • 可以看到这样文件就能成功上传了

image-20240324194833186

  • 那么问题来了,这道题有文件重命名的函数

image-20240324195412940

  • 那么怎么通过蚁剑来连接呢?

文件被重命名的情况下连接蚁剑

  • 其实我们只需要在上传了php文件的那个网页查看源代码就好了
  • 那么怎么打开那个网页呢(原网页上传的是抓包前的文件)
  • 我们可以用burp suite来显示那个网页:

image-20240324194838551

  • 然后把得到的url复制到内嵌浏览器中

image-20240324195736302

  • 再打开网页,查看源代码即可

image-20240324195811258

  • 用此地址便可连接蚁剑

image-20240324195933376

Pass-07

Pass-08

Pass-09

  • 先查看源代码
  • 注意到没有过滤掉::$DATAimage-20240324200158129
  • 像前几题就有这样的黑名单过滤:

image-20240324200122585

  • 少了$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA这句话我们就可以采用Windows文件流特性来绕过
  • 只需抓包后将上传的Moose9.jpg改为Moose9.php::$DATA
  • 这样上传后保存的文件其实是Moose9.php

(不过 前提是基于Windows系统,Linux系统就不行了)

Pass-10

Pass-11

  • 分析源代码
  • 首先可以看到这里有一个替换函数,将黑名单内的字符串替换成“”内的,在本题是替换成了空
  • 第二点是黑名单里都没有了.,这种情况才能使用双写绕过

  • 既然是替换成,那么就可以操作一下了
  • 采用双写绕过即可

image-20240324200720997

  • 先抓包

image-20240324201215979

  • 修改后缀名为pphphp
  • 注:phphpp不行噢

image-20240324201301130

  • 可以看到,文件成功上传

image-20240324201306562

  • 再打开上传页面 寻找保存路径

image-20240324201321175

  • 从网页源代码中找到路径
  • 可以看到上传保存的文件后缀名已经是php

image-20240324201327847

  • 尝试连接蚁剑
  • 成功连接

image-20240324201331717

Pass-12

  • 分析源代码

image-20240324202448583

  • 典型的白名单例题
  • 抓包后查看请求包
  • save_path在请求头位置
  • 经典的**%00绕过**

原理:%00在url编码中代表0

image-20240324202323525

image-20240324202326803

总结

%00截断适用于url处编码

Pass-13

  • 分析源代码
  • 也是一道白名单类型的题

image-20240325231459092

  • bp抓包一下

image-20240325231721062

  • 可以注意到,与上一题相比,upload在请求数据中,而不是在url处
  • 由于文件路径不在url处,因此不能使用**%00**绕过了

  • 既然如此,我们就可以使用0x00绕过
  • %00适用于文件路径在请求数据中的情况

  • 第一步,现在upload后加上我们要命名的文件名
  • 然后加上一个空格
  • 这时我们虽然敲的是空格,但其实是十进制的,而事实上我们需要的是十六进制的0
  • 于是还需要在Hex中改成十六进制的00

注:这个空格的作用只是便于我们在Hex中找到空格对应的十六进制编码的位置而已,改成其他有辨识度的字符其实也可以

image-20240325232942796

  • 由于空格在十六进制中表示为20
  • 寻找一下,发现20所在位置

image-20240325232948390

  • 然后我们将其改为00,也就是十六进制的0
  • 这样请求数据中的空格就变成十六进制的0了

image-20240325232949629image-20240325232950582

小结

0x00适用于upload在“请求数据”中的情况

Pass-14

Pass-15

Pass-16

Pass-17

Pass-18

Pass-19

Pass-20