axios icon indicating copy to clipboard operation
axios copied to clipboard

Security: Axios sends HTTPS data in cleartext to a proxy (regression)

Open benbucksch opened this issue 3 months ago • 1 comments

Describe the bug

Axios use the HTTP proxy incorrectly, so that the data and URL is sent in plaintext to the proxy. The proxy then wrongly tries a TLS connection with the target server and fails.

Older axios versions work correctly. Other libs also work.

To Reproduce

  1. Set proxy environment variables, using export http_proxy="http://foo:3100" and export https_proxy="http://foo:3100" (the http:// is correct, because the HTTP client connects to the proxy via HTTP and does HTTPS on top)
  2. let r = await axios.get("https://www.beonex.com"); console.log("page", r.text());

Code snippet

// with proxy, see above
let r = await axios.get("https://www.beonex.com");
console.log("page", r.text());

Expected behavior

  • The client connects to the remove server directly via TLS. The squid proxy only forwards the TCP stream, and is not involved in the TLS connection
  • The proxy should not even see the URL (!), only the hostname.
  • You see the HTML source of the webpage

Actual behavior

  • Error HTTP 503
  • You see the HTML source of the squid proxy error page
  • TLS connection settings mismatch between squid proxy (!) and remote server
  • Page, with HTML and some text removed for readability: " The following error was encountered while trying to retrieve the URL: https://www.beonex.com/

Failed to establish a secure connection to [unknown]

TLS code: SQUID_TLS_ERR_CONNECT+GNUTLS_E_KEY_USAGE_VIOLATION SSL handshake error (SQUID_TLS_ERR_CONNECT)

This proxy and the remote host failed to negotiate a mutually acceptable security settings for handling your request. It is possible that the remote host does not support secure connections, or the proxy is not satisfied with the host security credentials. "

  • You can see that the target URL is in the proxy error page. That's a serious security bug. (The proxy should never see the full URL in the first place. Ditto headers, cookies etc.)

Axios Version

1.5.1

Adapter Version

No response

Browser

No response

Browser Version

No response

Node.js Version

18.15.0 (but not relevant, see below)

OS

Ubuntu

Additional Library Versions

No response

Additional context/Screenshots

Cause

The squid proxy should not even be involved in the TLS connection. By the very definition of it, HTTPS needs to connect straight from the browser to the target server, and no intermediate proxies should be involved in the TLS connection. Otherwise, that would defeat the entire purpose of the TLS connection, to prevent man in the middle to see the content. That's what the CONNECT is for in HTTP proxies: It simply tunnels the TCP connection, and the browser does TLS.

It appears that axios is driving the HTTPS proxy wrong and doesn't do a CONNECT, but lets the proxy connect to the target server via TLS. That would be wrong.

What works

  • Axios 0.27 works, axios 1.5.1 fails, so it's clearly a regression sometime in this version range. This also proves that it's a bug in axios. I haven't been able to narrow down the first faulty version yet that broke it.
  • ky (version 1.2.3) works fine, again showing that it's likely a bug in axios.

benbucksch avatar Mar 25 '24 21:03 benbucksch

Thank you for the explanations, I also came to the same conclusion. I checked the access log of squid. axios just sends a GET request instead of creating a tunnel using CONNECT.

Vringe avatar Apr 15 '24 16:04 Vringe