Path: blob/master/modules/auxiliary/scanner/mysql/mysql_writable_dirs.rb
19500 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Exploit::Remote::MYSQL7include Msf::Auxiliary::Report8include Msf::Auxiliary::Scanner9include Msf::OptionalSession::MySQL1011def initialize12super(13'Name' => 'MYSQL Directory Write Test',14'Description' => %Q{15Enumerate writeable directories using the MySQL SELECT INTO DUMPFILE feature, for more16information see the URL in the references. ***Note: For every writable directory found,17a file with the specified FILE_NAME containing the text test will be written to the directory.***18},19'Author' => [ 'AverageSecurityGuy <stephen[at]averagesecurityguy.info>' ],20'References' => [21[ 'URL', 'https://dev.mysql.com/doc/refman/5.7/en/select-into.html' ]22],23'License' => MSF_LICENSE24)2526register_options([27OptPath.new('DIR_LIST', [ true, "List of directories to test", '' ]),28OptString.new('FILE_NAME', [ true, "Name of file to write", Rex::Text.rand_text_alpha(8) ]),29OptString.new('USERNAME', [ true, 'The username to authenticate as', "root" ])30])31end3233# This function does not handle any errors, if you use this34# make sure you handle the errors yourself35def mysql_query_no_handle(sql)36res = self.mysql_conn.query(sql)37res38end3940def run_host(ip)41print_warning("For every writable directory found, a file called #{datastore['FILE_NAME']} with the text test will be written to the directory.")42print_status("Login...") unless session4344# If we have a session make use of it45if session46print_status("Using existing session #{session.sid}")47self.mysql_conn = session.client48else49# otherwise fallback to attempting to login50return unless mysql_login_datastore51end5253File.read(datastore['DIR_LIST']).each_line do |dir|54check_dir(dir.chomp)55end56end5758def check_dir(dir)59begin60print_status("Checking #{dir}...")61res = mysql_query_no_handle("SELECT _utf8'test' INTO DUMPFILE '#{dir}/" + datastore['FILE_NAME'] + "'")62rescue ::Rex::Proto::MySQL::Client::ServerError => e63print_warning(e.to_s)64rescue Rex::ConnectionTimeout => e65print_error("Timeout: #{e.message}")66else67print_good("#{dir} is writeable")68report_note(69:host => mysql_conn.peerhost,70:type => "filesystem.file",71:data => {72:dir => dir,73:permissions => "writeable",74},75:port => mysql_conn.peerport,76:proto => 'tcp',77:update => :unique_data78)79end80end81end828384