From 024bbf84f137b6e937f8a702cb0718544e48483a Mon Sep 17 00:00:00 2001 From: nnposter Date: Tue, 16 Mar 2021 02:34:35 +0000 Subject: [PATCH] Make sure that SOCKS proxied server data are processed There was a race condition where proxied server data could arrive appended to the final SOCKS handshake response, causing the data to get skipped. --- CHANGELOG | 4 ++++ ncat/ncat_connect.c | 44 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 92530d9e2..0f70ca8b4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,10 @@ o [GH#2206] Nmap no longer produces cryptic message "Failed to convert o [Ncat][GH#2202] Use safety-checked versions of FD_* macros to abort early if number of connections exceeds FD_SETSIZE. [Pavel Zhukov] +o [Ncat] Connections proxied via SOCKS4/SOCKS5 were intermittently dropping + server data sent right after the connection got established, such as port + banners. [Sami Pönkänen] + o Nmap will now output a list of port numbers for each "ignored" state in the "extrareasons" element in XML output. The "All X ports" and "Not shown:" lines in normal output have been changed slightly to provide more detail. [Daniel Miller] diff --git a/ncat/ncat_connect.c b/ncat/ncat_connect.c index 21124e7fb..c0d4b4089 100644 --- a/ncat/ncat_connect.c +++ b/ncat/ncat_connect.c @@ -552,6 +552,8 @@ static int do_proxy_socks4(void) union sockaddr_u addr; size_t sslen; int sd; + size_t remainderlen; + char* remainder; if (getaddrfamily(o.target) == 2) { loguser("Error: IPv6 addresses are not supported with Socks4.\n"); @@ -629,6 +631,10 @@ static int do_proxy_socks4(void) return -1; } + /* whatever is left in the buffer is part of the proxied connection */ + remainder = socket_buffer_remainder(&stateful_buf, &remainderlen); + Write(STDOUT_FILENO, remainder, remainderlen); + return sd; } @@ -641,7 +647,7 @@ static int do_proxy_socks5(void) struct socket_buffer stateful_buf; struct socks5_connect socks5msg; uint16_t proxyport = htons(o.portno); - char socksbuf[8]; + char socksbuf[4]; int sd; size_t dstlen, targetlen; struct socks5_request socks5msg2; @@ -653,6 +659,10 @@ static int do_proxy_socks5(void) void *addrbuf; size_t addrlen; char addrstr[INET6_ADDRSTRLEN]; + size_t bndaddrlen; + char bndaddr[16 + 2]; /* IPv4/IPv6 address and port */ + size_t remainderlen; + char* remainder; sd = do_connect(SOCK_STREAM); if (sd == -1) { @@ -847,13 +857,18 @@ static int do_proxy_socks5(void) return -1; } - /* TODO just two bytes for now, need to read more for bind */ - if (socket_buffer_readcount(&stateful_buf, socksbuf, 2) < 0) { + if (socket_buffer_readcount(&stateful_buf, socksbuf, 4) < 0) { loguser("Error: malformed request response from proxy.\n"); close(sd); return -1; } + if (socksbuf[0] != SOCKS5_VERSION) { + loguser("Error: wrong SOCKS version in request response.\n"); + close(sd); + return -1; + } + switch(socksbuf[1]) { case 0: if (o.verbose) @@ -897,6 +912,29 @@ static int do_proxy_socks5(void) return -1; } + switch (socksbuf[3]) { + case SOCKS5_ATYP_IPv4: + bndaddrlen = 4 + 2; + break; + case SOCKS5_ATYP_IPv6: + bndaddrlen = 16 + 2; + break; + default: + loguser("Error: invalid proxy bind address type.\n"); + close(sd); + return -1; + } + + if (socket_buffer_readcount(&stateful_buf, bndaddr, bndaddrlen) < 0) { + loguser("Error: malformed request response from proxy.\n"); + close(sd); + return -1; + } + + /* whatever is left in the buffer is part of the proxied connection */ + remainder = socket_buffer_remainder(&stateful_buf, &remainderlen); + Write(STDOUT_FILENO, remainder, remainderlen); + return(sd); }