upload-labs
一、摘要
项目地址: https://github.com/c0ny1/upload-labs


二、关卡及说明
pass-01-JS校验
说明:该关卡在前端在JS中对上传文件的后缀进行限制
同类型题:XCTF-upload1
步骤
1、点击F12或查看源码,可看到JavaScript字段,其中对可上传文件后缀做了限制
2、上传步骤如下:
1、使用burp抓包,在返回包中去掉JavaScript字段,然后放包

2、直接在页面中选择 XX.php 的文件,上传

3、新标签中打开文件,即可看到上传好的文件

1、在本地文件夹中,将 .php 后缀的文件改为 .jpg 等后缀,打开 burp 抓包然后点击上传
2、在burp中,将所上传 .jpg 后缀的文件更换回 .php ,点击放包

3、在新标签中打开文件,可看到上传好的文件

1、选中JPG文件,点击上传并修改后缀(经测试,也可以使用方法一)

2、复制返回包中的路径及文件名

3、新建标签页打开

思考
1、说了这么多,那么为什么程序员开发代码时候会使用前端校验的方式,是他们不清楚前端校验很容易被绕过吗?当然不是。之所以使用前端校验,主要是因为效率高,用户体验好,如果所有的数据都发送给服务器,服务器校验后再发给客户端,这中间需要消耗时间,用户体验就变得不好。但这种校验方式的开发的初衷是针对中规中矩的普通用户,当面对黑客这类群体时候就变得形同虚设。
2、那么我们深入再思考一点,对于CS架构的游戏类开发,其实很多数据也是通过客户端进行校验的,因为游戏类产品,人物的复杂运动会产很多复杂的数据,这些数据如果全部提交给服务器校验,显然会对服务器造成很大处理压力,因此,程序员在开发时候,对一些安全要求不高,对速度要求很高的数据校验都是写在客户端进行校验的,当然,这也是游戏外挂编写的基本思路,其实还是那句老话,所有客户端的数据输入校验都是可以绕过的。
3、写到最后,实际编程开发中我们应该在安全开发方面注意哪里点呢。其实,从上面的分析就可以得出结论,一是不能只有前端校验,没有后端校验,对于一些可能重大影响程序结果的数据,最好使用前后端结合的校验方式,即保证用户体验,又保障程序安全。另外,在游戏、app等客户端开发时,我们可以通过混淆、加密、加壳等手段尽量防止客户端使用者对关键数据和算法进行逆向分析。
pass-02-MIME校验
本关卡源码如下:
根据提示,该关卡在服务端对文件的MIME进行了校验。
从源码中,可看出该关卡允许的MIME为:

1、故在上传文件时,只需要将 .php 文件中的Content-Type部分更改为允许的MIME即可,如下图


2、新标签页中打开文件,如图:

pass-03-后缀校验
该关卡源码如下:
该关卡采用了验证文件后缀的方式,其中,.asp,.aspx,.php,.jsp 为不可上传的文件后缀。且上传后,文件名会被修改
1、基于白名单验证:只针对白名单中有的后缀名,文件才能上传成功。 2、基于黑名单验证:只针对黑名单中没有的后缀名,文件才能上传成功。
但是可以其他后缀名嘛,例如php1、php2、phtml、php5等等。
步骤:
1、将本地的 .php后缀文件上传,同时抓包
2、在burp中更改所上传文件后缀为 .php5 ,并放包
3、收到返回包后,查看经程序修改后的文件名

4、访问文件

说明:若上传文件后发现访问不了,可能原因有phpstudy的Apache配置文件原因。原配置文件限制了后缀,更改为 AddType application/x-httpd-php .php .phtml .php3 .php4 即可。记得重启服务!记得重启服务!记得重启服务!

pass-04-.hatccess
该关卡使用黑名单验证,禁止上传的后缀有:
于是,可先上传 .hatccess 文件来进行绕过。
htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
apache服务器
能够上传.htaccess文件,一般为黑名单限制。
AllowOverride All,默认配置为关闭None。
LoadModule rewrite_module modules/mod_rewrite.so #模块为开启状态
上传目录具有可执行权限。
步骤:(该过程无需burp)
1、上传 .htaccess 文件
2、上传 .jpg 结尾的 php 脚本文件
3、访问文件

