Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [day] [month] [year] [list]
Date: Wed, 11 Oct 2023 07:58:42 +0200 (CEST)
From: Daniel Stenberg <daniel@...x.se>
To: curl security announcements -- curl users <curl-users@...ts.haxx.se>, 
    curl-announce@...ts.haxx.se, libcurl hacking <curl-library@...ts.haxx.se>, 
    oss-security@...ts.openwall.com
Subject: [SECURITY ADVISORY] curl: CVE-2023-38545: SOCKS5 heap buffer
 overflow

SOCKS5 heap buffer overflow
===========================

Project curl Security Advisory, October 11 2023 -
[Permalink](https://curl.se/docs/CVE-2023-38545.html)

VULNERABILITY
-------------

This flaw makes curl overflow a heap based buffer in the SOCKS5 proxy
handshake.

When curl is asked to pass along the hostname to the SOCKS5 proxy to allow
that to resolve the address instead of it getting done by curl itself, the
maximum length that hostname can be is 255 bytes.

If the hostname is detected to be longer than 255 bytes, curl switches to
local name resolving and instead passes on the resolved address only to the
proxy. Due to a bug, the local variable that means "let the host resolve the
name" could get the wrong value during a slow SOCKS5 handshake, and contrary
to the intention, copy the too long hostname to the target buffer instead of
copying just the resolved address there.

TERMINOLOGY
-----------

The curl library is known as libcurl and the command line tool that uses the
library is known as the curl tool. Either or both may be referred to as just
curl. The distinctive names are used in this document when necessary.

INFO
----

The hostname comes from the URL that curl has been told to operate with.

The target buffer is the heap-based download buffer in libcurl that is reused
for SOCKS negotiation before the transfer has started. The size of the buffer
is 16kB by default, but can be set to different sizes by the application. The
curl tool sets it to 102400 bytes by default - but it sets the buffer size to
a smaller size if `--limit-rate` is set lower than 102400 bytes per second.

libcurl provides the `CURLOPT_BUFFERSIZE` option to change the size of the
download buffer.

libcurl accepts hostnames up to 65535 bytes in the URL.

If the used hostname is longer than the target buffer, there is a `memcpy()`
that overwrites the buffer into the heap. The URL parser and possibly an IDN
library (if curl is built with one) have to accept the hostname, which
somewhat limits the set of available byte sequences that can be used in the
copy.

For an overflow to happen it needs a slow enough SOCKS5 handshake to trigger
the local variable bug, and the client using a hostname longer than the
download buffer. Perhaps with a malicious HTTPS server doing a redirect to an
especially crafted URL.

Typical server latency is likely "slow" enough to trigger this bug without an
attacker needing to influence it by DoS or SOCKS server control.

An overflow is only possible in applications that do not set
`CURLOPT_BUFFERSIZE` or set it smaller than 65541. Since the curl tool sets
`CURLOPT_BUFFERSIZE` to 100kB by default it is not vulnerable unless rate
limiting was set by the user to a rate smaller than 65541 bytes/second.

The options that cause SOCKS5 with remote hostname to be used in libcurl:
- `CURLOPT_PROXYTYPE` set to type `CURLPROXY_SOCKS5_HOSTNAME`, or:
- `CURLOPT_PROXY` or `CURLOPT_PRE_PROXY` set to use the scheme `socks5h://`
- One of the proxy environment variables can be set to use the `socks5h://`
   scheme. For example `http_proxy`, `HTTPS_PROXY` or `ALL_PROXY`.

The options that cause SOCKS5 with remote hostname to be used in the curl tool:
- `--socks5-hostname`, or:
- `--proxy` or `--preproxy` set to use the scheme `socks5h://`
- Environment variables as described in the libcurl section.

This bug was introduced when the SOCKS5 handshake code was converted from a
blocking function into a non-blocking state machine.

**The analysis in this section is specific to curl version 8.** Some older
versions of curl version 7 have less restriction on hostname length and/or a
smaller SOCKS negotiation buffer size that cannot be overridden by
CURLOPT_BUFFERSIZE.

The Common Vulnerabilities and Exposures (CVE) project has assigned the name
CVE-2023-38545 to this issue.

CWE-122: Heap-based Buffer Overflow

Severity: High

HackerOne: https://hackerone.com/reports/2187833

AFFECTED VERSIONS
-----------------

- Affected versions: libcurl 7.69.0 to and including 8.3.0
- Not affected versions: libcurl < 7.69.0 and >= 8.4.0
- Introduced-in: https://github.com/curl/curl/commit/4a4b63daaa

libcurl is used by many applications, but not always advertised as such!

SOLUTION
--------

Starting in curl 8.4.0, curl no longer switches to local resolve mode if the
name is too long but is instead rightfully returning an error.

- Fixed-in: https://github.com/curl/curl/commit/fb4415d8aee6c1

[Patch collection for older versions](https://curl.se/docs/CVE-2023-38545_patches.zip)

RECOMMENDATIONS
---------------

  A - Upgrade curl to version 8.4.0

  B - Apply the patch to your local version

  C - Do not use `CURLPROXY_SOCKS5_HOSTNAME` proxies with curl

  D - Do not set a proxy environment variable to socks5h://

TIMELINE
--------

This issue was reported to the curl project on September 30, 2023. We contacted
distros@...nwall on October 3, 2023.

libcurl 8.4.0 was released on October 11 2023, coordinated with the publication
of this advisory.

CREDITS
-------

- Reported-by: Jay Satiro
- Patched-by: Jay Satiro

Thanks a lot!

-- 

  / daniel.haxx.se

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.