##
# $Id: mysql_enum.rb 10680 2010-10-14 18:24:56Z egypt $
##

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##


require 'msf/core'


class Metasploit3 < Msf::Auxiliary

	include Msf::Exploit::Remote::MYSQL

	def initialize(info = {})
		super(update_info(info,
				'Name'			=> 'MySQL Enumeration Module',
				'Description'	=> %q{
					This module allows for simple enumeration of MySQL Database Server
					provided proper credentials to connect remotely.
				},
				'Author'		=> [ 'Carlos Perez. <carlos_perez[at]darkoperator.com>' ],
				'License'		=> MSF_LICENSE,
				'Version'		=> '$Revision: 10680 $',
				'References'		=>
				[
					[ 'URL', 'https://cisecurity.org/benchmarks.html' ]
				]
			))

	end

	def run
		return if not mysql_login_datastore
		print_status("Running MySQL Enumerator...")
		print_status("Enumerating Parameters")
		#-------------------------------------------------------
		#getting all variables
		vparm = {}
		res = mysql_query("show variables") || []
		res.each do |row|
			#print_status(" | #{row.join(" | ")} |")
			vparm[row[0]] = row[1]
		end
		#-------------------------------------------------------
		# MySQL Version
		print_status("\tMySQL Version: #{vparm["version"]}")
		print_status("\tCompiled for the following OS: #{vparm["version_compile_os"]}")
		print_status("\tArchitecture: #{vparm["version_compile_machine"]}")
		print_status("\tServer Hostname: #{vparm["hostname"]}")
		print_status("\tData Directory: #{vparm["datadir"]}")
		if vparm["log"] == "OFF"
			print_status("\tLogging of queries and logins: OFF")
		else
			print_status("\tLogging of queries and logins: ON")
			print_status("\tLog Files Location: #{vparm["log_bin"]}")
		end
		print_status("\tOld Password Hashing Algorithm #{vparm["old_passwords"]}")
		print_status("\tLoading of local files: #{vparm["local_infile"]}")
		print_status("\tLogins with old Pre-4.1 Passwords: #{vparm["secure_auth"]}")
		print_status("\tSkipping of GRANT TABLE: #{vparm["skip_grant_tables"]}") if vparm["skip_grant_tables"]
		print_status("\tAllow Use of symlinks for Database Files: #{vparm["have_symlink"]}")
		print_status("\tAllow Table Merge: #{vparm["have_merge_engine"]}")
		print_status("\tRestrict DB Enumeration by Privilege: #{vparm["safe_show_database"]}") if vparm["safe_show_database"]
		if vparm["have_openssl"] == "YES"
			print_status("\tSSL Connections: Enabled")
			print_status("\tSSL CA Certificate: #{vparm["ssl_ca"]}")
			print_status("\tSSL Key: #{vparm["ssl_key"]}")
			print_status("\tSSL Certificate: #{vparm["ssl_cert"]}")
		else
			print_status("\tSSL Connection: #{vparm["have_openssl"]}")
		end
		#-------------------------------------------------------
		#Account Enumeration
		# Enumerate all accounts with their password hashes
		print_status("Enumerating Accounts:")
		query = "select user, host, password from mysql.user"
		res = mysql_query(query)
		if res.size > 0
			print_status("\tList of Accounts with Password Hashes:")
			res.each do |row|
				print_status("\t\tUser: #{row[0]} Host: #{row[1]} Password Hash: #{row[2]}")
			end
		end
		# Only list accounts that can log in with SSL if SSL is enabled
		if vparm["have_openssl"] == "YES"
			query = %Q|select user, host, ssl_type from mysql.user where ssl_type
				(ssl_type = 'ANY') or
				(ssl_type = 'X509') or
				(ssl_type = 'SPECIFIED')|
			res = mysql_query(query)
			if res.size > 0
				print_status("\tThe following users can login using SSL:")
				res.each do |row|
					print_status("\t\tUser: #{row[0]} Host: #{row[1]} SSLType: #{row[2]}")
				end
			end
		end
		query = "select user, host from mysql.user where Grant_priv = 'Y'"
		res = mysql_query(query)
		if res.size > 0
			print_status("\tThe following users have GRANT Privilege:")
			res.each do |row|
				print_status("\t\tUser: #{row[0]} Host: #{row[1]}")
			end
		end

		query = "select user, host from mysql.user where Create_user_priv = 'Y'"
		res = mysql_query(query)
		if res.size > 0
			print_status("\tThe following users have CREATE USER Privilege:")
			res.each do |row|
				print_status("\t\tUser: #{row[0]} Host: #{row[1]}")
			end
		end
		query = "select user, host from mysql.user where Reload_priv = 'Y'"
		res = mysql_query(query)
		if res.size > 0
			print_status("\tThe following users have RELOAD Privilege:")
			res.each do |row|
				print_status("\t\tUser: #{row[0]} Host: #{row[1]}")
			end
		end
		query = "select user, host from mysql.user where Shutdown_priv = 'Y'"
		res = mysql_query(query)
		if res.size > 0
			print_status("\tThe following users have SHUTDOWN Privilege:")
			res.each do |row|
				print_status("\t\tUser: #{row[0]} Host: #{row[1]}")
			end
		end
		query = "select user, host from mysql.user where Super_priv = 'Y'"
		res = mysql_query(query)
		if res.size > 0
			print_status("\tThe following users have SUPER Privilege:")
			res.each do |row|
				print_status("\t\tUser: #{row[0]} Host: #{row[1]}")
			end
		end
		query = "select user, host from mysql.user where FILE_priv = 'Y'"
		res = mysql_query(query)
		if res.size > 0
			print_status("\tThe following users have FILE Privilege:")
			res.each do |row|
				print_status("\t\tUser: #{row[0]} Host: #{row[1]}")
			end
		end
		query = "select user, host from mysql.user where Process_priv = 'Y'"
		res = mysql_query(query)
		if res.size > 0
			print_status("\tThe following users have POCESS Privilege:")
			res.each do |row|
				print_status("\t\tUser: #{row[0]} Host: #{row[1]}")
			end
		end
		queryinmysql = %Q|       select user, host
				from mysql.user where
				(Select_priv = 'Y') or
				(Insert_priv = 'Y') or
				(Update_priv = 'Y') or
				(Delete_priv = 'Y') or
				(Create_priv = 'Y') or
				(Drop_priv = 'Y')|
		res = mysql_query(queryinmysql)
		if res.size > 0
			print_status("\tThe following accounts have privileges to the mysql databse:")
			res.each do |row|
				print_status("\t\tUser: #{row[0]} Host: #{row[1]}")
			end
		end


		# Anonymous Account Check
		queryanom = "select user, host from mysql.user where user = ''"
		res = mysql_query(queryanom)
		if res.size > 0
			print_status("\tAnonymous Accounts are Present:")
			res.each do |row|
				print_status("\t\tUser: #{row[0]} Host: #{row[1]}")
			end
		end

		# Blank Password Check
		queryblankpass = "select user, host, password from mysql.user where length(password) = 0 or password is null"
		res = mysql_query(queryblankpass)
		if res.size > 0
			print_status("\tThe following accounts have empty passwords:")
			res.each do |row|
				print_status("\t\tUser: #{row[0]} Host: #{row[1]}")
			end
		end

		# Wildcard host
		querywildcrd = 'select user, host from mysql.user where host = "%"'
		res = mysql_query(querywildcrd)
		if res.size > 0
			print_status("\tThe following accounts are not restricted by source:")
			res.each do |row|
				print_status("\t\tUser: #{row[0]} Host: #{row[1]}")
			end
		end


		mysql_logoff
	end

end

