文件上传漏洞简单绕过与防御机制

文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。常见场景是web服务器允许用户上传图片或者普通文本文件保存,而用户绕过上传机制上传恶意代码并执行从而控制服务器。显然这种漏洞是getshell最快最直接的方法之一,需要说明的是上传文件操作本身是没有问题的,问题在于文件上传到服务器后,服务器怎么处理和解释文件。

JS验证

1、关闭浏览器JS功能
///Chrome浏览器:在浏览器地址栏输入Chrome://settings/content/javascript;
或设置–>高级–>隐私设置与安全性–>内容设置–>javascript
///火狐浏览器:在地址栏输入about:config 然后搜索javascript.enabled,双击
2、中间人攻击
在使用浏览器上传的时候,使用burp拦截抓包,通过更改文件后缀名形式达到绕过JS验证的效果,从而成功上传文件。
如我们向某网站上传webshell为PHP语言,原文件名为shell.php。前端JS校验只允许上传jsp或png格式的文件,我们可以将我们的webshell后缀名改为.jpg,并开启burp拦截,点击上传,从burp抓到的请求包中将文件后缀名修改为.php,选择放包则上传成功。


MIME-Type验证

1、MIME Typr常见分类

分类/描述 典型类型
text/表明是普通文本 text/plain,text/html,text/css,text/javascript
image/表示是某种图像,不包括视频文件,但是包括动态图 image/gif,image/png,/image/jpeg,image/bmp,image/webp
aydio/音频文件 audio/midi,audio/mpeg,audio/webm,audio/ogg,audio/wav
video/表示某种视频文件 video/webm,video/ogg
application/表示某种二进制数据 application/octet-stream,/pkcs12,application/vnd,mspowerpoint,application/xhtml+xml,application/xml,application/pdf,application/json

2、MIME TYPE验证

  1. MIME类型服务端检测
  2. 检查http包的Content-Type字段中的值
  3. 判断上传文件是否合法
  4. 验证成功

	if ($_FILES['userfile']['type'] !="image/gif") {
	......
?>

3、绕过MIME-Type验证

  1. 上传PHP文件
  2. 使用burpsuite拦截查看MIME类型(Content-Type类型)
  3. 发现PHP文件的MIME类型为application/octet-stream
  4. 服务端判断文件类型是否为image/gif(允许上传gif格式的文件)
  5. 无法通过MIME类型验证
  6. 需要将Content-Type改为image/gif
    在这里插入图片描述

4、Type绕过防御机制

  1. 目录设为不可执行----只要web容器无法解析该目录下的文件,即使攻击者上传了脚本文件,服务器本身也不会受到影响,因此此点至关重要。
  2. 判断文件类型----判断文件类型时,应结合MIME-Type、后缀检查等方式。推荐使用白名单的方式。
  3. 用随机数改写----文件上传如果要执行代码,则需要用户能访问到这个文件。在某些环境下,用户能上传,但是不能访问。

文件扩展名绕过

1、常见文件扩展名
文件上传漏洞简单绕过与防御机制_第1张图片
2、检查方式

  1. 黑名单----黑名单检测是一种不安全的方式,黑名单定义了一系列不安全的扩展名,服务器端一般有个专门的blacklist文件,里面会包含常见的危险脚本文件类型,在接收文件后,与黑名单扩展名对比,如果发现文件扩展名与黑名单存储的扩展名匹配,则认为文件不和发。
  2. 白名单----白名单检测方式与黑名单恰恰相反,黑名单是定义不允许上传的文件扩展名,而白名单则定义允许上传的文件扩展名,白名单拥有比黑名单更好的防御机制。

3、黑名单检测

  1. 定义blacklist
  2. 检查文件扩展名
  3. 判断上传文件是否合法
  4. 过滤危险脚本
 
 $Blacklist = array('asp','php','jsp','php5','asa','aspx');
 ......
 ?>

4、黑名单绕过

  1. 忽略的扩展名----攻击者可以从黑名单找到web开发人员忽略的扩展名,如cer、phtml等。
  2. 大小写转换----所示代码中并没有对接收到的文件扩展名进行大小写转换操作,那就意味着可以上传AsP、PhP之类的文件名绕过黑名单检测,而此类扩展名在windows平台依然会被web容器解析。
  3. windows特性----在windows系统下,如果文件名以“.”或者空格作为结尾,系统会自动去除“.”与空格,利用测特征也可以绕过黑名单验证。如上传“asp.”或者“asp ”扩展名程序,服务器接收文件名后在写文件操作时,windows将会自动去除小数点和空格。
  4. 双写后缀----双写后缀名绕过,用于只将文件后缀名,例如:上传时将Burpsuite截获的数据包中文件名【xxx.php】改为【xxx.phphpp】,那么开头的ph和结尾的p就结合又形成了【php】。

5、白名单检测
在获取到文件扩展名后对$WhiteList数组里的扩展名迭代判断,如果文件扩展名被命中,程序将认为文件是合法的,否则不允许上传


$WhiteList = array('rar','jpg','png','bmp','gif',jpeg','doc');
......
?>

6、白名单绕过

  1. IIS----IIS6.0攻击者把木马文件名改为xxx.php;1.jpg上传,此时文件格式为JPG格式,从而顺利通过验证,而IIS6.0会把xxx.php;1.jpg当做ASP脚本执行,最终攻击者可以绕过白名单检测,并执行木马程序。
  2. Apache----在Apache1.x 2.x中,对文件名的解析是从后行前解析的,直到遇到一个Apache认识的文件类型为止。如:phpshell.php.rar.rar.rar,因为Apache不认识.rar这个文件类型,所以会一直遍历所有后缀到.php,然后认为这是一个php类型的文件从而绕过白名单。

修改文件头

1、文件头验证

  1. 读取图像
  2. 检测第一个字节
  3. 判断上传文件是否合法
  4. 过滤危险脚本

文件头校验是使用对于文件内容的验证机制,这种方法利用的是每一个特定类型的文件都会有不太一样的开头或者标志位,也就是我们常说的文件幻数。

if (! exitf_imagetype($_Files['uploadedfile']['tmp_name'])) {
		echo "File is not an image";
		return;
	}

2、文件内容检测

  1. 读取图像
  2. 检测文件头
  3. 判断图片类型
  4. 过滤危险脚本
function isTmage($file){
		$fh = foprn($file,'rb');
		if($fh) {
				$bytes = fread($fh,6);
				fclose($fh);
				if ($bytes ==false){
					return false;
				}
				if (substr($bytes,0,3) == "\xff\xd8\xff"){
					return 'image/jpeg';
				if ($bytes == "\x89png\x0d\x0a"){
					return 'image/png';
				}
				if ($bytes == "GIF87a" or $bytes == "GIF89a"){
					return 'image/gif';
				}
		}
		return false;
}

浏览器的MIME Sniff实际上通过读取文件前256字节,来判断文件类型。
3、文件头绕过
伪造一个合法的文件头,将真实的PHP等脚本附在合法的文件头之后。
也就是说给上传脚本加上相应的幻数头字节就可以了,PHP引擎会将

GIF89A

phpinfo();>

你可能感兴趣的:(信息安全)