文件上传进阶
1.文件扩展名白名单绕过
白名单扩展名校验相比于黑名单更安全、可靠、普遍。绕过白名单检测通常需要依靠Web服务器的解析缺陷,或lmageMagick等组件缺陷。
1.IIS(一个服务器)解析缺陷
在IIS 6.0中,".asp"和".asa"目录中的任何扩展名的文件,都会被IIS当作asp文件来解析执行。比如在目录"a.asp"中存在文件"a.asp/1jpg",那么"1.jpg"就会当作asp文件解析执行。
对于文件名为"a.asp;a.jpg"的文件,IIS会忽略分号后的部分,当作"a.asp"解析执行。
2.Nginx解析缺陷
Nginx解析缺陷是配置不当造成的,在Nginx未设置try_files指令对要访问的文件进行存在性检查,并且PHP-FPM未设置"security.limit_extensions"限制可解析的扩展名时,可能出现解析缺陷。
当Nginx使用下面的配置文件时
location ~ \.phps{
fastcgi_pass 127.0.0.1:9000;
fastcgt_param SCRIPT_FILENAME $document_root$fastcgt_script_name;
include fastcgt_params;
}
先上传木马"1.jpg",再访问"1.jpg/1.php"由于文件名为"·php"结尾,Nginx会发给FPM处理,当PHP启用了(默认)"cgi.fix_pathinfo”时,会发现"jpg/1.php"不存在,开始fallback到"1.jpg”,此时若“security.limit_extensions"没有设置,那么PHP就会解析并执行"1.jpg”,造成解析缺陷。
自PHP 5.3.9开始“security.limit _extensions"被加入到PHP中,并且默认值为".php",".phar”
3.Apache解析缺陷
多扩展名解析
在Apache中,单个文件支持多个扩展名,如果每个扩展名都存在对应的handler或media-type,那么对应的解析器会处理当前文件。
如果存在配置"AddHandler application/x-htpd-php .php",那么"a.php.xxx“文件会使用php进行处理
2.上传文件禁止访问绕过
在测试的过程中,经常会遇到,虽然上传功能允许上传任意扩展名的文件,但是上传后无法访问,或不能被解析。这通常是由于配置了上传目录禁止解析。在这种场景下,可以尝试目录穿越,使用"../"上传到上级目录,不过对于PHP中$FILES获取的文件名,已经被basename处理过,无法直接利用。
1.".htaccess"禁止脚本文件解析
利用".htaccess"文件设置了上传目录中的文件Handler,".php"无法使用默认handler进行解析。但是在Apache 2.3.9之后,"AlowOverride"默认为None,".htaccess"无法继续发挥作用,造成绕过。
2.上传文件到"OSS"
如果上传文件被保存到云对象存储(OSS)中,自然无法进行解析执行。但是可以通过上传“HTML等文件实现XSS,不过需要注意OSS的域名,需要与网站的域名一致。
3.配合文件包含
如果目标站点存在文件包含缺陷,比如PHP中的"include $_GET['page”;”,那么无论上传文件的扩展名是什么,都可以被文件包含执行。同样也可以适用于SSTI,如果网站允许选择染模板的路径,那么也可以完成SSTI。
3.图片验证绕过
部分开发者认为,上传文件的内容如果是正常图片,那么就不可能再包含代码,因此只检查是否是图片,不检查文件扩展名。
但是在PHP中,检查文件是否为正常图片的方法,往往可以被绕过
1.getimagesize绕过
getimagesize函数用于获取图像的信息,包括尺寸和文件类型。绕过文件不是有效的图像,那么返回FALSE。
对getimagesize的绕过,只需把PHP代码添加到图片后,getimagesize函数会正常工作,文件也可以被正常解析。
比如使用"GIF98a作为文件开头",就会被识别为GIF文件。
还可以使用XBM格式,如果在文件的某一行符合“#define%s %d”,就会格式化取出字符串和数字如果最后height和width不为空,那么getimagesize就会成功返回。因为是逐行读取,所以这个"#define“可以放在任意一行。
2.imagecreatefromjpeg绕过
imagecreatefromjpeg会重新渲染并生成新图片,在图片中插入其他字符经过渲染后会消失。
可以使用“https://github.com/BlackFan/jpg_payload",将脚本嵌入到jpg图片中,即使经过转换仍然可以保留在图片中。
先保存一个jpg文件,然后用jpg_payload.php进行处理,然后再经过上传服务的转换,最后仍然能执行其中的system命令。