pass-05-.user.ini
从源码中可得,本关使用的黑名单如下:
于是,可上传文件如下:
文件大意:所有的php文件都自动包含1.gif文件。.user.ini相当于一个用户自定义的php.ini
上传后,使用连接器连接即可。
注意:phpstudy2016版本默认不会扫描到 .user.ini 文件
pass-06-后缀大小写
由源码可知,本关只是限制了部分后缀,因为上传的脚本文件为PHP的,所以可看到相关限制有:
大小写绕过原理:
Windows系统下,对于文件名中的大小写不敏感。例如:test.php和TeSt.PHP是一样的。
Linux系统下,对于文件名中的大小写敏感。例如:test.php和 TesT.php就是不一样的。
所以,可上传后缀为 .Php 的文件,进行绕过
访问结果如下:

pass-07-空格
根据源码,可得:
此关卡中大小写无效
限制了一些文件后缀
此时,可在burp中抓包,在文件名后面添加空格,来绕过
Windows系统下,对于文件名中空格会被作为空处理,程序中的检测代码却不能自动删除空格。从而绕过黑名单。 针对这样的情况需要使用Burpsuite阶段HTTP请求之后,修改对应的文件名 添加空格。

之后访问文件:

pass-08-点号
文件上传时,添加点号即可完成绕过。
.号绕过原理:
Windows系统下,文件后缀名最后一个点会被自动去除。

完成上传后,访问文件,效果图如下:

pass-09-::$DATA
特殊符号绕过原理:
Windows系统下,如果上传的文件名中 test.php::$DATA 会在服务器上生成一个 test.php 的文件,其中内容和所上传文件内容相同,并被解析。


pass-10-. .


pass-11-双写后缀
这一关是用str_ireplace函数将符合黑名单中的后缀名进行替换为空。所以可以双写绕过


pass-12-0x00
这一关,需要php的版本号低于5.3.29,且magic_quotes_gpc为关闭状态。

pass-13-0x00
这一关和Pass-12的区别是,00截断是用在POST中,且是在二进制中进行修改。因为POST不会像GET那样对%00进行自动解码。

pass-14-文件头

pass-15-getimagesize()
注:这里可能会有一些问题,就是copy制作的图片马,制作出来后,图像是损坏的,那么15关就过不去。所以可以利用winhex之类的工具,讲一句话加在图片的后面。这样就能过了。

pass-16-exif_imagetype()
这一关需要开启php_exif模块。

