CVSS 7.1 CVE-2021-28041
CVSS 7.1 CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:H/A:H
ssh-agent in OpenSSH before 8.5 has a double free that may be relevant in a few less-common scenarios, such as unconstrained agent-socket access on a legacy operating system, or the forwarding of an agent to an attacker-controlled host.
Update OpenSSH to version 8.5 or greater.
OpenSSH 8.5 Release Notes
ssh-agent(1): fixed a double-free memory corruption that was introduced in OpenSSH 8.2 . We treat all such memory faults as potentially exploitable. This bug could be reached by an attacker with access to the agent socket.
On modern operating systems where the OS can provide information about the user identity connected to a socket, OpenSSH ssh-agent and sshd limit agent socket access only to the originating user and root. Additional mitigation may be afforded by the system’s malloc(3)/free(3) implementation, if it detects double-free conditions.
The most likely scenario for exploitation is a user forwarding an agent either to an account shared with a malicious user or to a host with an attacker holding root access.
Double free errors
Double free errors occur when free() is called more than once with the same memory address as an argument.
Calling free() twice on the same value can lead to memory leak. When a program calls free() twice with the same argument, the program’s memory management data structures become corrupted and could allow a malicious user to write values in arbitrary memory spaces. This corruption can cause the program to crash or, in some circumstances, alter the execution flow. By overwriting particular registers or memory spaces, an attacker can trick the program into executing code of their own choosing, often resulting in an interactive shell with elevated permissions.
When a buffer is free()‘d, a linked list of free buffers is read to rearrange and combine the chunks of free memory (to be able to allocate larger buffers in the future). These chunks are laid out in a double linked list which points to previous and next chunks. Unlinking an unused buffer (which is what happens when free() is called) could allow an attacker to write arbitrary values in memory; essentially overwriting valuable registers, calling shellcode from its own buffer.