大家好,我是ABC_123。上周写了一篇《史上最严重的APT供应链攻击事件,借助Solarwinds攻击欧美的流程图梳理和分析(上篇)》反响还不错。由于该APT供应链攻击事件极其复杂,所以大约需要写5至6篇文章。本期继续分享第2篇,讲述其中用到的Sunburst后门的设计思路,以及它如何实现绕过流量检测的。
ABC_123对网上大量的分析文章进行总结,排除掉多数人看不懂的二进制分析内容,争取用最通俗易懂的语言,让大家明白这款顶级后门的设计思路,给大家的攻防带来启示。相信大家看了文章之后,会直观地体验到顶级APT组织设计的后门有多么强悍。
按照惯例,首先放出一张ABC_123绘制的关于Solarwinds供应链攻击事件中Sunburst后门的设计思路及流程图,是从大量的Sunburst后门样本分析文章中归纳整理出来的,接下来依据此图,详细讲解整个后门工作过程。
Sunburst后门是如何被编译进Orion软件中的,上一篇文章有详细介绍,这里就不叙述了。Sunburst携带了合法的Solarwinds合法数字签名,这种方式自带白名单效果,完美绕过各种防护措施。最终该dll文件被打包在Orion网管软件的更新补丁中,一旦受害者安装此补丁就会导致Sunburst后门触发,但是它不是立即运行的,会经过一系列复杂的初始化条件判断,比如是否在真实的受害者的计算机环境中运行,以及是否有杀软防护,父进程是否合理等。
Sunburst后门将会从Solarwinds公司的Orion软件中的XML配置文件中读取ReportWatcherRetry的值,借此判断是否继续运行,只有其值不为3的时候才会继续运行。
该XML配置文件的ReportWatcherRetry值会返回3、4、5三种值,分别对应了Truncate、New、Append三种持久化状态,默认值为4(New)。4(New)表示后门第一次运行,5(Append)表示告诉后门先前已在系统上运行,但因存在预定条件(如主动防病毒软件)而退出,3(Truncate)意味着该后门应当立即停止运行。
Part3 后门触发的8个必要条件
注:Sunburst后门在执行条件判断阶段,会频繁使用OrionImprovementBusinessLayer.DelayMin()方法随机休眠/延迟30-120分钟,延迟代码执行速度,这样可以降低被自动化分析防护软件发现的概率。
通过计算父进程名的hash值,判断运行进程是否为SolarWinds.BusinessLayerHost.exe或SolarWinds.BusinessLayerHostx64.exe,而且hash算法是自定义的。这一步是规避沙箱检测或者调试工具,避免沙箱自动化检测或者安全人员分析。
3 等待10几天后运行
随机设置后门激活时间,会随机等待12天到14天逐步触发恶意代码。这样做的目的是让全球1万8千多家Orion软件用户的被控服务器逐步上线,避免集中上线被流量监控设备发现并告警,导致计划败露。很多单位会在7后清除日志,所以足够的等待时长也可以减少日志记录。
4 创建命名管道防止多实例运行
后门创建名为583da945-62af-10e8-4902-a8f205c72b2e的命名管道,放置多示例运行。
5 检查配置文件状态参数
检查XML配置项ReportWatcherRetry的值,判断当前Sunburst后门所处的状态,如果是New或者Append状态的话继续运行。
6 本地域名黑名单检查
1. 获取AD域并通过Hash和正则判断是不是黑名单中的值,如swdev.local,swdev.dmz、saas.swi等,其中swi对应着"SolarWInds Internal",swdev对应着"SolarWinds Develop"。2. 不能包含solarwinds 关键字。3. 该域名不得与正则表达式(?i)([^a-z]|^)(test)([^a-z]|$)匹配,简单来说,它不能看起来像是一个测试环境域名。
7 检测是否存在杀软进程、服务、驱动
1. 进程黑名单检查
通过SearchAssemblies方法检查是否有进程黑名单,查看是否有Windbg、Winhex、Autoruns、Wireshark、dnSpy、apimonitor-x64、fiddler、idaq64、ollydbg、procdump64、x64dbg等进程存在。
2. 服务黑名单检查
通过SearchServices方法检测是否有黑名单服务名,例如Windows Defender、Carbon Black、Crowdstrike Falcon、FireEye - EDR等。如果遇到黑名单服务,Sunburst会通过修改注册表,将服务禁用掉。
3. 安全软件驱动黑名单检查
通过SearchConfigurations方法调用WMI查询,Select * From Win32_SystemDriver检测是否有驱动黑名单,比如groundling32.sys等。
8 确认网络连通性
通过CheckServerConnection方法解析api.solarwinds.com域名,做网络联通性检测,只有通过检测才会进一步执行,否则就会退出,等待下次执行。
1 dga域名通信阶段概述
在以上环境检测都通过之后,Sunburst后门会进入使用dga域名的DNS通信阶段。DGA域名通信包括两个阶段:第一个阶段主要向攻击者C2反馈计算机域名信息,便于攻击者根据这些信息筛选目标;第二阶段主要反馈安全防护软件的状态信息,便于攻击者了解目标杀软、edr等部署情况。这些信息加密隐藏在DGA域名的第一个分段中,Sunburst后门攻击者根据Sunburst后门收集的计算机域名信息及安全防护软件信息,挑选了大约100家有价值的目标进行内网横向。
2 唯一标识符userid
部分受害者计算机基础信息过大(比如说计算机域名过长),需要发送多次DGA域名请求才能完整地把计算机域名信息传输完毕。为了能够区分不同计算机的dga域名请求,把来自于同一计算机的dga域名的分段信息解密后组合到一起,Sunburst对于每台计算机都会计算一个唯一的标识符userid。
对于每台受感染的计算机,userid由受害者的MAC地址、windows域名,windows计算机唯一标志符GUID(即Windows安装时随机生成并存储在HKLM\SOFTWARE\Microsoft\Cryptography\MachineGuid的注册表值)这3个值经过自定义的加密算法,计算得到的唯一的userid。
3 后门DGA域名生成格式
Sunburst使用的dga域名做了非常巧妙的处理,大致格式如下:
*.appsync-api.eu-west-1.avsvmcloud.com(*代表DGA的子域名)
*.appsync-api.us-west-2.avsvmcloud.com(*代表DGA的子域名)
*.appsync-api.us-east-1.avsvmcloud.com(*代表DGA的子域名)
*.appsync-api.us-east-2.avsvmcloud.com(*代表DGA的子域名)
其中,每个DGA域名右边三小段,来自于后门程序中硬编码的字符串,而dga域名的第一分段的星号部分是根据受害者服务器中的域名等信息动态生成的,以下是一个DGA阶段域名生成算法的示例。
1 第1阶段DGA域名通信
在这个阶段,Sunburst主要任务是把受害者计算机域名,经过几层加密放在DGA域名中,然后回传给C2。如果有的计算机域名过长,那么Sunburst后门会对信息进行分割,每次发送14个字符,发送多次DNS请求完成信息传送。攻击者如果对此计算机域名感兴趣,会进入第2阶段DGA域名通信,随后Sunburst后门将被激活,变为"Append"状态。
如下图所示,这些是从流量中抓到的Sunburst在第一阶段的dga域名通信的dga域名的流量样本。第二列是解密出来的Sunburst收集的受害者域名,攻击者就是从这些解密出来的域名信息,判断目标受害者单位是否有价值的。通过对这些域名进行解码分析我们发现,疑似包括思科、Intel在内的多家科技公司以及美国多所大学、政府机构均疑似本次攻击的受害者。
2 第2阶段DGA域名通信
在这一阶段,Sunburst后门主要完成将受害者计算机的杀软防护状态信息回传给C2服务端。当Sunburst后门状态为Append(激活状态)时,即开始第2阶段dga域名,生成的DGA域名将包括计算机唯一标志符、内置服务黑名单的安全产品测状态信息(包括是否存在、是否还在运行、是否被关闭等信息)和与上一次DNS C2阶段中通信是否成功的信息。
攻击者控制C2域名的解析IP地址范围属于Google、Amazon和Microsoft段的IP地址,而不是随机选择IP地址来触发不同的行为,这是为了降低被检测的机率。再次强调,恶意软件不会与这些IP地址进行通信联系。
如上图所示,Sunburst开发者将IP地址定义在一个AddressFamilyEx结构中,Sunburst将会根据DNS解析返回的不同IP地址触发不同的恶意行为。通过阅读Sunburst后门的C#代码发现,根据C2将域名解析到不同类别的ip地址,Sunburst后门将执行大约5大类型的操作:
1. 继续发送未传输完毕的域名片段信息;2. 发送目标计算机的安全防护产品的状态信息;3. 执行第2阶段的C2通道;4. 清理并退出;5. 重置成初始状态,就像第一次执行一样。
最后给出一张总的图:
4 C2控制域名解析ip间接控制Sunburst流程图
接下来ABC_123制作了一张流程图,演示了实战过程中C2端如何通过控制DGA域名解析到不同IP来控制Sunburst后门行为的全过程。由于该通信过程非常复杂,后续ABC_123会专门写一篇文章详细讲解全过程。
通过前面2个阶段的DGA域名通信,攻击者筛选出了有价值的目标,Sunburst后门进入下一个阶段:HTTP C2通信阶段。在这个阶段DNS的返回数据中会有CNAME记录,Sunburt后门会将此域名用来做HTTP C2通信。
在这个阶段,Sunburst将会启动一个新的线程执行HttpHelper.Initialize方法,以便去处理HTTP C2通信阶段请求,接收攻击者发送的指令并且执行,然后将指令执行结果经过加密后,混淆在正常的流量包中反馈给攻击者的C2服务端。研发Sunburst后门的攻击者,为了过流量监控,在这个阶段设计了极为巧妙的流量加密方法,接下来ABC_123给大家具体说一下,让大家开开眼界。
首先贴出在HTTP C2通信阶段Sunburst后门的3种不同的URL访问形式,分别对应着3种情况:
1. Sunburst会不断访问.xml网址,主动获取C2端的指令,URL形式如下:
hxxps://3mu76044hgf7shjf.appsync-api.eu-west-1.avsvmcloud.com/swip/upd/Orion.Wireless.xml
2. Sunburst将指令执行结果返回C2端,数据大于10,000时,URL形式如下:
hxxps://3mu76044hgf7shjf.appsync-ap.us-east-2.avsvmcloud.com/pki/crl/492-ca.crl
3. Sunburst将指令执行结果返回C2端,数据小于等于10,000时,URL形式如下:
hxxps://3mu76044hgf7shjf.appsync-api.us-east-1.avsvmcloud.com/fonts/woff/6047-freefont-ExtraBold.woff2
接下来讲解一下Sunburst后门获取C2指令并执行,然后将执行结果回传给C2端的3个过程。
1 Sunburst访问.xml网址接收指令
为了获取攻击者发送的指令,Sunburst后门会不断发起http GET请求访问C2端的.xml结尾的URL地址,而且在每次请求之后,都会通过setTime设置的时间进行休眠。这些XML文件会伪装成一个与.NET程序集相关的正常的XML文件,攻击者下发的指令就通过各种隐写技术隐藏在其中。Sunburst会读取C2端返回的XML文件内容,并使用特有的解密算法从XML文件中提取攻击者发送的指令并执行。
Sunburst发起GET请求的URL路径是随机的,按照一定的算法进行随机构造,这样做也是为了对抗IOCs检测。对于以下URL:
hxxps://3mu76044hgf7shjf.appsync-api.eu-west-1.avsvmcloud.com/swip/upd/Orion.Wireless.xml
Sunburst后门对于URL请求的变换主要在于标黄的部分:/swip/upd/<random components>.xml。<random components>的取值算法比较复杂,每一小段设置了不同的比例被随机选取到。值得注意的是,error code的最后一位数字不是随机字符,取值为0或者1,表示上一步执行命令请求的是否成功。其中通常 0 表示成功,1 或其它值表示错误,最后加上.xml后缀。
最终会Sunburst根据算法随机构造出以下URL去访问C2端,获取下发的指令:
https[:]//infinitysoftwares.com/swip/upd/SolarWinds.CortexPlugin.Nodes-5.2.1.xml
https[:]//infinitysoftwares.com/swip/upd/Orion.Wireless.UI-3.1.0.xml
https[:]//infinitysoftwares.com/swip/upd/Nodes-1.2.0.xml
对于前 16 个请求,每次都使用不同的随机生成URL路径,但之后它可能会重复之前使用的随机生成的URL路径。在这个阶段会有一个固定的If-None-Match自定义请求头,这里含有经过加密处理的先前的userId。
如下图所示,这是在Sunbrust访问.xml结尾的URL的GET请求之后,攻击者C2服务端返回的XML格式内容,里面就加密存储了攻击者下发指令:
Sunburst后门从xml返回文本中解密提取攻击者下发的指令,并通过ExecuteEngine方法执行对应指令,通过JobEngine中的值作为条件,运行由命令行参数组成的命令。由这些指令可以看出,Sunburst后门执行的操作非常有限,这意味着攻击者如果想进一步扩大战果,必然要借助于其它工具进行更复杂的操作,也就是第三阶段的CobaltStrike后门。
1. 当指令被解析为JobEngine.SetTime时,设置每次请求的延迟时间。
2. Job.CollectSystemDescription时,将会收集信息,包括计算机域名,Administrator SID、本地主机名,用户名,操作系统版本信息,系统路径,网络适配器情况、注册用户的公司名、注册用户名、系统版本号、系统目录等。
3. JobEngine.UploadSystemDescription时,构造HTTP请求,将请求结果发给C2服务器。
4. JobEngine.RunTask时,根据给定的文件路径和参数启动一个新的进程。
5. JobEngine.GetProcessByDescription时,获取进程列表,根据进程参数获取进程信息,包含进程ID,进程名,父进程ID,进程对应用户名。
6. JobEngine.GetFileSystemEntries时,根据参数中的正则表达式列出文件和目录信息。
7. JobEngine.KillTask时,Sunburst将会杀死指定PID的进程。
8. JobEngine.SetTime时,设置延迟秒数,第二次触发时,如果第一次设置的时间小于300秒则会进行一次加倍延时
9. JobEngine.FileExists时,判断指定路径是否存在。
10. JobEngine.DeleteFile时,删除指定路径。
11. JobEngine.ReadRegistryValue时,读取注册表项的值。
12. JobEngine.SetRegistryValue时,设置注册表项的名称、类型、路径
13. JobEngine.DeleteRegistryValue时,删除注册表项
14. JobEngine.GetRegistrySubKeyAndValueNames时,获取所有指定项名称和数据
15. JobEngine.WriteFile时,解密传入的base64字符串并写入文件,写入后会触发延时函数保证,可见攻击者对于文件处理流程很是小心。
16. JobEngine.Reboot时,重启目标计算机。
17. JobEngine.Exit时,退出当前线程,等待下次被加载执行。
18. 还会根据指令投递第三阶段后门程序,TEARDROP、RAINDROP,用来加载CobaltStrike后门。
3 Sunburst将命令执行结果回传给C2
一旦Sunburst后门从XML文件中解密出攻击者下发的指令之后,Sunburst后门会按照指令进行执行,并将返回结果回传给C2服务端。Sunburst后门在数据回传阶段,不会发送GET请求,而是依据回传数据结果的大小,选择通过POST请求或者PUT请求将命令执行的结果回传给C2服务端。Sunburst会把请求伪装成合法的Solarwinds请求链接或者静态资源迷惑安全人员,误将Sunburst发送的http请求初步评估为合法的流量。
1、当回传的数据大于10,000字节时。Sunburst通过POST请求发送。POST请求会设置Content-type字段,application/octet-stream。这种情况下,URL格式如下:
hxxps://3mu76044hgf7shjf.appsync-api.us-east-2.avsvmcloud.com/pki/crl/492-ca.crl
请求URI路径格式为/pki/crl/{0}{1}{2}.crl,其中{0}是100到10000的随机数;{1}是一个内置的字符串列表,从中随机选择一个进行拼接;{2}表示上次请求的错误码,某些情况下此值为空;最后在URL结尾拼接上.crl后缀。
2、当回传的数据小于等于10000字节时。Sunburst将通过PUT请求将执行命令的结果回传给C2服务端。PUT请求回传的数据会被转换成类似于Solarwinds合法使用的Orion改进计划(OIP)消息的JSON文档,其中json数据中的Message是待发送的数据,在发送http请求时,会设置请求头Content-type: application/json。
在这个阶段,访问的URL格式如下:
hxxps://3mu76044hgf7shjf.appsync-api.us-east-1.avsvmcloud.com/fonts/woff/6047-freefont-ExtraBold.woff2
其中,URL格式分为两种情况:
1. /fonts/woff/{0}-{1}-{2}-webfont{3}.woff2
{0}是100到10,000之间的随机数;{1}内置列表字符串列表随机选一个;{2}内置列表字符串列表随机选一个;{3} 表示上次请求操作的错误码。
2. /fonts/woff/{0}-{1}-{2}{3}.woff2
其中{0}是100到10,000之间的随机数;{1}内置列表字符串列表随机选一个;{2}内置列表字符串列表随机选一个;{3}表示上次请求的错误码。
Sunburst将指令执行结果隐藏在以下JSON格式的POST请求数据包中,然后回传给C2服务端。
1. Sunburst后门必须在满足攻击者的要求,安全防护软件在攻击者预想的情况下才会继续执行,否则就会终止或者重试之前的修改防护软件状态的操作,这方面是APT攻击者与普通犯罪人员之间的关键区别之一。
2. 为了对抗IOCs检测,Sunburst后门作者设计了巧妙的dga域名生成算法和URL路径随机生成算法,而且两个dga域名请求间隔时间可能长达一整天,攻击过程非常隐蔽。
3. Sunburst在HTTP C2通信阶段,回传受害者电脑敏感信息时,把这些信息加密存储在XML程序集文档中或者JSON文档中,有时候还特意模仿Solarwinds专用协议的通信流量,这种方式在流量审计中难以发现。
4. 该APT组织通过将C2域名解析到不同的IP地址段,间接控制Sunburst后门的操作,这个攻击行为在流量审计中难以发现。
5. 攻击者向Orion软件的XML配置文件中写入不同的数字3、4、5,表示Sunburst后门所处的不同状态,Sunburst后门会读取这些值进行不同操作,这个过程同样非常隐蔽。
【往期推荐】