pass-17-二次渲染
思路:
将上传的图片重新下载下来,放入winhex,进行对比。可以找到二次渲染后不变的地方,而这个地方就是可以插入一句话的地方。
第71行检测$fileext和$filetype是否为gif格式.
然后73行使用move_uploaded_file函数来做判断条件,如果成功将文件移动到$target_path,就会进入二次渲染的代码,反之上传失败.
在这里有一个问题,如果作者是想考察绕过二次渲染的话,在move_uploaded_file($tmpname,$target_path)返回true的时候,就已经成功将图片马上传到服务器了,所以下面的二次渲染并不会影响到图片马的上传.如果是想考察文件后缀和content-type的话,那么二次渲染的代码就很多余.(到底考点在哪里,只有作者清楚.哈哈)
由于在二次渲染时重新生成了文件名,所以可以根据上传后的文件名,来判断上传的图片是二次渲染后生成的图片还是直接由move_uploaded_file函数移动的图片.
我看过的writeup都是直接由move_uploaded_file函数上传的图片马.今天我们把move_uploaded_file这个判断条件去除,然后尝试上传图片马.
将<?php phpinfo(); ?>添加到111.gif的尾部.
成功上传含有一句话的111.gif,但是这并没有成功.我们将上传的图片下载到本地.
可以看到下载下来的文件名已经变化,所以这是经过二次渲染的图片.我们使用16进制编辑器将其打开.
可以发现,我们在gif末端添加的php代码已经被去除.
关于绕过gif的二次渲染,我们只需要找到渲染前后没有变化的位置,然后将php代码写进去,就可以成功上传带有php代码的图片了.
经过对比,蓝色部分是没有发生变化的,
我们将代码写到该位置.
上传后在下载到本地使用16进制编辑器打开
可以看到php代码没有被去除.成功上传图片马
png的二次渲染的绕过并不能像gif那样简单.
png文件组成
png图片由3个以上的数据块组成.
PNG定义了两种类型的数据块,一种是称为关键数据块(critical chunk),这是标准的数据块,另一种叫做辅助数据块(ancillary chunks),这是可选的数据块。关键数据块定义了3个标准数据块(IHDR,IDAT, IEND),每个PNG文件都必须包含它们.
数据块结构
CRC(cyclic redundancy check)域中的值是对Chunk Type Code域和Chunk Data域中的数据进行计算得到的。CRC具体算法定义在ISO 3309和ITU-T V.42中,其值按下面的CRC码生成多项式进行计算:
x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
分析数据块
IHDR
数据块IHDR(header chunk):它包含有PNG文件中存储的图像数据的基本信息,并要作为第一个数据块出现在PNG数据流中,而且一个PNG数据流中只能有一个文件头数据块。
文件头数据块由13字节组成,它的格式如下图所示。
PLTE
调色板PLTE数据块是辅助数据块,对于索引图像,调色板信息是必须的,调色板的颜色索引从0开始编号,然后是1、2……,调色板的颜色数不能超过色深中规定的颜色数(如图像色深为4的时候,调色板中的颜色数不可以超过2^4=16),否则,这将导致PNG图像不合法。
IDAT
图像数据块IDAT(image data chunk):它存储实际的数据,在数据流中可包含多个连续顺序的图像数据块。
IDAT存放着图像真正的数据信息,因此,如果能够了解IDAT的结构,我们就可以很方便的生成PNG图像
IEND
图像结束数据IEND(image trailer chunk):它用来标记PNG文件或者数据流已经结束,并且必须要放在文件的尾部。
如果我们仔细观察PNG文件,我们会发现,文件的结尾12个字符看起来总应该是这样的:
00 00 00 00 49 45 4E 44 AE 42 60 82
写入php代码
在网上找到了两种方式来制作绕过二次渲染的png木马.
写入PLTE数据块
php底层在对PLTE数据块验证的时候,主要进行了CRC校验.所以可以再chunk data域插入php代码,然后重新计算相应的crc值并修改即可.
这种方式只针对索引彩色图像的png图片才有效,在选取png图片时可根据IHDR数据块的color type辨别.03为索引彩色图像.
在PLTE数据块写入php代码.
计算PLTE数据块的CRC CRC脚本
运行结果
3.修改CRC值
4.验证 将修改后的png图片上传后,下载到本地打开
写入IDAT数据块
这里有国外大牛写的脚本,直接拿来运行即可.
运行后得到1.png.上传后下载到本地打开如下图
pass-18-条件竞争
先上传再判断,所以实在判断前就对上传的文件进行请求


pass-19-图片
验证过程:依次检查文件是否存在、文件名是否可写、检查后缀(白名单)、检查文件大小、检查临时文件存在、保存到临时目录里、然后再重命名。与Pass-18存在同样的条件竞争。不同的是这里先检查了后缀,所以要上传符合白名单里的才能进行。
pass-20-点号
同样是上传路径可控,可以使用和Pass-13同样的方式绕过。不同的是这里的黑名单,可以文件名称保存的时候,加上.,最末的.号使得pathinfo()获取到的PATHINFO_EXTENSION为空,从而绕过黑名单。

pass-21-数组
验证过程:先检查MIME,通过后检查文件名,保存名称为空的就用上传的文件名。再判断文件名是否是array数组,不是的话就用explode()函数通过.号分割成数组。然后获取最后一个,也就是后缀名,进行白名单验证。不符合就报错,符合就拼接数组的第一个和最后一个作为文件名,保存。
绕过过程:绕过MIMIE,改一下包的Content-Type,为了绕过explode()函数,需要传入数组,绕过白名单,由于取的是end()也就是数组最后一个,需要传入数组的最后一个为jpg|png|gif,最后是拼接文件名,取的是reset()第一个,即索引为0,和索引count()-1(数组内元素个数-1)。所以令索引0为1.php,索引2为jpg(只要是索引1之后都可),这样数组元素个数为2,拼接的就是索引0和索引1,也就是1.php和空,结果还是1.php,这样就可以使得拼接后的文件名为1.php。

