在之前关于文件上传的文章中,笔者讲解了文件上传漏洞的相关原理,并以皮卡丘射击场为例,在本例中,对文件上传漏洞的前端代码进行了相关防护。从观察者的角度来看,如何绕过前端保护才能成功攻击?实际上,与文件上传漏洞相关的安全保护仅限于前端,因此本文将介绍与后端相关的问题并进行解释。如何从攻击者的角度规避过滤措施。
1.MIME类型过滤:
哑剧:
MIME(多用途互联网邮件扩展)是一种互联网标准,用于描述在互联网应用程序(例如电子邮件和Web)中发送的数据类型。 MIME 类型最初是为了解决通过电子邮件发送多媒体内容的问题而设计的,但现在广泛用于HTTP 协议中来描述和处理各种类型的网络资源。
MIME类型结构
MIME 类型由两部分组成:类型/子类型格式。
type:主类型,代表数据的主要类别,如文本、图像、音频、视频、应用程序等。
子类型:特定的子类型。表示数据的具体格式,例如plain、html、jpeg、png、mpeg或json。
例如:
text/html 表示HTML 文档
image/jpeg 表示JPEG 图像
application/json 表示JSON 数据
更熟悉的说法,文件上传MIME类型过滤是指通过检查上传文件的MIME类型来限制允许上传的文件类型的文件上传功能。这可以防止用户上传恶意文件并提高应用程序的安全性。以下是如何实现文件上传的MIME 类型过滤的一些细节和示例。
相关源码:
?php
if ($_SERVER[\’REQUEST_METHOD\’]===\’POST\’) {
$allowedTypes=[\’图像/jpeg\’, \’图像/png\’, \’应用程序/pdf\’];
$fileType=mime_content_type($_FILES[\’file\’][\’tmp_name\’]);
if (!in_array($fileType, $allowedTypes)) {
die(\’无效的文件类型。\’);
}
//处理文件上传逻辑,例如将文件移动到目标目录
move_uploaded_file($_FILES[\’file\’][\’tmp_name\’], \’uploads/\’ .basename($_FILES[\’file\’][\’name\’]));
echo \’文件上传成功。 \’;
}
?
表单方法=\’POST\’ enctype=\’multipart/form-data\’
输入类型=\’文件\’名称=\’文件\’
按钮类型=\’提交\’上传/按钮
/形状
$allowedTypes=[\’image/jpeg\’, \’image/png\’, \’application/pdf\’]; 定义一个包含允许上传的文件的MIME 类型的数组。
$fileType=mime_content_type($_FILES[\’file\’][\’tmp_name\’]); 使用mime_content_type 函数获取上传文件的MIME 类型。 $_FILES[\’file\’][\’tmp_name\’] 是上传文件的临时文件路径。
if (!in_array($fileType, $allowedTypes)) {
die(\’无效的文件类型。\’);
}
使用in_array 函数检查上传文件的MIME 类型是否在允许的类型列表中。如果不是,它将终止脚本执行并打印“无效的文件类型”。
绕过方式:
通过BP捕获数据包并修改请求头中的Content-Type字段来绕过数据包。如果您上传的文件是php文件,则该字段的内容将为:
目前,您可以通过将该字段更改为以下示例MIME 类型来绕过它:
图像/jpeg、图像/png、应用程序/pdf、文本/纯文本、文本/html、图像/png
下面的表格(10 行)显示了常见的MIME 类型。
文件扩展名MIME 类型描述.htmltext/htmlHTML document.csstext/cssCSS stylesheet.jstext/javascriptJavaScript code.jsonapplication/jsonJSON format.jpgimage/jpegJPEG image.pngimage/pngPNG image.gifimage/gifGIF image.mp3audio/mpegMP3 audio.mp4video/mp4MP4 video .pdf申请/pdfPDF文档
当然,除了这些可修改的值之外,您还可以将各种MIME 类型存储在txt 文件中并使用BP 运行FUZZ 测试。
2.扩展名验证:
黑名单:
使用扩展程序黑名单是防止文件上传漏洞的有效方法。禁用具有特定扩展名的文件上传可降低恶意文件上传到服务器的风险。常见的可加入黑名单的恶意文件扩展名包括(以靶场上传为例):
如果(文件存在(上传路径)){
$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=strto lower($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;
} 除此之外{
$msg=\’上传错误!\’;
}
} 除此之外{
$msg=\’不允许上传.asp、aspx、php、jsp后缀文件!\’;
}
代码逻辑:
$deny_ext=array(\’.asp\’,\’.aspx\’,\’.php\’,\’.jsp\’);定义一个包含不允许上传的文件扩展名的数组。
接下来,对上传的文件名进行处理,得到上传文件的扩展名。in_array($file_ext, $deny_ext) 然后判断当前上传文件的扩展名是否在黑名单中。文件未保存)。
此时的绕过思路:
以PHP为例,使用特殊的文件后缀来绕过它。
.php3、php4、php5、php7:用于指定PHP版本的文件后缀。几乎没有使用过。
.phtml:表示包含PHP代码的HTML文件。通常用于混合HTML 和PHP 代码。
.inc:通常本身不是PHP后缀,但常常包含PHP代码并通过include或require引入其他PHP文件。 (需要文件包含漏洞)
上面的代码黑名单列表并不完整,所以现在只需要更改php文件的后缀并上传即可。如果开发过程中需要完成尽可能多的黑名单,以下是一些常见的黑名单:
.php、php3、php4、php5、phtml、phps、asp、aspx、jsp、jspx、cfm、cgi、pl、py、rb、sh、bat 、exe、com、cmd、dll、scr、msi、vbs、js、jse、wsf、wsh、ps1
白名单
对于文件上传保护,使用白名单过滤仅允许某些安全文件类型和扩展名,是降低风险的有效方法。下面是如何实现白名单过滤的详细说明和示例代码。
if(isset($_POST[\’提交\’])){
$ext_arr=array(\’jpg\’,\’png\’,\’gif\’);
$file_ext=substr($_FILES[\’upload_file\’][\’name\’],strrpos($_FILES[\’upload_file\’][\’name\’],\’.\’)+1);
if(in_array($file_ext,$ext_arr)){
$temp_file=$_FILES[\’upload_file\’][\’tmp_name\’];
$img_path=$_GET[\’save_path\’].\’/\’.rand(10, 99).date(\’YmdHis\’).\’.\’.$file_ext;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload=true;
} 除此之外{
$msg=\’上传错误!\’;
}
} 除此之外{
$msg=\’您只能上传.jpg|.png|.gif 类型的文件。 \’;
}
}
?
$ext_arr=array(\’jpg\’,\’png\’,\’gif\’); 设置文件后缀白名单列表,只有文件后缀包含在白名单中才允许上传。
绕过方式:
00 截断:如果文件名中包含NULL字符,某些编程语言和服务器在处理字符串时会截断NULL字符后面的内容。例如,PHP 有时会将example.php\\0.jpg 文件名截断为example.php,从而绕过扩展名检查。
其他绕过手法总结
1.大小写绕过:利用服务器文件系统或代码对文件扩展名大小写不敏感的特性,绕过安全检测和过滤。
某些文件系统的文件名不区分大小写。换句话说,example.php 和example.PHP 被视为同一文件。在这种情况下,攻击者可以使用大小写变体来绕过文件扩展名检测。
Windows 文件系统(NTFS、FAT32):默认情况下不区分大小写。
macOS 文件系统(HFS+):默认情况下不区分大小写。
Linux 文件系统(ext3、ext4、XFS):默认区分大小写。
然而,上述代码包含对获得的扩展进行统一转换的操作。
$file_ext=strto lower($file_ext); //转换为小写
因此,目前无法在之前的环境中启用案例旁路。
2.双重扩展名
使用双扩展允许服务器仅检查第一个扩展并避免检测。
示例:
示例.php.aa
示例.php.bb
在这种情况下,中间件在解析过程中从后到前进行识别,并使用将其标识为当前文件类型的后缀名。
3.文件内容混淆
原理:在文件内容中添加无害的字符或注释以通过内容检查。
例子:
将JPEG 文件头添加到PHP 文件中。
适用条件:服务器检查文件内容,但允许使用无害字符。
4.特殊字符绕过
原理:使用特殊字符或编码方式来规避检查。
示例:example.php%00.jpg(%00 是NULL 字符)
适用条件:服务器在处理字符串时忽略特殊字符或编码。
5.编码绕过
原理:通过URL编码或Unicode编码绕过检查。
示例: example%2Ephp (%2E 代表)
适用条件:编码过程中服务器未解码或解码错误。
6.::$DATA
原理:利用NTFS文件系统的ADS功能,在文件名后追加:$DATA。
示例:example.php:$DATA
适用于:服务器运行在Windows操作系统上,使用NTFS文件系统。
防御措施
1.严格的白名单机制:仅允许某些文件扩展名和MIME类型。
2.统一转换为小写:处理扩展名时统一转换为小写。
3.检查文件内容:不仅检查文件扩展名,还检查文件内容的实际类型(MIME类型和文件头)。
4. 删除特殊字符。处理文件名时,去除特殊字符,包括NULL字符和:
5. 重命名上传的文件。上传文件后,重命名该文件以删除任何潜在的恶意扩展名。
6. 设置正确的文件权限。确保上传目录没有执行权限,防止文件被执行。
示例代码
下面是结合了多种防御的文件上传代码示例。
?php
函数sanitize_filename($filename) {
//删除NULL 字符、NTFS 数据流标识符和其他特殊字符。
$filename=str_replace([\’\\0\’, \’:$DATA\’], \’\’, $filename);
$filename=preg_replace(\’/[^a-zA-Z0-9._-]/\’, \’\’, $filename);
$返回文件名;
}
$allowed_ext=array(\’jpg\’, \’jpeg\’, \’png\’, \’pdf\’); //后缀名白名单
$allowed_mime_types=array(\’image/jpeg\’, \’image/png\’, \’application/pdf\’); //mime 白名单
$file_name=sanitize_filename($_FILES[\’upload_file\’][\’name\’]);
$file_ext=strto lower(pathinfo($file_name, PATHINFO_EXTENSION));
$finfo=finfo_open(FILEINFO_MIME_TYPE);
$file_mime_type=finfo_file($finfo, $_FILES[\’upload_file\’][\’tmp_name\’]);
finfo_close($finfo);
if (in_array($file_ext, $allowed_ext) in_array($file_mime_type, $allowed_mime_types)) {
$temp_file=$_FILES[\’upload_file\’][\’tmp_name\’];
$destination=\’上传/\’ .
if (move_uploaded_file($temp_file, $destination)) {
echo \’文件上传成功。 \’;
} 除此之外{
echo \’移动上传文件时发生错误。 \’;
}
} 除此之外{
echo \’文件类型无效。 \’;
}
?
表单方法=\’POST\’ enctype=\’multipart/form-data\’
输入类型=\’文件\’名称=\’上传文件\’
按钮类型=\’提交\’上传/按钮
/形状
安全性分析
清理文件名: sanitize_filename 函数删除NULL 字符和NTFS 数据流标识符,仅保留字母、数字、点、下划线和破折号。这有效地防止了常见的文件名绕过技术。
检查文件扩展名和MIME 类型:
检查文件扩展名是否在允许列表中。
使用finfo_file函数获取文件的MIME类型并检查它是否在允许列表中。这种双重检查可确保文件类型是安全的。
唯一的文件名:使用uniqid 函数生成唯一的文件名并避免文件覆盖问题。
错误处理:如果文件移动失败,则会打印错误消息。这并不能完全防止攻击,但它将帮助您调试和改进代码。
#Web入侵上图:与文件上传相关的内容源网络仅供参考。相关信息请参见官方公告。
原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/91829.html