137 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 1d66562c67fc0099d0fd882c693e51dd0b10c45c Mon Sep 17 00:00:00 2001
 | |
| From: Jay Satiro <raysatiro@yahoo.com>
 | |
| Date: Sat, 30 Sep 2023 03:40:02 -0400
 | |
| Subject: [PATCH] socks: return error if hostname too long for remote resolve
 | |
| 
 | |
| Prior to this change the state machine attempted to change the remote
 | |
| resolve to a local resolve if the hostname was longer than 255
 | |
| characters. Unfortunately that did not work as intended and caused a
 | |
| security issue.
 | |
| 
 | |
| Name resolvers cannot resolve hostnames longer than 255 characters.
 | |
| 
 | |
| Bug: https://curl.se/docs/CVE-2023-38545.html
 | |
| ---
 | |
|  lib/socks.c             |  8 +++---
 | |
|  tests/data/Makefile.inc |  2 +-
 | |
|  tests/data/test728      | 64 +++++++++++++++++++++++++++++++++++++++++
 | |
|  3 files changed, 69 insertions(+), 5 deletions(-)
 | |
|  create mode 100644 tests/data/test728
 | |
| 
 | |
| diff --git a/lib/socks.c b/lib/socks.c
 | |
| index c492d663c..a7b5ab07e 100644
 | |
| --- a/lib/socks.c
 | |
| +++ b/lib/socks.c
 | |
| @@ -531,13 +531,13 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
 | |
|        infof(data, "SOCKS5: connecting to HTTP proxy %s port %d\n",
 | |
|              hostname, remote_port);
 | |
|  
 | |
|      /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
 | |
|      if(!socks5_resolve_local && hostname_len > 255) {
 | |
| -      infof(data, "SOCKS5: server resolving disabled for hostnames of "
 | |
| -            "length > 255 [actual len=%zu]\n", hostname_len);
 | |
| -      socks5_resolve_local = TRUE;
 | |
| +      failf(data, "SOCKS5: the destination hostname is too long to be "
 | |
| +            "resolved remotely by the proxy.");
 | |
| +      return CURLPX_LONG_HOSTNAME;
 | |
|      }
 | |
|  
 | |
|      if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
 | |
|        infof(data,
 | |
|              "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n",
 | |
| @@ -855,7 +855,7 @@ CONNECT_RESOLVE_REMOTE:
 | |
|  
 | |
|      if(!socks5_resolve_local) {
 | |
|        socksreq[len++] = 3; /* ATYP: domain name = 3 */
 | |
| -      socksreq[len++] = (char) hostname_len; /* one byte address length */
 | |
| +      socksreq[len++] = (unsigned char) hostname_len; /* one byte length */
 | |
|        memcpy(&socksreq[len], hostname, hostname_len); /* address w/o NULL */
 | |
|        len += hostname_len;
 | |
|        infof(data, "SOCKS5 connect to %s:%d (remotely resolved)\n",
 | |
| diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
 | |
| index 081e344d4..62ee53578 100644
 | |
| --- a/tests/data/Makefile.inc
 | |
| +++ b/tests/data/Makefile.inc
 | |
| @@ -99,7 +99,7 @@ test672 test673 test674 test675 test676 test677 test678 test679 test680 \
 | |
|  \
 | |
|  test700 test701 test702 test703 test704 test705 test706 test707 test708 \
 | |
|  test709 test710 test711 test712 test713 test714 test715 test716 test717 \
 | |
| -test718 \
 | |
| +test718 test728 \
 | |
|  \
 | |
|  test800 test801 test802 test803 test804 test805 test806 test807 test808 \
 | |
|  test809 test810 test811 test812 test813 test814 test815 test816 test817 \
 | |
| diff --git a/tests/data/test728 b/tests/data/test728
 | |
| new file mode 100644
 | |
| index 000000000..05bcf2883
 | |
| --- /dev/null
 | |
| +++ b/tests/data/test728
 | |
| @@ -0,0 +1,64 @@
 | |
| +<testcase>
 | |
| +<info>
 | |
| +<keywords>
 | |
| +HTTP
 | |
| +HTTP GET
 | |
| +SOCKS5
 | |
| +SOCKS5h
 | |
| +followlocation
 | |
| +</keywords>
 | |
| +</info>
 | |
| +
 | |
| +#
 | |
| +# Server-side
 | |
| +<reply>
 | |
| +# The hostname in this redirect is 256 characters and too long (> 255) for
 | |
| +# SOCKS5 remote resolve. curl must return error CURLE_PROXY in this case.
 | |
| +<data>
 | |
| +HTTP/1.1 301 Moved Permanently
 | |
| +Location: http://AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/
 | |
| +Content-Length: 0
 | |
| +Connection: close
 | |
| +
 | |
| +</data>
 | |
| +</reply>
 | |
| +
 | |
| +#
 | |
| +# Client-side
 | |
| +<client>
 | |
| +<features>
 | |
| +proxy
 | |
| +</features>
 | |
| +<server>
 | |
| +http
 | |
| +socks5
 | |
| +</server>
 | |
| + <name>
 | |
| +SOCKS5h with HTTP redirect to hostname too long
 | |
| + </name>
 | |
| + <command>
 | |
| +--no-progress-meter --location --proxy socks5h://%HOSTIP:%SOCKSPORT http://%HOSTIP:%HTTPPORT/%TESTNUMBER
 | |
| +</command>
 | |
| +</client>
 | |
| +
 | |
| +#
 | |
| +# Verify data after the test has been "shot"
 | |
| +<verify>
 | |
| +<protocol crlf="yes">
 | |
| +GET /%TESTNUMBER HTTP/1.1
 | |
| +Host: %HOSTIP:%HTTPPORT
 | |
| +User-Agent: curl/%VERSION
 | |
| +Accept: */*
 | |
| +
 | |
| +</protocol>
 | |
| +<errorcode>
 | |
| +97
 | |
| +</errorcode>
 | |
| +# the error message is verified because error code CURLE_PROXY (97) may be
 | |
| +# returned for any number of reasons and we need to make sure it is
 | |
| +# specifically for the reason below so that we know the check is working.
 | |
| +<stderr mode="text">
 | |
| +curl: (97) SOCKS5: the destination hostname is too long to be resolved remotely by the proxy.
 | |
| +</stderr>
 | |
| +</verify>
 | |
| +</testcase>
 | |
| -- 
 | |
| 2.42.0
 | |
| 
 |