三、文件上传对应防御手段
黑白名单;
对上传的文件重命名,不易被猜测;
对上传的内容进行读取检查;
不要暴露上传文件的位置;
禁用上传文件的执行权限;
系统运行时的防御
1、文件上传的目录设置为不可执行。只要web容器无法解析该目录下面的文件,即使攻击者上传了脚本文件,服务器本身也不会受到影响。
2、判断文件类型。在判断文件类型时,可以结合使用MIME Type、后缀检查等方式。在文件类型检查中,强烈推荐白名单方式,黑名单的方式已经无数次被证明是不可靠的。此外,对于图片的处理,可以使用压缩函数或者resize函数,在处理图片的同时破坏图片中可能包含的HTML代码。
3、使用随机数改写文件名和文件路径。文件上传如果要执行代码,则需要用户能够访问到这个文件。在某些环境中,用户能上传,但不能访问。如果应用了随机数改写了文件名和路径,将极大地增加攻击的成本。再来就是像shell.php.rar.rar和crossdomain.xml这种文件,都将因为重命名而无法攻击。
4、单独设置文件服务器的域名。由于浏览器同源策略的关系,一系列客户端攻击将失效,比如上传crossdomain.xml、上传包含Javascript的XSS利用等问题将得到解决。
5、使用安全设备防御。文件上传攻击的本质就是将恶意文件或者脚本上传到服务器,专业的安全设备防御此类漏洞主要是通过对漏洞的上传利用行为和恶意文件的上传过程进行检测。恶意文件千变万化,隐藏手法也不断推陈出新,对普通的系统管理员来说可以通过部署安全设备来帮助防御。
系统开发阶段的防御
对文件上传漏洞来说,最好能在客户端和服务器端对用户上传的文件名和文件路径等项目分别进行严格的检查。客户端的检查虽然对技术较好的攻击者来说可以借助工具绕过,但是这也可以阻挡一些基本的试探。服务器端的检查最好使用白名单过滤的方法,这样能防止大小写等方式的绕过,同时还需对%00截断符进行检测,对HTTP包头的content-type也和上传文件的大小也需要进行检查。
系统维护阶段的防御
1、系统上线后运维人员应有较强的安全意识,积极使用多个安全检测工具对系统进行安全扫描,及时发现潜在漏洞并修复。
2、定时查看系统日志,web服务器日志以发现入侵痕迹。定时关注系统所使用到的第三方插件的更新情况,如有新版本发布建议及时更新,如果第三方插件被爆有安全漏洞更应立即进行修补。
3、对于整个网站都是使用的开源代码或者使用网上的框架搭建的网站来说,尤其要注意漏洞的自查和软件版本及补丁的更新,上传功能非必选可以直接删除。除对系统自身的维护外,服务器应进行合理配置,非必选一般的目录都应去掉执行权限,上传目录可配置为只读。
四、相关内容
1、文件名SQL注入
通关过程:
步骤如下:
1、SQL注入双写绕过
2、语句拆解
3、前后闭合 4、"+"号代替空格号。
2、文件上传与XSS
1) 文件名
文件名本身可能就是网页的一部分可以造成反射,所以可以通过将 XSS 语句插入文件名中来触发反射。

2) 元数据
使用 exiftool 工具可以修改 EXIF 元数据,从而在某些地方造成反射:
例子:

3) 内容
如果 Web 应用允许上传 SVG(一种图像类型)扩展名,则以下内容可以用来触发 XSS:
一个 POC 可以在这里看到 brutelogic.com.br/poc.svg。
4)源码
我们可以很容易的创建一张包含 javascript payload 的 GIF 图片,然后将这张图片当做源码加以引用。如果我们可以成功的注入相同的域名,如下所示,则这样可以有效的帮我们绕过 CSP(内容安全策略)防护(其不允许执行例如<script>alert(1)</script>)

创建这样一张图片可以使用如下内容并将文件命名为 .gif 后缀:
GIF 文件标识 GIF89a 做为一个 javascript 的变量分配给 alert 函数。中间注释部分的 XSS 是为了以防图像被检索为 text/HTML MIME 类型时,通过请求文件来执行 payload。
我们通过下图可以发现,类 UNIX 命令的 PHP 函数 exif_imagetype() 和 getimagesize() 都会将这个文件识别为 GIF 文件。而一般的 Web 应用都是使用这些函数来验证图像类型的,所以这样一个文件是可以被上传的(但上传后可能会被杀毒软件查杀)。

方法:
文件名中添加
;例如:1;23.php文件名中添加
'例如:1'23.php文件后缀中添加空格:
12.php文件后缀中添加空格:
12.p hp
4、已提交相关漏洞

最后更新于
这有帮助吗?