1. 概述
文件上传在Web业务中很常见,如用户上传头像、编写文章上传图片等。在实现文件上传时,如果后端没有对用户上传的文件做好处理,会导致非常验中的安全问题,如服务器被上传恶意木马或者垃圾文件。
2. 基础文件上传漏洞
PHP的文件上传通常使用move_uploaded_file方法配合 $_FILES
变量实现。
<?php
$file = $_FILES['file'];
move_uploaded_file($file['tmp_name'], $file['name']);
.......
?>
3. 截断绕过上传限制
3.1 00截断
00截断是绕过上传限制的一种常见方法。在C语言中,\0
是字符串的结束符,如果用户能够传入 \0
,就能实现截断。
00截断绕过上传限制适用的场景为,后端先获取用户上传文件的文件名,如 x.php/00.jpg
,再根据文件名获得文件的实际后缀 jpg ;通过后缀的白名单校验后,最终在保存文件时发生截断,实现上传的文件为 x.php 。
PHP的底层代码为C语言,自然存在这种问题,但是实际PHP使用 $_FILES
实现文件上传时并不存在00截断绕过上传限制问题,因为PHP在注册 $_FILES
全局变量时已经产生了截断。上传文件名为 x.php/00.jpg
的文件,而注册到 $_FILES['name']
的变量值为 x.php ,根据该值得到的后缀为 php ,因此无法通过后缀的白名单校验。
3.2 转换字符集造成的截断
虽然 PHP 的 $_FILES
文件上传不存在00截断绕过上传限制的问题,不过在文件名进行字符集转换的场景下也可能出现截断绕过。PHP在实现字符集转换时通常使用iconv()函数,UTF-8在单字节时允许的字符范围为0x00~0x7F,如果转换的字符不在该范围内,则会造成 PHP_ICONV_ERR_ILLEGAL_SEQ 异常,低版本PHP在 PHP_ICONV_ERR_ILLEGAL_SEQ 异常后不再处理后面字符从而造成截断问题。当PHP版本低于5.4时,转换字符集能够造成截断,但5.4及以上版本会返回 false 。
转换字符集造成的截断在绕过上传限制中适用的场景为,先在后端获取上传的文件后缀,经过后缀白名单判断后,如果有对文件名进行字符集转换操作,那么可能出现安全问题。
3.3 文件后缀黑名单校验绕过
黑名单校验上传文件后缀,即通过创建一个后缀名的黑名单列表,在上传时判断文件后缀名是否在黑名单列表,在黑名单中则不进行任何操作,不在则可以上传,从而实现对上传文件的过滤。
3.3.1 上传文件重命名
在文件名重命名的场景下,可控的只有文件后缀,通常使用一些比较偏门的可解析的文件后缀绕过黑名单限制。
PHP常见的可执行后缀为PHP3、PHP5、phtml、pht等,ASP常见的可执行后缀为cdx、cer、asa等,JSP等
3.3.2 上传文件不重命名
3.3.2.1 上传 .htaccess 文件绕过黑名单
.htaccess是Apache分布式配置文件的默认名称,也可以在Apache主配置文件中通过AccessFileName指令修改分布式配置文件的名称。
3.3.2.2 上传 .user.ini 文件绕过黑名单
References:
《从0到1 CTFer成长之路》
《CTF特训营》