Headline
CVE-2023-25076: TALOS-2023-1731 || Cisco Talos Intelligence Group
A buffer overflow vulnerability exists in the handling of wildcard backend hosts of SNIProxy 0.6.0-2 and the master branch (commit: 822bb80df9b7b345cc9eba55df74a07b498819ba). A specially crafted HTTP, TLS or DTLS packet can lead to arbitrary code execution. An attacker could send a malicious packet to trigger this vulnerability.
SUMMARY
A buffer overflow vulnerability exists in the handling of wildcard backend hosts of SNIProxy 0.6.0-2 and the master branch (commit: 822bb80df9b7b345cc9eba55df74a07b498819ba). A specially crafted HTTP, TLS or DTLS packet can lead to arbitrary code execution. An attacker could send a malicious packet to trigger this vulnerability.
CONFIRMED VULNERABLE VERSIONS
The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.
SNIProxy 0.6.0-2
SNIProxy Master 822bb80df9b7b345cc9eba55df74a07b498819ba
PRODUCT URLS
SNIProxy - https://github.com/dlundquist/sniproxy
CVSSv3 SCORE
9.8 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CWE
CWE-120 - Buffer Copy without Checking Size of Input (‘Classic Buffer Overflow’)
DETAILS
SNIProxy (https://github.com/dlundquist/sniproxy) is an open source application that reverse proxies HTTP and TLS connections based on the requested hostname. It is distributed via package manager on several Linux distributions.
When wildcard backend hosts are used in SNIProxy configuration, an attacker could achieve remote code execution or denial of service by sending a crafted HTTP, TLS or DTLS packet.
The latest version on GitHub and the 0.6.0-2 Debian package were determined to be vulnerable. Note that while the original repository hasn’t been updated in several years, there are several forks of the original repository which are more active and may also contain this bug.
SNIProxy contains functions to parse addresses and hostnames, usually obtained by parsing the HTTP Host header or from a TLS server name indication (SNI) extension header. The new_address() function parses arbitrary hostname or address strings into a usable format. This function is called when parsing the configuration file, and, more importantly, when parsing hostnames that are to be sent to a wildcard backend.
Example wildcard configuration (note the asterisk on the right side):
table my_hosts {
[a-z0-9]*\\.example\\.com *:443
}
Normally, TLS libraries such as OpenSSL do not allow SNI hostname values to exceed 256 bytes. However, SNIProxy does not use an external library for this functionality. It implements its own basic parsing on the TLS header values, which allow longer values to be parsed. The same also applies to the HTTP “Host” header, which itself has no maximum length in an HTTP request. As such, SNIProxy will extract and accept hostnames of arbitrary lengths.
During code inspection, an issue was observed in the new_address() function in the code block that parses IPv6 address strings (e.g. “[ff02::1]”). The issue arises because the source length is used in a string copy rather than destination length when copying into a stack buffer of size 262. The source length is calculated based on the distance between the opening and closing square brackets, which can be more than 262 due to the behavior noted above with unrestricted hostname lengths. Because of this, the call to strncpy will overflow the ip_buf buffer, resulting in a stack buffer overflow.
char ip_buf[262];
... snip ...
/* [IPv6 address] */
memset(&s, 0, sizeof(s));
if (hostname_or_ip[0] == '[' &&
(port = strchr(hostname_or_ip, ']')) != NULL) {
len = (size_t)(port - hostname_or_ip - 1); // len can be longer than 262
...
strncpy(ip_buf, hostname_or_ip + 1, len); // buffer overflow here
ip_buf[len] = '\0';
Exploit Proof of Concept
Configure an SNIProxy instance with the following configuration:
listen 0.0.0.0 443 {
proto tls
table my_hosts
}
table my_hosts {
.*test\\.example\\.com *:443
}
Attached is a proof-of-concept that will either crash SNIProxy outright, or, in the case of missing compiler mitigations, may redirect SNIProxy’s execution flow to a specified memory address (in this case, the invalid address 0xdeadbeefdeadbeef).
Mitigation
This is a suggested patch for the affected code in the new_address() function in address.c, which prevents the string copy from overflowing the destination and ensures that the resultant buffer is null terminated: strncpy(ip_buf, hostname_or_ip + 1, sizeof(ip_buf)); ip_buf[sizeof(ip_buf) - 1] = '\0’;
TIMELINE
2023-03-16 - Initial Vendor Contact
2023-03-17 - Vendor Disclosure
2023-03-17 - Vendor Patch Release
2023-03-30 - Public Release
Discovered by Keane O’Kelley of Cisco ASIG.
Related news
Ubuntu Security Notice 6148-1 - It was discovered that SNI Proxy did not properly handle wildcard backend hosts. An attacker could possibly use this issue to cause a buffer overflow, resulting in a denial of service, or arbitrary code execution.
Debian Linux Security Advisory 5413-1 - An issue has been found in sniproxy, a transparent TLS and HTTP layer 4 proxy with SNI support. Due to bad handling of wildcard backend hosts, a crafted HTTP or TLS packet might lead to remote arbitrary code execution.
An attacker could exploit this vulnerability by sending a specially crafted HTTP, TLS or DTLS packet to the target machine, potentially causing a denial of service or gaining the ability to execute remote code.