The vulnerability, described as 'Russh SSH message fields were decoded through allocation-first parsers', stems from a common anti-pattern where the library allocates memory based on length fields from untrusted network data before validating those lengths. This allows a remote attacker to trigger excessive memory allocation, leading to a denial of service. The analysis of the patches between the vulnerable version 0.60.2 and the fixed version 0.61.0 confirms this pattern across the codebase.
The patches consistently introduce checks in functions responsible for parsing SSH messages. These checks are primarily of two types:
- Trailing Data Validation: The introduction of a new
ensure_end function, which is called after decoding a message's fields, ensures that no unexpected trailing data is present in the packet. This prevents a class of attacks where malformed packets could be partially processed.
- Pre-allocation Size Validation: In several places, such as the keyboard-interactive authentication handler and the SSH agent communication logic, explicit checks are added to validate length fields (e.g., number of prompts, frame length) against reasonable limits before memory is allocated for them.
The Proof of Concept (PoC) specifically targets the KEXINIT message parser (Server::read_kex), demonstrating how a pre-authentication message with a large, high-fanout name-list can cause multi-gigabyte memory consumption on the server. The patches address this directly in russh::negotiation::Select::read_kex.
The identified vulnerable functions are the primary entry points for parsing different types of SSH messages, from the initial key exchange (read_kex) to encrypted data packets (process_packet, server_read_encrypted) and specialized messages like CHANNEL_OPEN and agent requests. An exploit would involve a stack trace showing one of these functions calling down into decoding and allocation primitives which then fail or cause resource exhaustion.