0x00 前言
最近Kaspersky Exploit Prevention成功检测到一系列0-day攻击,其中攻击者利用了Google Chrome浏览器中的一个未公开漏洞。我们第一时间向Google Chrome安全团队报告了该漏洞,Google在审核我们提供的PoC后,确认这是一个0-day漏洞,分配的漏洞编号为CVE-2019-13720。Google为Windows、Mac及Linux发布了新版的Chrome(78.0.3904.87),我们建议用户尽快升级到该版本。这里大家可以参考Google公布的安全公告。
Kaspersky将此次攻击标记为Exploit.Win32.Generic
。
我们将这些攻击行动称之为“Operation WizardOpium”,目前我们还无法将其与已知的攻击组织关联起来。此次攻击与Lazaru(拉撒路)攻击在代码上有较弱的相似性,但这可能是一种假阳性关联。目标网站在配置上与之前的DarkHotel攻击行动关联性更强,而DarkHotel攻击者最近也采取了类似的虚假攻击特征。
0x01 技术细节
此次攻击行动在韩语新闻门户网站上采用了水坑式注入技术,攻击者将恶意JavaScript代码插入主页面,恶意代码随后会从远程网站上加载配置脚本。
图1. 重定向到漏洞利用页面
主页面上托管着一个小型JavaScript标签,可以从hxxp://code.jquery.cdn.behindcorona[.]com/
处加载远程脚本。
该脚本随后会加载名为.charlie.XXXXXXXX.js
的另一个脚本,这个JavaScript脚本会对比浏览器的user-agent信息,判断浏览器是否运行在64位的Windows系统上,并且不以WOW64
进程运行,以检查受害者系统是否能被成功感染。此外,该脚本还会尝试提取浏览器的名称及版本。攻击者想利用的是Google Chrome浏览器中的一个bug,需要通过该脚本判断浏览器版本号是否大于或等于65(目前的Chrome版本号为78)。
图2. 脚本(.charlie.XXXXXXXX.js
)检查Chrome版本
如果浏览器版本满足条件,该脚本会向攻击者控制的服务器(behindcorona[.]com
)发起一系列AJAX请求,其中路径名以参数形式传入目标脚本(xxxxxxx.php
)。第一个请求用来获取某些重要的信息,以便后续利用。该信息包括若干个经过十六进制编码的字符串,指导脚本需要从服务端下载多少块(chunk)漏洞利用代码,字符串中也包含指向某个图像文件的URL,该文件中包含最终payload的秘钥以及用来解密利用代码chunk的RC4秘钥。
图3. 利用链:向xxxxxxx.php
发起AJAX请求
下载所有chunk后,RC4脚本会解密并将所有数据拼接在一起,这样攻击者就能构造出一个新的JavaScript代码,其中包含完整的浏览器漏洞利用代码。攻击者在payload解密过程中使用了之前提取到的RC4秘钥。
图4. 再次检查版本号
浏览器漏洞利用脚本经过混淆处理,去混淆后,我们观察到了一些有趣的信息:
1、脚本会再次检查user agent字符串,这一次要检查浏览器版本是否等于76或者77。这意味着漏洞利用代码只适用于这些版本(前面检查的是版本号大于或等于65),或者其他利用技术之前已在老版本的Chrome上使用过。
图5. 经过混淆的利用代码
2、脚本中有一些函数调用了浏览器的BigInt
内置类,该类可以用来在JavaScript代码中执行64位运算(比如在64位环境中处理原生指针)。通常情况下,漏洞利用开发者会实现自己的函数,通过32位数值来完成该任务。然而在此次行动中,攻击者使用的是BigInt
,由于该类由浏览器代码原生支持,因此运行效率应该更高。这里漏洞利用开发者并没有使用全部64 bit,只在部分bit上操作,这也是为什么攻击者要实现一些函数,用来处理高位/低位数值的原因所在。
图6. 处理64位数值的代码片段
3、有很多函数及变量并没有在实际代码中使用。这通常意味着这些函数及变量属于调试代码,在投入实际使用时没有被删除。
4、大部分代码使用了多个类,这些类与浏览器中存在漏洞的某个组件有关。由于该bug尚未被修复,这里我们并没有公布该漏洞组件的详细信息。
5、代码中还有一些大数组,用来表示shellcode代码及内嵌的PE映像。
为了遵循漏洞披露原则,这里我们提供的研究分析比较简单。浏览器的两个线程中缺少正确的同步机制,因此存在竞争条件bug,攻击者可以利用这一点,达到释放用重用(UAF)状态。这种状态非常危险,可能导致代码执行,而这次攻击者的确完成了该任务。
漏洞利用代码首先尝试触发UAF,(以指针形式获取)一些关键的64位地址信息。如果该步骤成功完成,攻击者可实现:1)如果成功获取地址,意味着漏洞利用代码正常工作;2)可以使用提取到的地址获取堆/栈的位置,绕过ASLR(地址空间布局随机化)机制;3)可以搜索该地址附近的其他一些有用指针,以便后续利用。
随后,利用代码尝试使用递归函数创建一大堆大型对象。该操作是为了获取特定的堆布局,确保漏洞利用能够成功完成。与此同时,代码尝试使用堆喷射技术,复用之前在UAF中被释放的同一个指针。攻击者可以通过这种技术制造混乱,(从JavaScript代码角度来)操作两个不同的对象,虽然这两个对象实际上位于相同的内存区域。
利用代码尝试执行各种操作来分配/释放内存,也使用了其他技术,最终攻击者成功实现了任意读/写原语。攻击者通过这种方式构造一个特定的对象,与WebAssembly
及FileReader
配合使用,以执行嵌入式shellcode payload。
图7. 第一阶段shellcode
0x02 Payload解析
最终下载的payload为经过加密的二进制文件(worst.jpg
),由shellcode负责解密。
图8. 经过加密的payload:worst.jpg
经过解密后,恶意软件模块以updata.exe
形式保存到本地磁盘上并执行。为了实现本地驻留,恶意软件会在Windows Task Scheduler中创建计划任务。
installer
payload为RAR SFX归档文件,具体信息如下:
文件大小: 293,403
MD5: 8f3cd9299b2f241daf1f5057ba0b9054
SHA256: 35373d07c2e408838812ff210aa28d90e97e38f2d0132a86085b0d54256cc1cd
归档文件中包含两个文件:
两个文件对应的信息分别为:
文件名 iohelper.exe
MD5: 27e941683d09a7405a9e806cc7d156c9
SHA256: 8fb2558765cf648305493e1dfea7a2b26f4fc8f44ff72c95e9165a904a9a6a48
文件名: msdisp64.exe
MD5: f614909fbd57ece81d00b01958338ec2
SHA256: cafe8f704095b1f5e0a885f75b1b41a7395a1c62fd893ef44348f9702b3a0deb
这两个文件编译时间相同,都为“2019年10月8日 01:49:31”。主模块(msdisp64.exe
)尝试通过硬编码的C2服务器列表下载下一阶段payload,下阶段payload位于C2服务器上,具体路径对应受害者的计算机名,因此攻击者知道哪些主机已被成功感染,会将对应的模块放置在C2服务器的特定目录中。
0x03 IoC
behindcorona[.]com
code.jquery.cdn.behindcorona[.]com
8f3cd9299b2f241daf1f5057ba0b9054
35373d07c2e408838812ff210aa28d90e97e38f2d0132a86085b0d54256cc1cd
27e941683d09a7405a9e806cc7d156c9
8fb2558765cf648305493e1dfea7a2b26f4fc8f44ff72c95e9165a904a9a6a48
f614909fbd57ece81d00b01958338ec2
cafe8f704095b1f5e0a885f75b1b41a7395a1c62fd893ef44348f9702b3a0deb
kennethosborne@protonmail.com