20199102《网络攻防实践》综合实践
20199102-孙启龙-FUSE: Finding File Upload Bugs via Penetration Testing
Lee T, Wi S, Lee S, et al. FUSE: Finding File Upload Bugs via Penetration Testing[C]//2020 Network and Distributed System Security Symposium. Network & Distributed System Security Symposium, 2020.
Abstract
不受限制的文件上传(UFU)漏洞是严重的安全威胁,它使攻击者可以将其选择的伪造文件上传到目标Web服务器。当攻击者能够通过触发其URL来执行上载文件的远程代码执行时,此错误会演变为“不受限制的可执行文件上载(UEFU)”漏洞。我们设计并实现FUSE,这是一种渗透测试工具,旨在发现服务器端PHP Web应用程序中的UFU和UEFU漏洞。 FUSE的目标是生成上载请求。每个请求都会成为触发UFU或UEFU漏洞的漏洞利用有效载荷。但是,这种方法面临两个技术挑战:(1)它应生成一个上传请求,以绕过目标Web应用程序中存在的所有内容过滤检查; (2)应该保留生成的上传文件的执行语义。我们通过使用精心设计的变异来更改标准上传请求来应对这些技术挑战,这些变异可以绕过内容过滤检查,并且不会篡改上传文件的执行。 FUSE发现了30个以前未报告的UEFU漏洞,其中包括来自33个实际Web应用程序的15个CVE,从而证明了FUSE通过文件上传查找代码执行错误的功效。
Introduct
共享用户提供的内容已成为现代Web应用程序的事实上的标准功能。 Facebook,Instagram和Twitter越来越多地邀请用户上传自己的图片,视频和文字帖子。 内容管理系统(CMS)是另一个支持文件上传的代表性Web应用程序。 WordPress [23]和Joomla [10]平台合计占CMS市场份额的65%[20],使用户能够上传其图像,PDF和TAR文件。 此上载功能是服务器端Web应用程序支持的普遍功能。
同时,上载功能会带来安全风险,攻击者可以将其任意文件上载到目标服务器,并将其用作垫脚石,以提供更多机会破坏目标系统。因此,对于Web应用程序开发人员来说,至关重要的是防止攻击者滥用此上传功能。缓解该问题的一种普遍做法是实施内容过滤检查,以禁止上传构成严重安全风险的指定文件类型。例如,WordPress禁止其用户上传任何PHP文件,因为对手可以执行即上传了一个PHP文件,该文件允许不受限制地访问内部服务器资源。
不受限制的文件上传(UFU)[18]是一个漏洞,它利用服务器端Web应用程序中的内容筛选检查中的错误。攻击者称为上传攻击者,利用她的有限权限通过利用UFU漏洞来上传格式错误的文件。成功上传伪造的文件会带来潜在的代码执行风险[18]。系统管理员在审核新文件时可能会意外运行此伪造但仍可执行的文件,或者现有软件中的错误可能有助于执行上载的文件。
当攻击者能够通过其URL触发上载文件的代码执行时,此UFU漏洞将变得更加严重。 这意味着对手可以通过调用URL来执行任意代码执行。 我们将内容过滤检查中的错误称为“不受限制的可执行文件上传(UEFU)”漏洞,其中(1)它允许上传可执行文件,并且(2)对手能够在目标网站上远程运行此可执行文件 服务器或受害者的浏览器(通过调用URL)。
以前有关于检测各种Web漏洞的研究。 通过静态分析[43,49,63,65]或动态执行[29,53],尝试使用多种技术来检测Xt和SQLI等污点样式的漏洞。 为了发现逻辑错误[59,62]和产生攻击漏洞[26],也已经进行了执行符号执行的研究。 但是,很少有研究解决发现U(E)FU漏洞的问题[40]。
贡献:在本文中,我们提出了FUSE,这是一种旨在确定U(E)FU漏洞的渗透测试系统。 渗透测试是一种广泛实践的测试策略,尤其是在发现安全性漏洞方面[32,44,48,51]。 渗透测试的无价优势之一是它会产生触发固有漏洞的实际漏洞。 每个报告的漏洞有效载荷都可以帮助审核员更好地了解系统漏洞,并确保其较低的安全级别。
渗透测试的有效性仅取决于生成可能触发U(E)FU漏洞的输入,这带来了两个技术挑战:(1)FUSE应该生成一个上传请求,绕过目标Web应用程序中存在的特定于应用程序的内容过滤检查 成功上传; (2)成功的上传请求应下载目标Web服务器或浏览器能够执行的文件。
为了解决这些挑战,我们提出了一种基于变异的新颖算法,用于生成引发U(E)FU漏洞的上传请求。 FUSE首先生成四个种子上传请求; 每个请求都会尝试上传PHP,HTML,XHTML或JS文件。 目标应用程序可能会阻止这些种子请求,因为每个请求都试图上载可执行文件,而该文件对于目标应用程序是不允许的。
因此,FUSE通过应用13种精心设计的突变操作的组合来突变每个种子请求。我们设计了每个选项,以帮助绕过内容过滤检查并保留种子文件的执行语义。具体来说,我们定义了五个目标,这些目标在实施内容过滤检查时会引发常见错误。然后,我们实施了具体的变异方法,每种方法均至少实现了一个目标,从而解决了第一个挑战。同时,这些变异操作不会篡改种子文件可由目标执行环境执行所需的约束,因此保留了种子文件的执行语义。也就是说,这些突变是解决上述两个技术挑战的关键组成部分。然后,FUSE将这些生成的请求发送到目标PHP应用程序,以尝试上传种子文件的变异变体。最后,它通过访问其URL来检查上载的文件是否可执行,该URL是从给定的配置文件计算出来的,或者是从目标服务器上的文件事件监视工具获得的。
我们在33种流行的现实世界Web应用程序上评估了FUSE。 FUSE发现了30个带有相应上传请求的UEFU漏洞,这些漏洞导致任意代码执行。 这些上载请求是触发固有漏洞的有价值的测试输入,从而帮助开发人员了解其根本原因。 我们将所有调查结果报告给了相应的供应商,并收到了15个CVE。
总而言之,本文证明了使用精心设计的变异操作进行有效的渗透测试是可行的,这些变异操作不会篡改种子文件的代码执行,但在绕过内容过滤检查方面仍然有效。 因为我们的基于变异的测试策略与用于发现Web漏洞的现成渗透测试工具[3,32,44]兼容,所以FUSE能够为扩展到涵盖U(E)FU漏洞的那些测试工具做出贡献。
Background
我们解释了在PHP服务器端Web应用程序中上传文件的一般过程。 然后,我们描述UFU和UFU漏洞及其安全影响。
File Upload in PHP Web Applications
PHP是一种流行的服务器端Web编程语言。 在Alexa排名前1000万的站点中,大约80%的Web服务器使用PHP来实现各种服务,包括CMS和社交论坛[21]。
上载功能是PHP支持的一项关键功能。 常见的上载过程始于客户端浏览器发送源自HTML表单的HTTP(S)多部分请求[50]。 该请求通常通过POST发送,这体现了用户对本地文件的选择。此上载请求的收件人PHP解释器提取文件,然后将其移动到php.ini中指定的临时目录。 最后,由该上载请求调用的PHP应用程序执行内容过滤检查,以确定上载的文件是否符合开发人员的期望。
<?php
$black_list = array('js','c','php3',...,'php7')
if (!in_array(ext($file_name), $black_list)) {
$file_path = $base_path . sanitize($file_name)
$uploaded = move($tmp_file_path, $file_path);
}
else {
message('Error: forbidden file type');
}
?>
上述代码显示了Monstra CMS应用程序中的内容过滤检查的示例。 第三行通过ext函数从上载的文件名中提取扩展名,然后检查该扩展名是否属于第二行硬编码的列入黑名单的扩展名。它禁止上载具有潜在安全威胁的列入黑名单的扩展名的任何文件。 最后,第五行将上载的文件从临时目录移动到已清理的文件路径,第四行计算该路径以指定应该在其中存储上载文件的上载目录。
UFU and UEFU Vulnerabilities
UFU漏洞[18]是一个安全漏洞,使攻击者可以上传开发人员不希望接受的任意文件。 此漏洞源于内容过滤检查的错误实现,该检查旨在仅接受可接收的文件。 例如,Monstra不接受其客户端的JS文件,如图1中的Ln 2所示,这构成了潜在的安全威胁。 但是,假设有人上传了bypass.Js文件,其中包含任意JS代码。 此文件触发UFU漏洞,因为它绕过了Ln 3中的内容过滤器检查,该检查以区分大小写的方式检查文件扩展名。 此上载的JS文件会带来潜在代码执行(PCE)的风险。 上载攻击者可以滥用运行易受攻击的Monstra的主机来分发可以在受害者的浏览器上运行的恶意JS脚本。
在本文中,我们将无限制可执行文件上传(UEFU)漏洞定义为UFU漏洞,该漏洞允许通过导致上载可执行文件的URL进行任意代码执行(CE)。 因此,UEFU漏洞是UFU漏洞的子集。 我们仅考虑允许文件上传的UFU和UEFU漏洞,这些漏洞可由PHP解释器或浏览器执行。 具体来说,我们专注于确定U(E)FU漏洞,这些漏洞使能够上传四种文件类型:PHP,HTML,XHTML和JS。 每种文件类型要求使用不同的条件来导致PCE或CE。
PHP: 当(1)上载攻击者能够通过利用UFU漏洞来上传PHP文件并且(2)攻击者能够通过公开访问的URL执行该上载的文件时,被利用的UFU漏洞成为UEFU漏洞,从而导致 远程CE。 例如,考虑对手成功上传了如下的的简单PHP Web Shell代码。 由于可以通过具有任何精心设计参数的URL调用上载的脚本,因此对手可以执行任何系统命令。 这构成了严重威胁,攻击者便能够访问本地文件资源和数据库[4],注入shell命令和脚本[37]并进行服务器端请求伪造(SSRF)攻击[56]。
<?php
system($_GET['c']);
?>
.htaccess:是一个Apache配置文件,其中包含每个目录的配置指令。 它通常定义文件所在目录下文件的访问控制策略,并确定PHP解释器应运行哪些文件扩展名[1]。 PHP应用程序开发人员可以通过实现.htaccess来限制允许访问上载文件的入口点。 在这种情况下,攻击者无法通过URL调用上传的PHP文件。 但是,它仍然可以视为导致PCE的UFU漏洞。 考虑一个带有本地文件包含(LFI)[16]的易受攻击的Web应用程序,该程序允许攻击者嵌入任何服务器端文件来执行此应用程序,如以下示例所示。无论是否存在可公开访问的URL,Web攻击者都可以利用此LFI漏洞来执行上载的PHP。
<?php include($_GET['page']); ?>
(X)HTML:上载的HTML或XHTML文件也是注入恶意JS代码的关键攻击媒介,从而带来了CE威胁。 假设对手通过上载下文所示的HTML文件来扮演网络攻击者的角色[31],并诱使受害者访问导致该上载文件的URL。 因此,攻击者可以代表受害者使用易受攻击的Web服务器来源触发执行恶意JS脚本。 这样一来,就可以不受限制地访问受受害人的Cookie和受相同来源策略(SOP)[57]约束的本地存储中的敏感信息。 根据定义,这是一种存储的跨站点脚本攻击[17]。 任何基于域的内容安全策略(CSP)[36、54、60、61]几乎都无法提供保护,因为呈现恶意HTML文件的URL在目标Web服务器域内。
<html>
<script>
alert('xss');
</script>
</html>
JS: 允许上传JS文件的UFU漏洞构成了PCE威胁。 许多网络级防火墙或CSP使用域名来阻止内容资源请求,这些请求是通过黑名单或白名单来获取JS文件的。 通过将恶意JS脚本上传到易受攻击的Web服务器,攻击者可以将这些恶意JS脚本分发给受害者,或者绕过将该易受攻击的Web服务器列为可信赖的CSP [47,64]。
Related work
MIME混淆攻击。巴特等。 [30]提出了内容嗅探XSS攻击,该攻击针对Web浏览器和目标网站的内容文件过滤逻辑之间的差异。他们证明可以通过利用上传的PDF文件来存储XSS。但是,它们涵盖了一部分UEFU漏洞,这些漏洞利用了主要浏览器的内容嗅探算法。 FUSE考虑了更多不同的攻击媒介,这些攻击媒介通过文件上传来启用CE,例如将攻击代码放置在SVG文件中以及上传包含攻击PHP代码的映像。 Jana等。 [41]提出了变色龙攻击,它们利用远程环境中的恶意软件检测器与实际主机应用程序中的文件解析算法之间的文件类型推断启发法中的差异。
而且,已经进行了许多尝试来利用PNG或PDF变色龙来发现嗅探XSS的内容[9,24,52]。我们的框架受这些工作方法的启发,但我们的目标是逃避很少解析文件的CMS Web应用程序中的文件过滤逻辑。此外,我们在变异操作中考虑了许多攻击媒介,这些攻击媒介除了变色龙攻击外还可以触发U(E)FU漏洞。
查找网络漏洞。先前的研究提出了静态分析来识别数据流漏洞,包括XSS和SQL注入[43,49,63,65]。 Backes等。 [28]提出了一种可扩展框架,用于从PHP Web应用程序计算代码属性图[66]。作者利用对计算图的遍历来识别XSS和SQLI漏洞。 Doupé等。 [35]和Payet等。 [55]确定了EAR漏洞,这些漏洞是控制流错误,可以在重新定向后继续执行。 Lee等。 [46]手动分析了渐进式Web应用程序的安全性和隐私性,并报告了滥用独特渐进式Web功能的新方法。
Saner [29]验证了定制消毒程序的安全性。它使用自动机实例静态地逼近变量可以在某些程序点保存的字符串值,然后检查接受转义字符的可行性。对于后续步骤,它随后将攻击字符串动态注入到预定义的测试套件中以消除误报。这种方法显然适用于发现U(E)FU漏洞。但是,他们的方法需要将各种PHP内置函数建模为换能器,这需要不懈的工程努力。
关于将符号执行应用于PHP Web应用程序,有几本著作[26,40,59,62,65]。黄等。 [40]进行了符号执行,以发现允许上传PHP文件的UEFU漏洞。他们将有关文件写入功能(即move_uploaded_file或file_put_content)的PHP内置函数建模为易受攻击的接收器,并设计了可访问性约束条件,以确保可从受污染的源(即$ _FILES)访问此类函数。他们还设计了扩展名约束,以确保上载的PHP文件确实具有PHP样式的文件扩展名。因此,他们的目标是检查是否可以使用PHP样式的文件扩展名上传任意文件。他们在9,160个WordPress插件上评估了其工具,仅发现了三个漏洞。另一方面,FUSE考虑了除扩展以外的多个突变向量,例如Content-Type和Content,应将其考虑为从33个应用程序中发现复杂的U(E)FU漏洞。
NAVEX [26]引入了自动漏洞利用生成框架。它结合了静态和动态分析,以识别从源到易受攻击的接收器的路径,同时考虑了消毒过滤器,并通过解决符号约束来生成漏洞利用字符串。 Son和Shmatikov [59]提出了SAFERPHP,它利用污点分析和符号执行来发现语义错误。 THAPS [42]是一个网络扫描仪,它应用符号执行来模拟所有可能的执行路径,并进行污点分析,作为发现缺陷的后期处理。 Sun等。 [62]进行了带有污点分析的符号执行,以识别电子商务应用程序中的逻辑漏洞。他们的工具探索了结帐节点之间的关键逻辑状态,包括付款状态。
Motivation
本节描述了威胁模型以及攻击者利用FUSE旨在发现的U(E)FU漏洞的具体功能。 然后,它描述了系统地发现U(E)FU漏洞的两个技术挑战,并总结了我们应对这些挑战的方法。
Threat Model
我们假设一个上载攻击者。 攻击者具有上载由目标Web应用程序授予的合法文件的有限特权; 她无法使用任何其他系统级上载通道,例如安全文件传输(SFTP)或安全复制协议(SCP)。 例如,上载攻击者可能是WordPress网站的注册用户。 攻击者只能按照开发人员预期的访问控制角色执行有限的操作。 也就是说,除了WordPress提供的嵌入上传功能外,她无法使用其他措施上传任何文件。 攻击者的目标是在服务器端PHP解释器或客户端浏览器上载启动CE的文件,并随后通过可公开访问的URL触发上载文件的执行。 攻击者可以利用现有的LFI漏洞来启动上传文件的执行[16]。
Technical Challenges
查找UEFU漏洞需要进行两个技术挑战:(1)识别特定于应用程序的内容过滤检查中的错误,以及(2)确认此类错误是否允许PHP解释程序或浏览器成功上传可执行文件。
特定于应用程序的检查。 不同的应用程序以独特的方式实现自己的内容过滤检查。 图1和图3显示了两种不同类型的内容过滤逻辑。 Monstra的内容过滤逻辑仅检查用户提供的文件扩展名是否符合预定义的扩展名黑名单。 另一方面,下述代码中WordPress的内容过滤逻辑是从第五行的文件名中提取扩展名开始的。当给定的文件是图像时,第六行的省略逻辑将推断其MIME类型,计算出real_mime。 如果未确定real_mime,则第九行通过调用finfo_file内置函数根据其内容从给定文件推断其MIME类型。第十六行最后通过利用文件扩展名和内容中的两种推断出的MIME类型,检查给定文件是否可接受。
<?php
function check_filetype_and_ext($file, $filename, $mimes) {
// Infer a type from filename.
$filetype = check_filetype($filename, $mimes);
...
if($type && !$real_mime && extension_loaded('fileinfo')) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$real_mime = finfo_file($finfo, $file);
// Check an inferred MIME type.
if(!in_array($real_mime, array('application/octet-stream',..),true)){
$type = $ext = false;
}
}
...
$allowed = get_allowed_mime_types();
if (!in_array($type, $allowed)){
$type = $ext = false;
}
}
?>
更糟糕的是,一些应用程序在其应用程序的不同位置实现了内容过滤逻辑。 因此,即使进行手动分析,也很难理解其基本逻辑。 在由33个流行CMS组成的基准测试中,我们观察到没有应用程序实现相同的内容过滤逻辑。
这种工程实践在识别此类特定于应用程序的内容筛选检查中的错误时带来了技术挑战。 大多数Web应用程序都没有附带其允许文件的规范,也没有附带说明是否已检查的注释。 识别或引入此类规范以开始任何程序是一个挑战性的问题[34、49、58]。 此外,仅对内容过滤检查的识别还不够。 找到能够绕过此类检查但背离开发人员期望从而触发错误的测试输入至关重要。
符号执行当然适用于系统地查找内容过滤检查中的错误。 然而,当进行符号执行时,上述工程实践成为问题。 本质上,符号执行需要规避在内容过滤检查之后精确定位代码位置的规范。 这项要求要求对目标应用程序有深入的了解,因此可能会阻碍那些想要测试各种应用程序的领域知识较少的审核员对其应用程序的使用。
可执行的上传文件。 还有另一个技术挑战。 内容过滤检查中的错误应允许成功上传目标Web服务器或浏览器可以执行的文件。 解决这一挑战需要回答以下研究问题:应在上传的文件中保留哪些约束,以使其可以通过Web服务器或浏览器执行? 识别此类约束要求深入了解Web服务器和浏览器执行给定文件的行为。
我们的方法。 我们着重于发现U(E)FU漏洞,这些漏洞允许对使用Apache或三个主要浏览器(即Chrome,Firefox和Internet Explorer)的PHP解释程序执行的上载种子文件执行代码。 为此,我们提出了一种渗透测试系统来应对上述两个技术挑战。
为了解决第一个挑战,我们建议通过提供伪造的上载请求来引发意外的错误行为,这些请求可能触发固有的错误,同时避免生成针对特定于应用程序的检查的预期语义的规范。 特别是,在生成上载请求时,我们将应用经过精心设计的变异操作,以帮助绕过错误的应用程序特定检查,其根源来自开发人员的常见错误。
我们还将分析Chrome,Firefox,Apache和PHP引擎的源代码,以确定可执行文件所需的约束。 生成上载请求时,我们确保将这些已确定的约束保留在上载请求的攻击文件中,这解决了第二个挑战。 另外,在第VII-D节中,我们证明了由于软件更新而对这些约束所做的更改很少,以至于大多数突变变体的执行在不同版本的Chrome,Firefox,Safari和PHP引擎之间保持一致。
给定目标服务器端Web应用程序,FUSE接收一组种子文件和一个配置文件。 然后,FUSE启动渗透测试活动。 在活动期间,FUSE通过应用13种精心设计的变异操作的组合来变异种子文件的上传请求,并通过发送那些请求来尝试上传变异的种子文件。 活动结束后,FUSE将报告功能上载请求,以证明存在U(E)FU漏洞。
上图1说明了FUSE的总体架构,它由三个组件组成:链协调器,上载代理和上载验证器。 在较高的层次上,这些组件协同工作以执行三个步骤;(1)链协调器为四个种子文件中的每个文件准备测试策略; (2)UPLOAD AGENT建立上传请求,根据测试策略对这些请求进行变异,并发送这些变异的请求,以尝试上传种子文件的变体; (3)UPUP VALIDATOR检查上传的文件是否可以通过公开访问的URL访问和执行。
链协调器。 链协调器构造一种测试策略,称为链表。 它指定如何生成一系列突变的上传请求。 此链列表中的每个链都包含一个FUSE应用于种子上传请求的变异操作的列表。 因此,每个突变的上传请求是将链中的突变应用于种子上传请求的计算结果。
上载代理。 该模块负责为给定的种子文件生成一个上传请求,并根据链协调器计算出的给定链来改变原始请求。 目标应用程序通常需要完成身份验证过程,并与每个尝试的上载请求一起发送有效的CSRF令牌。 因此,UPLOAD AGENT解决了身份验证过程,并附加了有效的CSRF令牌以促进上载过程。
上传验证器。 UPUP VALIDATOR检查生成的请求是否成功上传文件,并获取这些上传文件的公共URL。 通过通过计算的URL访问这些文件,UPLOAD VALIDATOR检查上传的文件是否可执行
Design
给定一个配置文件,FUSE进行三个阶段。 第一阶段为每个种子文件计算一种测试策略,我们将其称为链表。 阶段II通过为每个种子文件构造一个种子请求,根据链表对这些种子请求进行变异并发送变异的请求来执行此测试策略。 第三阶段获取导致成功上传文件的可访问URL,并检查这些上传文件的执行能力。
Specifying a Testing Campaign
FUSE接受两个输入:一组种子文件和一个配置文件。每个种子文件都成为构建标准上传请求(称为种子请求)的源。 FUSE还使用用户提供的配置文件,该文件为目标PHP应用程序指定参数。
/* Required Parameters */
login_page = [Login page URL.],
credential = {
id = [Username.],
pw = [Password.]
},
upload_page = [Uploading page URL.],
token_re = [Regex for matching a CSRF token.],
/* Optional Parameters */
success_re = [Regex for a successful upload.],
response_re = [Regex for file URLs.],
url_prefix = [Common prefix of file URLs.],
上述代码显示了配置模板。它指定了认证凭证,登录和上载网页的URL以及FUSE从中提取令牌的CSRF令牌字段。 Lines(Lns)10-12中的参数是可选的,因为某些应用程序可能不需要它们。它们指定如何获取上载文件的URL。 V-D节详细说明了FUSE如何利用每个参数。
我们认为,指定此配置文件对于查找U(E)FU漏洞而言是可以接受的成本。广泛的Web渗透测试工具需要相当的配置工作。 SQLmap [14]要求审核员指定登录cookie凭据,目标URL和参数以注入有效负载。 Arachni [3]和Burp [5]默认情况下会爬网目标URL和注入参数,但仍需要相同的信息以提供更好的覆盖范围和精确的扫描。 Zap [25]利用其网络代理工具来生成站点地图并通过用户交互来指定攻击目标,从而系统地生成此类配置信息。
定义success_re,response_re和url_prefix参数需要FUSE的额外配置成本。 success_re参数指示上载尝试是否成功。 response_re和url_prefix参数用于计算导致上传文件的URL。在目标Web服务器(§V-D)上使用文件监视器时,可以省略这些参数。但是,这些参数存在以支持测试方案,在该方案中,放置“文件监视器”不是一个可行的选择。
Phase I: Chain Coordination
此链协调步骤将生成一个测试策略,该策略指定如何更改给定的种子请求。回想一下,链是突变操作的列表。这种测试策略需要一个链列表,我们称之为链列表。该链协调的目的是穷举探索所有可行的突变组合,从而有助于FUSE生成各种上载请求并发现新的错误。请注意,每个变异操作都旨在绕过一种内容过滤检查。因此,这些组合的确增加了绕过多个内容过滤检查的几率。我们的评估表明,如果不考虑突变组合(§VII-D),FUSE可能会遗漏许多错误。
链协调器首先为每个种子请求创建一个初始链表。对于每个种子请求,它将对所有适用的变异操作进行排列,然后按链长排序。例如,如果适用于HTML种子的变异操作是M1,M2和M3,则链表如下。
HTML: {∅, M1, M2, M3, M1M2, M1M3, M2M3, M1M2M3}
在两个不同的变异操作修改种子请求的重叠部分的情况下,它们可能会相互冲突。 链协调程序可删除此类虚假链以清除不必要的突变。 例如,如果M1与M2冲突,则先前示例的修订链列表将变为以下内容。
HTML: {∅, M1, M2, M3, M1M3, M2M3}
链协调器的另一个功能是根据从第三阶段获得的先前的上载尝试结果来删除链,以进行有效的渗透测试。 如果一条链有助于成功上传,则“链协调器”会清除包括该成功链的所有其他链。 由于链表是根据其链长排序的,因此FUSE总是选择一条短链,而不是其他包含此短链的较长链。 我们的目的是报告成功利用漏洞的独特最小长度链。 例如,如果链M1成功触发了UFU漏洞,则链协调器将从链列表中删除包括M1的所有其他链,如下所示:
另外,如果the链(即种子请求未发生任何突变)触发了UFU漏洞,则链协调器将删除链表中的所有链。 换句话说,当种子请求成功上传其种子文件时,FUSE不再发送源自该种子请求的其他变异的上传请求。 当目标应用程序没有采取任何措施来防止UFU漏洞时,找到各种测试用例就变得毫无意义。 另一方面,如果种子请求失败,则表明存在内容筛选检查,FUSE针对该内容筛选检查执行渗透测试活动。
Phase II: Mutating and Sending Upload Requests
上载代理通过执行目标Web应用程序的身份验证过程开始。 它利用给定配置文件中的login_page和凭据参数来构造身份验证请求,并发送此请求以完成身份验证过程。 然后,上传代理通过更改种子请求来生成上传请求并发送这些请求。 下述算法1描述了此上传过程。 它获得给定的配置文件(conf),种子文件(种子)和链。 它首先在Ln 2中分配一个唯一标识符,该标识符是用于以后的验证过程的参考索引。
function Upload(conf, seed, chain)
unique ← RandStr(32)
url ← conf.upload_page
tokenu ← ExtractTokens(url, conf.token_re)
request ← ConstructRequest(url, tokenu, seed)
for m ∈ chain do
request ← MutateRequest(request, m)
request ← PostProcess (request, unique)
response ← SendRequest (url, request)
return request, response, unique
由于目标Web应用程序通常需要有效的CSRF令牌,因此ExtractTokens函数可从上传页面动态提取CSRF令牌。 它在内部获取上传的网页,并利用conf中指定的常规表达式提取与CSRF令牌相对应的form元素。 然后,Ln 5中的ConstructRequest函数构造一个种子请求,尝试通过添加提取的CSRF令牌来尝试上传种子。 然后,上载代理通过应用链中的每个突变来突变种子,如Lns 6-7所示。 Ln 8对变异的上载请求执行后处理,以方便后续的验证过程。 具体来说,它将更改上载文件名,为其分配一个唯一值,然后将此值附加到要上载文件的注释部分中。 最终,Ln 9中的SendRequest函数将经过变异和后处理的请求发送到目标url,并返回从目标应用程序接收到的响应。
Phase III: Upload Validation
UPUP VALIDATOR执行三个任务:(1)检查每个尝试的上传请求是否成功将文件拖放到托管目标应用程序的Web服务器上;(2)计算导致上传文件的URL; (3)确认获取的URL是否调用了上传文件的执行。 作为审核成功上传的第一个任务,默认情况下,UPLOAD VALIDATOR检查上传请求的响应是否没有任何错误消息。 UPUP VALIDATOR利用配置文件中定义的正则表达式(success_re),该正则表达式检查响应中是否存在指示成功上传的模式。
对于第二项任务,上传验证器具有三种不同的方法来获取上载文件的URL。 由于各种应用程序在将URL分配给上载文件方面有所不同,因此我们将其归纳为三种方法。 我们从最简单的方法到最复杂的方法对这些方法进行说明。
URL的通用前缀。 UPUP VALIDATOR使用用户提供的参数url_prefix,该参数指示导致所有上载文件的URL的公共前缀。 如果设置了此参数,则UPVAL VALIDATOR会简单地将用url_prefix提取的URL值和上载文件名连接起来,从而生成最终的URL。
上载回应和摘要网页。 包括HotCRP在内的多个应用程序都在响应上载文件的请求时显示上载文件的URL。 上传验证器利用用户提供的参数response_re提取指向该上载文件的URL。
代替检查上传响应,UPLOAD VALIDATOR能够引用指定的摘要页面,该页面列出了所有导致上传文件的可访问URL。 UPUP VALIDATOR利用算法1中的唯一标识符。每个URL在其文件路径中已经具有一个唯一标识符,并且从该URL提取的内容在其主体中包含一个唯一标识符。 因此,通过使用唯一标识符作为连接密钥,上传验证器能够将每个URL映射到上传请求。
文件监视器。 前两种方法高度依赖于用户提供的参数以及对目标应用程序的理解。 此外,一些应用程序使用随机文件名作为其上载文件,并且不提供摘要页面,这使得定义url_prefix和response_re参数变得不可行。 为了处理这种情况,UPLOAD VALIDATOR使用文件监视器。 文件监视器是安装在托管目标Web应用程序的Web服务器上的监视组件。 它是一次性设置工具,可监视Web根目录下的任何文件创建事件。
对于每个创建事件,文件监视器都会存储所创建文件的绝对路径及其内容的MD5哈希值。 当UPVAL VALIDATOR发送哈希值以检索导致成功上传文件的URL时,文件监视器将以与文件哈希值匹配的已存储绝对路径进行响应。 UPLOAD VALIDATOR通过将Web根目录替换为Web服务器域名,从接收的绝对路径计算URL。
最后,UPLOAD VALIDATOR验证每个获取的URL是否确实调用了上载文件的执行,该文件可能与其种子文件不同。 对于PHP种子文件,我们实现了动态生成“ FUSE_GEN”的代码。UPLOAD VALIDATOR通过其URL调用此种子的变异版本,并检查响应页面是否包含“ FUSE_GEN”,这表明PHP变体的CE成功 。 否则,“上传验证器”将考虑诸如PCE风险之类的情况。
对于上传的HTML,JS或XHTML文件,上传验证器检查上传请求中包含的尝试上传文件与从获取的URL提取的上传文件之间的差异。 如果没有差异,则这些上载的文件极有可能是可执行文件,因为所应用的任何变异都不会篡改变异文件的执行。 接下来,UPLOAD VALIDATOR检查响应中的Content-Type标头是否在我们选择的10种MIME类型中。 回想一下JS,HTML和XHTML文件是在客户端浏览器上执行的,这些浏览器在Content-Type标头中引用MIME类型,以确定所获取的内容是否可执行。我们凭经验收集了上述10种MIME类型。 对于每个JS或(X)HTML种子文件,我们在更改Content-Type标头值的同时获取MIME类型,并检查它们是否确实可以在Chrome,Firefox或Internet Explorer无头浏览器中执行。
Uploading .htaccess
FUSE进一步检查了上载.htaccess文件的可行性。 如果上载攻击者能够控制.htaccess文件,则她可以调用PHP解释器来执行带有任何扩展名的上载文件,并使该上载文件可访问。 这是一个关键的安全威胁,它使具有PCE风险的UFU漏洞演变为导致CE的UEFU漏洞。
具体来说,在完成阶段III之后,FUSE尝试上载任意的.htaccess文件。 我们对该.htaccess文件进行了编程,以允许PHP解释器执行任意扩展。 为了检查.htaccess文件是否已成功上传,FUSE上传了另一个任意图像文件,其元数据嵌入了PHP种子文件中。 然后,它通过调用导致该图像文件的URL,通过PHP解释器验证上载图像文件的执行。
Mutation operations
突变的主要目标是以给定的上载请求保留其种子文件的执行语义的方式来转换给定的上载请求,并且经过变异的请求可能会绕过内容过滤逻辑。为了实现该目标,我们首先确定了上载攻击者能够操纵的突变载体。假设有一个利用这些突变向量的上载攻击者,我们进行了一项初步研究,以识别开发人员在执行内容过滤检查中的常见错误。
初步研究。我们调查了已知的CVE,互联网上现有的回避技术以及先前的研究[30,41]。我们还研究了成熟的应用程序利用哪些内置方法对包括WordPress和Joomla在内的9种流行应用程序进行内容过滤检查。基于这些调查,我们将现有的攻击技术概括为利用不同类型的开发人员错误的五个目标。然后,我们设计了13个操作,每个操作都实例化了一个或两个已定义的目标,从而触发了固有的错误并绕过了已放置的内容过滤逻辑。请注意,我们的工作提出了13种操作中的5种(即M5,M7,M9,M10和M13)。
执行约束。设计每个突变时,我们调整了操作以保留种子文件的执行语义。我们调查了Apache Web服务器或浏览器执行该文件所需的给定文件的基本约束。我们手动分析了Chrome 74,Firefox 68,八个不同版本的Apache mod_php模块和PHP 5.6解释器引擎的源代码,以了解应保留哪些约束以便可执行种子文件。
我们观察到PHP解释器执行的PHP文件包含PHP开始标记(即<?php或<?)。 但是,PHP解释器的此调用由Apache mod_php模块控制。 此模块需要一个可执行的PHP文件具有七个PHP样式的文件扩展名之一(例如php3,phar),以便通过直接的URL调用执行。 在Chrome和Firefox浏览器中,我们还确定了可执行HTML文件必须在其前512个字节内以预定义的开始标签开头,并带有有效的HTML代码,该代码与Barth等人的模型很好地吻合。 提取[31]。 可执行XHTML文件与HTML情况共享相同的约束,但需要存在xmlns标记。 我们还研究了其他浏览器支持的文件类型(即SVG和EML),这些文件类型可以体现JS脚本。 在执行每个变异操作时,我们确保它们反映了这些约束,从而防止变异篡改这些约束。
突变载体。 FUSE更改HTTP(S)多部分请求[50]的字段,该请求通常由客户端构建以将文件和数据上传到Web服务器。 图6表示HTTP多部分请求的标准消息格式。 在上载请求的请求主体中(图6),FUSE考虑了三个突变向量来修改其对应字段:(1)扩展,(2)Content-Type和(3)Content。 从文件的角度来看,每个向量表示如下。
- 扩展名:文件名的扩展名。
- Content-Type:文件的MIME [38]类型。
- 内容:文件的二进制内容或纯文本。
突变目标。以下列举了从上述初步研究得出的五个关键目标。
1)检查是否没有内容过滤检查:我们观察到一些应用程序不对传入的上传请求执行任何检查。 FUSE通过发送每个可执行种子文件的种子请求而不应用任何突变来实现此目标。
2)根据内容引发错误的类型推断:此目标是受以前的方法启发的,这些方法生成的文件的推断类型在不同的执行环境之间有所不同[30,41]。他们展示了变色龙攻击,该变色龙将一种文件伪装为另一种文件,从而逃避了恶意软件检测器或浏览器的类型推断启发。我们扩展了这种想法,以在Web应用程序和运行上载文件的执行环境之间对上载文件类型引起不同的看法。具体来说,我们旨在从PHP内置函数(包括finfo_file和mime_content_type)(引用了Content部分)导致错误的类型推断。
3)根据扩展利用不完整的白名单或黑名单:我们观察到不同的应用程序在指定禁止的扩展名(黑名单)或允许的扩展名(白名单)方面有所不同。目的是利用扩展名白名单或黑名单的这种不一致,这提供了允许上传不允许的文件的机会。
4)绕过基于内容的关键字过滤逻辑:目标是绕过搜索某些特定于程序的关键字的应用程序的过滤逻辑,包括<?php,<\h\t\m\l>和<\s\c\r\i\p\t>,以推断上载的文件类型。
5)绕过基于Content-Type的过滤逻辑:我们观察到一些应用程序经常接受Content-Type中指定的MIME类型,而不检查Content中文件的实际类型。目标是注入不正确的MIME类型以绕过内容过滤检查。
表一总结了我们为解决上述五个目标而设计的突变操作清单。请注意,实现第一个目标不需要更改,因为接受没有更改的种子请求就意味着没有内容过滤检查。每种突变都针对至少一个目标,并且对应于某些种子文件。例如,M1旨在实现第二个目标,并且仅适用于上载HTML或PHP种子文件的两种种子请求类型。
变异冲突。回顾第V-B节,我们为每个突变操作预定义了一组冲突的突变操作,并在创建链表时排除了此类冲突的操作。对于给定的操作(M 1),我们将冲突的突变(M 2)定义为:(1)M 1和M 2都修改了突变载体的相同部分,或者(2)M 1与M 2结合导致了CE失败,因此使M 2不必要。在枚举13个突变集的排列时,我们丢弃了其中一个突变操作与其他突变操作相冲突的组合。
M1:在资源标头之前。 M1将六个资源文件(GIF,JPG,PDF,PNG,TAR_GZ和ZIP)的文件头的1024字节添加到给定上传请求的内容中。 因此,应用M1意味着为每个资源文件生成一个变异请求,从而生成六个不同的变异请求。 目的是欺骗目标PHP应用程序的类型推断启发法。 筛选出恶意文件的常用方法是推断其类型并基于推断的类型拒绝文件。 我们观察到几个PHP应用程序通过将准备好的签名与文件的标头部分匹配来推断文件类型。 这种观察使我们定义了M1操作。 M1适用于PHP和HTML种子请求; 但是,M1不适用于JS和XHTML,因为没有浏览器能够执行带有资源文件头的JS或XHTML文件。
M2:将种子插入资源元数据中。 M2将给定上传请求的内容注入六个资源文件(JPG,PNG,GIF,ZIP,PDF和BMP)的元数据部分,从而生成六个不同的突变。 FUSE分析每个资源文件的结构,并标识包括注释元数据的特定块块。 之后,我们的系统将上传文件作为评论元数据注入到该区块中。 最后,FUSE使用修改后的资源文件的相应值更改种子请求中的内容。 例如,FUSE将PHP种子注入GIF89a元数据的注释部分。 与尝试上载不完整资源文件的M1不同,M2上载完整的资源文件,以便大多数图像查看器呈现其缩略图和图像而不会出现任何错误。 我们检查了M2操作不会篡改PHP和HTML文件的代码执行。
M3:更改上载请求的内容类型。 M3将上载请求的内容类型更改为六个资源文件(JPG,PNG,GIF,TAR_GZ,ZIP和PDF)的一种MIME [38]类型。我们观察到某些应用程序利用了上传请求正文的Content-Type,而不是根据其内容来推断上传文件的类型。 M3操作可有效绕过此类滤波逻辑。因为此操作仅更改Content-Type值,所以M3适用于所有种子文件。
M4:更改文件扩展名。此操作将给定上传请求的扩展名更改为七个PHP样式扩展名之一或17个预定义的公共扩展名之一。因为FUSE会尝试这些扩展中的每一个,所以对于给定的上传请求,它会产生19个变异的请求。我们观察到,Web应用程序通常使用扩展名黑名单来防止攻击者上传恶意文件。对于此操作,我们的目标是尝试各种不同的通用扩展,包括PHP样式的扩展,这些扩展可能会调用目标PHP解释器或有助于绕过内容过滤检查。我们从八个不同版本的Apache mod_php模块中收集了PHP样式的扩展,每个模块都指定哪个扩展集调用PHP解释器。例如,phar是mod_php为PHP 7.2支持的新扩展。因此,开发人员还应更新其内容过滤逻辑,以阻止Phar文件。 M4旨在识别每个列出的扩展的内容过滤逻辑的省略。 M4适用于所有种子类型。
M5:替换PHP标签。 M5用短标签(即<?)替换给定上传请求内容中的默认PHP开头标签(即<?php)。它旨在绕过仅搜索默认PHP开头标记的内容过滤逻辑。 M5专为PHP种子文件而设计。
M6:将HTML转换为EML。通过更改上传请求,此操作会将给定上传请求的内容中的HTML文件转换为电子邮件(EML)[6,38]。 EML是Microsoft Outlook,Mozilla Thunderbird和Apple Mail使用的电子邮件文件的标准格式。有趣的是,EML文件能够包含带有脚本元素的HTML文档。 M6首先将准备好的EML文件的标题添加到Content的开头。然后,它将内容中的HTML特殊字符转换为十六进制格式,以便转换后的HTML代码执行代码执行。最后,它将给定种子请求的扩展名更改为eml扩展名。我们观察到Internet Explorer 9、10和11执行EML格式的HTML。因此,M6适用于(X)HTML种子文件。
M7:删除文件扩展名。 M7操作旨在删除给定上传请求的扩展,该扩展可能有助于绕过内容过滤检查。不幸的是,我们观察到几个Web应用程序不检查文件扩展名本身的存在。由于此操作仅涉及请求的扩展,因此适用于所有种子类型。
M8:将文件转换为SVG。 SVG是XML的文件格式,代表矢量图像;它有助于将HTML代码嵌入其文件中。 M8将HTML文件嵌入到准备好的可伸缩矢量图形(SVG)[15]文件中。 M8将准备好的SVG文件的开始和结束标签附加到给定上传请求的内容的开始和结束处。此外,此操作将请求的扩展名更改为svg。由于SVG文件格式仅支持在HTML文档中嵌入,因此M8操作仅适用于HTML文件。
M9:在HTML注释之前。在此操作中,由任意字符串组成的HTML注释的4,096字节位于给定请求的内容之前。我们基于以下事实设计M9:XE应用程序的内容过滤逻辑检查上载文件的标题部分中是否存在指示JS脚本或HTML文档的关键字。例如,XE搜索<\h\t\m\l>或<\s\c\r\i\p\t>在标题部分,但不在整个文件中。通过利用此信息,M9将HTML注释标签(即<!-,->)添加到原始HTML种子文件的内容之前,从而绕过了内容过滤逻辑。同时,由于注释开始标签的前512个字节存在,因此Chrome浏览器和Firefox浏览器将变异文件推断为可执行HTML文件。此操作旨在执行HTML类型的文件,从而使该操作适用于HTML和XHTML种子文件。
M10:将文件扩展名更改为不常见的扩展名。M10将给定请求的扩展名更改为不常见的扩展名(例如,保险丝)。与M4和M7类似,此操作旨在绕过基于黑名单的扩展筛选检查。我们观察到,几个Web应用程序的过滤逻辑不会对不常见的扩展名执行内容过滤逻辑,因为它们不知道如何检查这种不常见的文件类型。我们注意到,M10突变的文件的CE取决于Web服务器是否执行内容嗅探[2]。在默认的Apache设置中,Apache不会对扩展名不常见的文件执行内容嗅探。这邀请浏览器通过执行内容嗅探来基于文件的内容来推断文件类型。当浏览器确定其MIME类型为HTML时,上载的文件将变为可执行文件。这是经典的MIME混淆攻击[12]。 M10适用于HTML和JS种子文件。
M11:将文件扩展名转换为大写。M11执行将给定请求的扩展名中的第二个字符更改为大写的操作。此操作利用了检查目标Web应用程序的文件过滤逻辑与Apache服务器的类型推断模块之间的文件扩展名的差异。考虑一个目标应用程序,由于内容过滤器逻辑有问题,该应用程序允许上传带有hTml扩展名的HTML文件。现在,当受害者访问此上载的文件时,Apache Web服务器以不区分大小写的方式检查其文件扩展名,并将Content-Type标头指定为推断的text / html类型。受害人的浏览器由于其内容标题而将其作为HTML执行。也就是说,目标应用程序认为该文件不是HTML文件,但是其Web服务器自动注入推断出的text / html MIME类型,从而产生CE。 M11适用于所有种子。
M12:附加文件扩展名。此操作将给定扩展名添加到预定义的14个扩展名(包括png,jpg和zip)之前,添加到给定种子请求的扩展名中。例如,M12通过将gzip附加到扩展名,将上载文件的扩展名从.php更改为.gzip.php。许多应用程序根据其扩展名评估上传文件的MIME类型,以过滤掉可疑文件类型。我们设计M12来欺骗有缺陷的内容过滤逻辑,该逻辑通过检查扩展名之前的扩展名(gzip)而非原始扩展名(php)来推断文件的MIME类型。 M12适用于所有种子。
M13:追加资源标头。 M13将预定义JPG文件的八个字节的标头附加到给定上传请求的内容的末尾。因此,上载的文件具有两个文件签名:一个来自原始种子文件,另一个来自预定义的JPG文件。目标是更改上传请求,以便上传的文件导致目标应用程序无法推断文件的正确MIME类型。我们观察到finfo_file内置函数返回此格式错误的文件的两种MIME类型。 M13通过创建具有多个文件签名的文件来滥用这种误解。此操作适用于所有文件类型。
Eveluation
我们评估了FUSE以发现U(E)FU漏洞(§VII-B),并将其与最新的渗透测试工具(§VII-C)进行了比较。 我们还分析了行使突变操作(§VII-D)的功效。 最后,我们对发现的漏洞(§VII-E)进行案例研究。
Experimental setup
我们对表II第一栏中列出的33个PHP Web应用程序进行了一系列实验。我们从三个方面选择了支持上传功能的基准测试应用程序:(1)NAVEX覆盖的评估集[26]; (2)W3Techs [20]列出的流行CMS应用程序; (3)PHP评分最高的CMS项目,在GitHub [500]上有500颗星,报告其安装没有错误。根据W3Techs统计资料[20],这些应用程序具有至少5,600个站点使用的上传功能[20],或者已受到GitHub开发人员的广泛关注。我们故意排除了不支持上传的应用程序。每个PHP应用程序在内容过滤逻辑的实现上都不同。这种趋势有助于测试FUSE在发现U(E)FU漏洞中的广泛适用性。
环境。我们在具有Intel Core i7-7700(3.60 GHz)CPU和32 GB RAM的Linux工作站上运行FUSE。对于使用我们基准测试的目标系统,我们使用了Linux工作站和Intel Core i7-8700(3.20 GHz)CPU,32 GB的RAM。我们在测试的目标系统上安装了Ubuntu 16.04,Apache 2.4和PHP 5.6。对于某些要求PHP版本高于5.6的应用程序,我们使用了单独的Docker容器以及PHP 7.0和7.1。对于每个PHP解释器,我们故意启用PHP短标签,因为在5.3以下的PHP版本中默认支持这些短标签,在使用PHP的Alexa前1000万个网站中,这些短标签占Web服务器设置的15.1%[22]。
Discovering UFU and UEFU Vulnerabilities
表II总结了FUSE发现的错误。第二列描述了FUSE尝试的上传请求总数。当一条链有助于触发UFU或UEFU漏洞时,FUSE会清除其他包含此成功链(§V-B)的链。此机制会修剪不必要的上载请求,从而触发与较短的变异链已经调用的漏洞相同的漏洞。因此,总请求数随导致成功上传的链数而变化。请注意,对ECCube3,DotPlant2和Codiad的尝试请求总数为5,因为它们允许上传四个种子和.htaccess文件,这表明没有内容过滤检查。
表II中的CE列显示了通过上传PHP,HTML和XHTML的变体成功找到UEFU漏洞的请求数。这些列中的任何正数表示相应的应用程序具有UEFU漏洞。例如,对于Microweber,FUSE生成了26个不同的上载请求,每个请求都能够将可执行的PHP文件拖放到目标Web服务器上。此外,上载攻击者能够使用URL调用这些PHP文件,从而启用远程CE。
表II中的PCE列表示成功上载可能的可执行PHP和JS文件的上传请求数。第八列指示应用程序是否允许上载.htaccess文件。如果应用程序允许.htaccess上载,则我们用✓标记,否则用mark标记。第九列显示应用程序是否需要文件监视器。如果应用程序使用文件监视器,则我们用✓标记,否则用✗标记。 24个应用程序不需要文件监视器。为了研究不应用文件监视器的可行性,我们实现了一个配置文件,以为每个应用程序指定文件上载Oracle。如果将File Monitor放在目标服务器上进行测试是可行的,则配置任务将变得更加容易,从而使FUSE成为灰盒测试工具。最后一列显示FUSE完成渗透测试活动的执行时间。
UEFU漏洞。 FUSE报告了23个应用程序中的30个可利用的UEFU漏洞,其中包含176个不同的上传请求有效负载。这23个易受攻击的应用程序包括流行的PHP应用程序,例如WordPress,Concrete5,OsCommerce2和ZenCart。估计部署这五个应用程序的网站数量从5,600到300万个不等[20]。
我们没有将176个不同请求中的每个报告为一个漏洞,而是保守地计算了UEFU漏洞的不同原因。 我们利用了突变操作的五个关键目标(§VI),因为每个目标都旨在利用不同的漏洞原因。 对于一个链列表,每个链都有助于在176个请求中产生一个成功的上传请求,我们计算了多个具有相同突变目标的链作为一个漏洞。 也就是说,我们计算了具有不同突变目标的链组。 例如,考虑FUSE报告四个突变链的情况,每个突变链对应一个成功的上传请求:
我们将它们视为三个漏洞,因为M1和M2操作共享相同的根本原因(目标2),尽管它们的上传请求和应用的变异完全不同。 M4M9链是两次突变操作的结果,其根本原因是由于开发人员共同犯下了两个错误(目标2和3)。 这种方法有助于避免重复计算具有相同根本原因的漏洞。
我们向相应的供应商报告了全部30个UEFU漏洞,并从9个应用程序中获得了15个CVE。 已修复来自五个供应商的八个漏洞。 来自包括WordPress在内的4个供应商的5个漏洞确认已解决了所报告的漏洞。 15个错误正在等待相应厂商的确认。 两家供应商拒绝修补报告的错误。
在30个UEFU漏洞中,有14个漏洞需要利用管理员级别的特权才能加以利用。我们强调,对于这14个UEFU漏洞中的9个,已实施的内容过滤检查禁止为应用程序管理员上载我们的种子文件。因此,这些UEFU漏洞表现出开发人员的错误,从而导致意外的远程CE。请注意,即使Web主机和Web应用程序管理员可能不同,成熟的Web应用程序甚至也限制了其应用程序管理员的上传功能,因此仅强制允许文件的上传。例如,网络托管管理员通常将应用程序管理员与主机管理区分开来,例如通过SFTP或SCP上载文件,并且仅向他们提供对指定托管应用程序的访问权限[33]。众所周知,恶意应用程序管理员已利用UEFU漏洞上传Web Shell,以获得对主机资源的访问权限[33]。
我们仔细检查了每个上传的文件是否导致了远程CE。在176个上传请求有效负载中,有一个针对MyBB的上传请求和两个针对XE的上传请求为误报(1.7%)。对于一个MyBB误报的情况,MyBB在URL中将随机令牌附加到导致上传的文件。 FUSE能够在文件监视器的帮助下检索此URL。在基准测试中,其他应用程序使用随机URL,并将这些URL提供给上载攻击者可以参考和利用的网页。但是,MyBB没有提供泄漏此随机URL的页面,因此攻击者只剩下一个选择:猜测URL。因此,我们将其标记为误报。报告的URL确实调用了U(E)FU漏洞。但是,这不能说明攻击者难以猜测URL的事实。 XE的两个误报包括在应用M6之后上载HTML和XHTML文件。我们发现XE删除了上载文件的扩展名(.eml),从而在将Content-Type标头设置为响应时使Web服务器无法推断MIME类型。这将强制浏览器获取此资源,以通过内容嗅探来推断获取的资源类型。我们使用Chrome,Firefox和Internet Explorer测试了这些上传的文件。每个浏览器都将它们呈现为文本文件,从而导致无法执行。对在上载的文件上运行Internet Explorer进行此附加验证可以消除这两个误报。但是,引入此附加步骤会使我们的工具依赖于各种无头浏览器执行环境。无需执行此步骤即可验证Content-Type标头(§V-D)满足了我们的目标,几乎没有误报。
我们观察到ECCube3,DotPlant2,SymphonyCMS,OsCommerce2,ClipperCMS和Codiad允许上载.htaccess文件,这带来了对安全性至关重要的后果。现在,攻击者可以诱使Apache Web服务器为任何文件扩展名调用PHP解释器,从而使PHP解释器可以执行任何上载的文件。例如,攻击者能够为OsCommerce2上传49个独特的PHP变体,如表II所示。这些上载的文件具有PCE的风险。但是,攻击者可以对.htaccess文件进行重新编程,并为49个PHP变体中的每个变体调用PHP解释器,从而启用CE。因此,我们将有关.htaccess上载错误的所有发现报告给了供应商,并从OsCommerce2和ClipperCMS获得了两个CVE。
性能。 FUSE的执行时间因目标应用程序而异,因为FUSE会调用特定于应用程序的上传功能。 Elgg,ECCube3,DotPlant2和Codiad用了不到两秒钟的时间,因为它们允许上载所有四个种子文件。在这种情况下,FUSE不会尝试查找更复杂的示例,因为它们没有执行内容过滤检查(§V-B)。另一方面,FUSE花了100多分钟的时间来完成针对XE,SilverStripe,HotCRP和Collabtive的渗透测试。这些延迟源于它们内部处理与请求关联的并发会话的实现。他们使用了PHP会话内置方法,这些方法通常会在锁定会话文件之前挂起,直到进行中的请求将会话文件解锁为止[13]。也就是说,这些应用程序并非旨在处理来自一个会话的批量请求。其他应用程序实现自己的会话处理方法,或在生成响应完成之前显式解锁会话文件。
Comparison against State-of-the-Art Penetration Testing Tools
我们将FUSE与两个最新工具进行了比较:fuxploider [7]和UploadScanner [19]。 Fuxploider是一个开放源代码上传漏洞扫描工具,UploadScanner [19]是Burp Suite Pro(用于Web应用程序安全测试的商业平台)的扩展。 我们选择这些工具是因为它们是可从GitHub获得的渗透测试工具,并且专门用于查找U(E)FU漏洞。
我们使用相同的基准对两个扫描程序进行了测试,并通过应用相同的计数标准对漏洞进行了计数。 我们从报告的错误中手动检查了每个成功的漏洞利用及其原因。 表III总结了每种工具发现的漏洞。 请注意,虽然fuxploider仅尝试上传PHP文件,但是UploadScanner上传PHP和HTML文件来触发CE,以及JS文件来触发PCE。 为了公平比较,我们比较了每种种子文件类型的FUSE性能。
PHP CE。关于上传PHP文件,FUSE发现的漏洞是fuxploider和UploadScanner发现的两倍多。由于多个实施问题,Fuxploider从五个应用程序中遗漏了五个UEFU漏洞。例如,当目标应用程序生成带有内容编码标头为gzip的上载响应时,该工具会生成执行错误。 Fuxploider也无法检索随机URL来检查是否存在上载的文件,FUSE的File Monitor可以支持该URL。
与上载扫描程序相比,FUSE还发现了另外七个UEFU错误。应用M4时,考虑到各种PHP样式的扩展(包括pht和php7),FUSE的功能产生了四个UEFU错误。但是,UploadScanner仅尝试两个渗透测试扩展:php5和phtml,因此无法找到这四个bug。剩下的三个UEFU错误是由于无法检索随机URL和区分大小写比较匹配文件名所致。 UploadScanner仅根据预定义的文件名计算上传URL。当目标应用程序将此文件名更改为小写时,UploadScanner变得无法检查此文件的成功上传,从而产生假阴性结果。
HTML CE。对于涉及HTML文件的UEFU错误,FUSE发现的错误比UploadScanner多出九个。九个错误中的七个是由于文件监视器模块和上载的上载扫描程序的其他杂项实现问题引起的。其余两个错误是由M9和M13操作发现的。例如,FUSE通过尝试将M4和M13组合使用从WordPress中发现了UEFU错误,而UploadScanner无法识别该错误。
JS PCE。关于带有JS种子的UFU错误,FUSE和UploadScanner之间存在19个常见错误。尤其是,由于上述相同的问题以及无法利用文件监视器,UploadScanner错过了七个错误。在两个应用程序中,FUSE遗漏了两个错误,这些错误涉及将JS净荷注入到GIF元数据中,因为FUSE并未将M2应用于JS文件。通过修改突变操作之间的冲突规则,可以很容易地修复这些假阴性。
Effectiveness of Mutations
操作意义。图7说明了每个突变的频率。每个直方图都对应一个诱变操作,其高度代表使用此突变的成功上传请求的总数。我们观察到,每个突变都被用来生成至少五个触发UFU漏洞的上传请求。这表明每个突变都是必不可少的。请注意,通过达到最高频率,M4操作明显优于其他操作。回想一下,应用M4操作意味着为每个扩展生成一个上载请求,从而导致19个不同的请求,每个请求都尝试伪造自己的扩展。 M4操作的有效性还表明,许多应用程序基于文件扩展名实施错误的内容筛选检查。
链长。我们还测量了触发U(E)FU漏洞的每个链长的频率。如图8所示,FUSE报告了45、419、314和28个上传请求,其链长分别为零,一,二和三。链长度为零表示没有突变的上传请求会触发UFU漏洞。我们观察到,FUSE通过应用单个突变发现了许多错误,这表明每个突变在绕过内容过滤检查方面都非常有效。我们还观察到,触发28条上传请求引发了UFU漏洞,原因是应用了长度为3的链。考虑到FUSE协调最短链来触发UFU漏洞,这些长链的存在意味着很难手动找到这些bug。
漏洞原因。表IV列出了将突变应用于各自的突变目标后,FUSE发现的漏洞数量。第一个目标的列显示,FUSE发现了14个UFU和13个UEFU漏洞,其中包括四个由于不进行任何内容过滤检查而导致的CVE。为第三个目标设计的突变是最有效的,有助于发现21个UFU和14个UEFU漏洞,包括11个CVE。 FUSE报告了这些目标以及实际的有效载荷利用,可帮助用户了解发现的U(E)FU漏洞的根本原因。
约束一致性。请注意,这13个变异操作旨在保留种子文件的执行语义。但是,当目标执行环境(包括Web浏览器和PHP解释器)由于其软件更新而改变了它们的执行约束时,这些突变操作应反映出这种改变。
我们测试了执行约束在不同版本的浏览器和PHP解释器之间如何保持一致。具体来说,我们检查了从一个种子文件变异而来的可执行文件是否仍可在不同的执行环境中保持可执行。对于PHP,HTML,XHTML和JS种子文件,我们应用了长度小于3的13个突变的所有组合链,从而准备了一组突变的种子文件。然后,我们测试了它们是否可以在不同版本的浏览器和PHP解释器中执行。在此实验中,我们部署了Chrome(版本53、61、69和77),Firefox(版本49、52、62和69),Internet Explorer(版本9、10和11)和Safari (版本10、11、12和13)检查JS和(X)HTML变体的执行约束。对于每种浏览器,我们选择了过去四年(2016-2019年)每年十月发布的稳定版本。我们还针对不同版本的PHP解释器和启用PHP短标签(版本5.2、5.6、7.0、7.1、7.2和7.3)的Apache mod_php模块测试了PHP变体。
我们观察到,除一种情况外,所有可执行的JS和(X)HTML变体在不同版本的浏览器中都保持一致。它表示,在这些浏览器的不同版本中,提取出的约束不会有太大变化,随着这些软件的发展,我们的变异也无需更改。一个异常情况是由Internet Explorer 9引起的。InternetExplorer 10和11可执行由M2突变的JS文件。但是,Internet Explorer 9将此图像/ JS文件的元数据部分中的JS有效负载视为未终止的注释,因此没有执行。但是,此JS文件可被Chrome,Firefox和Safari的每个版本执行,这表明当受害者使用Chrome,Firefox或Safari时,该JS文件将是可执行的。
请注意,在四个不同版本的Safari中,所有变异的(X)HTML和JS文件都保持一致,我们在设计13个变异时并未进行分析。此观察表明,提取的约束与浏览器无关,因为不需要任何更改即可生成将删除Safari可执行(X)HTML和JS文件的上传请求。
具有不同PHP样式扩展名的PHP文件的执行随PHP版本的不同而不同。例如,仅通过PHP 7.2和7.3才能通过URL使用phar定向调用和执行PHP文件。除了扩展名带来的差异外,导致PCE的突变PHP文件的执行结果在不同的PHP解释程序中也是一致的。
我们得出的结论是,浏览器更新对FUSE生成可执行上载文件的功能影响很小。至于PHP解释器更新,随着时间的推移,FUSE可能需要使用解释器更新来覆盖更多PHP样式的扩展。
Case Studies
在下文中,我们将调查FUSE的发现,以及其突变操作如何有助于发现这些bug。 我们特别关注来自Concrete5,Joomla和Microweber的UEFU错误。
结构5。 图9显示了一个上载的SVG文件,该文件在Concrete5中调用CVE-2018-19146。 此上载文件是更改后的上载请求的结果,该请求是将M8操作应用于HTML种子请求的结果。 Concrete5允许用户上传图像,并将SVG文件视为图像,如图10所示。 但是,白名单允许对手上传带有嵌入有任意JS脚本的HTML代码的SVG文件,从而导致CE。
Joomla。 Joomla实现了严格的内容过滤逻辑,该逻辑不允许使用PHP脚本上载任何文件,从而阻止了PCE。 FUSE生成了一个上载请求,该请求成功删除了一个可执行PHP,如图11所示。该上载的文件是同时应用M1,M4和M5操作的结果。 省略任何这些突变操作都会导致不绕过Joomla中的内容过滤检查。 这种情况说明FUSE能够生成复杂的输入,从而触发目标Web应用程序中的错误行为。 它还表明,仅应用单个突变不足以发现UFU漏洞。
Microweber。 图12显示了一起应用M4和M13操作之后的种子PHP文件的变体。 Microweber在内部管理文件扩展名和MIME类型的黑名单。 因此,Microweber从每个上传请求中提取文件扩展名并推断MIME类型,然后将其与黑名单匹配。 这种情况滥用了不在黑名单上的pht扩展名,并通过将JPG标头附加到其内容将推断出的MIME类型更改为application / octet-stream。 M4和M13都是触发此UEFU漏洞(导致CE)的关键。
我们提出了捕获常见的开发人员错误并实现13个突变的五个目标。我们承认,存在其他实现相同目标的突变方法。但是,提出的目标足够一般,用户可以建议自己实现相同目标的突变。例如,第二个变异目标是通过操纵Content导致错误的类型推断。我们为finfo_file内置函数触发了错误的类型推断。但是,用户可以实现不同的突变,该突变将带来相同的结果,并将其与FUSE集成在一起以减少可能的假阴性。
我们手动检查了浏览器和PHP解释器(§VI)的执行约束,并在设计13个突变时反映了这些约束。因此,当嵌入在这些软件中的这些约束由于其更新而发生更改时,也应修改这些突变以反映这些更改(第VII-D节)。这些执行约束的自动提取[30]以及这种约束对变异的反映是我们留给未来研究的有趣的技术挑战。
我们观察到,导致UFU漏洞的最常见错误是使用扩展名不完整的黑名单或有缺陷的白名单。这种趋势源于开发人员对构成低安全风险的文件类型的无知。例如,它需要特定领域的专业知识才能知道SVG和EML文件能够执行嵌入式脚本。此外,嵌入在上传请求中的文件扩展名通常受上传攻击者的控制。因此,基于用户提供的扩展名推断上传文件类型为进一步的攻击打开了一扇门。开发人员应检查给定文件的实际内容,以确定其可接受性[18]
另一个漏洞来源是由于智能浏览器执行内容嗅探。 假设攻击者尝试上载目标应用程序接受的攻击文件。 在某些情况下,承载应用程序的Apache服务器无法推断上载的文件类型,因此在对该文件请求的响应中不放置Content-Type标头。 这邀请浏览器通过执行内容嗅探来基于文件的内容来推断文件类型,上载攻击者会利用该内容嗅探。 对于Web服务器无法推断其类型的上载文件,我们建议设置X-Content-Type-Options标头以启用nosniff,这可防止浏览器执行内容嗅探[11]。 调整Apache配置文件以设置此标头的默认值将阻止攻击。 此外,Web应用程序可以使用应用程序推断出的特定文件类型指定标头,从而防止攻击。
Conclusion
我们建议使用FUSE,这是一种旨在发现U(E)FU漏洞的渗透测试工具。 我们提出了13种变异操作,它们转换可执行种子文件以绕过内容过滤检查,同时在目标执行环境中保持可执行状态。 我们在33个真实的PHP应用程序上评估了FUSE。 FUSE发现了30个UEFU漏洞,其中包括15个CVE,这表明FUSE在通过文件上传查找代码执行错误的实用工具。
\x89\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48... #1024 bytes of PNG binary
<?
$sn = pack('H*', dechex(2534024256545858215*2));
echo $sn;
# $sn set to "FUSE_GEN" after the Ln #4.
...
?>