Friday, July 5, 2013

Building an SSH Botnet C&C Using Python and Fabric


Introduction

Disclaimer: I suppose it would be wise to put a disclaimer on this post. Compromising hosts to create a botnet without authorization is illegal, and not encouraged in any way. This post simply aims to show security professionals how attackers could use standard IT automation tools for a purpose in which they were not originally intended. Therefore, the content is meant for educational purposes only.

System administrators often need to perform the same (or similar) tasks across a multitude of hosts. Doing this manually is unreasonable, so solutions have been created to help automate the process. While these solutions can be a life-saver to many, let's look at them in a different light. In this post, we'll explore how easy it would be for an attacker to use one of these solutions, a popular Python library called Fabric, to quickly create a command and control (C&C) application that can manage a multitude of infected hosts over SSH.

Fabric Basics

Fabric's documentation describes it as a "library and command-line tool for streamlining the use of SSH for application deployment or systems administration tasks." Using the popular Paramiko Python library to manage it's SSH connections, Fabric provides programmers with an easy-to-use API to run sequential or parallel tasks across many machines. Before building a C&C application, let's explore some of the basics of Fabric (a full tutorial can be found here).

The "fab" Command-line Tool

While we won't be using it much in this post, I don't feel a post about Fabric would be complete without mentioning the "fab" tool. Usually, sysadmins only need to setup predefined commands (called "tasks") to be run on multiple hosts. With this being the case, the standard application of Fabric is as follows:
  • Create a "fabfile" (more on this later)
  • Use the fab tool to execute tasks defined in the fabfile on selected hosts
While this allows us to run a predefined set of commands, this isn't helpful if we want an interactive framework. The solution to this is found in the Fabric documentation:

The fab tool simply imports your fabfile and executes the function or functions you instruct it to. There’s nothing magic about it – anything you can do in a normal Python script can be done in a fabfile!

This means that we can execute any task in our fabfile without needing to go through the fab command line tool. This is helpful, since we can create an interactive management wrapper to perform tasks on a dynamic list of hosts as we choose. But first, we need to address the obvious: what is a fabfile?

Fabfiles

In a nutshell, a fabfile is simply a file containing functions and commands that incorporate Fabric's API. These functions can be found in the fabric.api namespace. It's important to remember our note above which says that a fabfile is just Python - nothing special.

So, with that brief intro, let's dive into the Fabric API to see how we can use the provided functions to build an SSH C&C:

Building the C&C

Let's assume an attacker managed to compromise numerous hosts, either using SSH, or via other means and now has SSH access to them. Let's also assume that credentials to these hosts are stored in a file with the following format:

username@hostname:port password

The example for this post will be as follows:



It is important to note that Fabric tries to automatically detect the type of authentication needed (password or passphrase for private key). Therefore, if the passwords stored in the credentials file are for private keys, they should work seamlessly.

Now that we have our credentials, let's consider what functions we will create. For the sake of this post, let's implement the following:

  • Status check to see which hosts are running
  • Run a supplied command on multiple selected hosts
  • Create an interactive shell session with a host

To start, we will import all members of the fabric.api namespace:



Next, we will use two of Fabric's environment variables, env.hosts and env.passwords, to manage our host connections. "Env.hosts" is a list we can use to manage our master host list, and env.passwords is a mapping between host strings and passwords to be used. This prevents us from having to enter the passwords upon each new connection. Let's read all the hosts and passwords from the credentials file and put them into the variables:



Now for the fun part - running commands. There are 6 types of command-execution functions that can we should consider:

Let's see how we can use these commands. First, let's create a function that takes in a command string, and execute the command using Fabric's "run" or "sudo" command as needed:


Now, let's create a task that will use our run_command function to see which hosts are up and running. We will do this by executing the command uptime on the hosts.


For the other tasks, we will want to dynamically select which hosts we want to run a given command on, or establish a shell session to. We can do this by creating a menu, and then executing these tasks with a specific list of hosts using Fabric's execute function. Here's what this looks like:


I should note that I left out a task to put a file onto the remote host, since this can be easily done from the command line (though a task for this could be made easily). Let's see what our application looks like in action:


Great! It looks like we were able to successfully control all of the machines we had access to. It's important to note that there is so much more we can do with Fabric to help facilitate the host management. Here are just a few examples:

  • By adding the @parallel decorator before our tasks, our tasks will run in parallel (Note: this won't work in Windows).
  • Fabric also allows us to create groups (called roles). We could use these roles to create groups based on location, functionality, etc.
  • Since our fabfile is just Python, we can extend it to use any functionality we want. For example, we could easily create a web interface to this using Flask or Django

Conclusion
The goal of this post was to give a practical example showing how attackers could use high-quality network management products in ways they weren't intended to be used. It's important to note that this same functionality could extend to any other IT automation solution such as Chef, Puppet, or Ansible.

As always, feel free to leave questions and comments below.

1 comment: