Created attachment 1481 [details] Ignore a EADDRNOTAVAIL error when binding to the X11 forwarding port This bug happen with 5.0p1 (but this version was not available in the version field of the bug report form). The patch for CVE-2008-1483 applied in this release has a side effect on Solaris (at least Solaris 10, I didn't test on other solaris versions). With this patch, openssh will do X forwarding on a port only if it successfully binded to it on the inet4 and inet6 address (if the latter was available). The problem is that on Solaris 10, even if ipv6 was not enabled at install time, the getaddrinfo will still return the ipv6 address in addition to the ipv4 address. As a result, when try to bind to port A, openssh will try to bind to 127.0.0.1:A and ::1:A, and the latter will always fail as there are not ipv6-enabled localhost interface. So openssh will not be able to bind on any port and X Forwarding will not work. I don't know it it can be considered a solaris bug or openssh bug. To fix this bug, I slightly modified the security fix patch so openssh will ignore an error on an address if the errno is EADDRNOTAVAIL. This fixes the bug and still seems to avoid the X11 hijacking bug but I am not sure it's the good solution. One possible problem is if a sysadmin configures the inet6 loopback interface after someone already did X forwarding. That would leave a window for an attacker. He could then listen on the 6010 port on the inet6 interface to hijack X11 communication coming from apps which first try the ipv6 port. That's not likely to happen often but still...
I think this is a Solaris bug in the getaddrinfo implementation - there is no reason for it to return addresses that will never bind. You can work around this by specifying "AddressFamily inet" in your sshd_config.
Yes it's what I'm wondering and I am trying to see how other os behave. BTW, while reading the getaddrinfo manpage, I found the following option: If the AI_ADDRCONFIG flag is specified, IPv4 addresses are returned only if an IPv4 address is configured on the local system, and IPv6 addresses are returned only if an IPv6 address is configured on the local system. For this case, the loopback address is not considered to be as valid as a configured address. For example, when using the DNS, a query for AAAA records should occur only if the node has at least one IPv6 address configured (other than IPv6 loopback) and a query for A records should occur only if the node has at least one IPv4 address configured (other than the IPv4 loopback). that could have been interesting. However as an ipv6 loopback is not considered a valid interface, that would still allow an attacker to hijack a X11 session in the case only the loopback is ipv6 enabled and an application first try to talk to the X11 forwarded port via tcp6.
Made some test under Linux/Ubuntu and the same problem exists. getaddrinfo also returns the ipv6 loopback address ::1 even if inet6 is not configured on the interface. But the thing is that it's not a standard setup under linux, usually, either you have ipv6 enabled and ipv6 on all interfaces, or ipv6 is disabled. To reproduce the bug, I had to load the ipv6 module and then manually disable the inet6 loopback address. You usually don't meet the solaris-like case where ipv6 is in fact enabled but no interface is configured with ipv6 support. So I suppose that theoretically, you should not assume that addresses informations returned by getaddrinfo are valid ones, but I didn't yet read POSIX to check. BTW, I maintain the blastwave openssh package [1] and I would like to apply the attached patch on the stable package. May I request your opinion about it ? [1] http://www.blastwave.org/
Well, I'd be wary of doing this - adding hacks to support broken systems is what got us this bug to begin with :(
Well, I don't want to break X11 forwarding on a lot of systems with a stable update, so I just would like to know it the patch attached still fixes properly the security hole without side-effects. About this patch being a hack, it's true I have to make this modification for a solaris-specific issue, but to not bind on non-existing interface could be considered good behavior. Anyway, if you're not interested in this issue, feel free to change it to WONTFIX or INVALID.
Any updates on this? I built 6.4p1 and found the problem still exists on Solaris 9 and 10 (at least) with no IPV6 running. I applied this patch to workaround the issue: *** channels.c.orig Fri Nov 8 01:28:04 2013 --- channels.c Wed Jan 1 11:46:27 2014 *************** *** 3466,3471 **** --- 3466,3474 ---- debug2("bind port %d: %.100s", port, strerror(errno)); close(sock); + if (ai->ai_next) + continue; + for (n = 0; n < num_socks; n++) { close(socks[n]); } This restores a piece of code that was there in an older release (got it from 4.7p1 actually) Comparing similar code for general port forwarding binds, this code now behaves like that; ie: works on Solaris without ipv6 enabled. The code I'm referring into is the bind-fail case in channel_setup_fwd_listener(); note it continues trying to bind to other addresses if one fails.
FYI had to apply the same patch to 7.1p1
Note that you're reimplementing CVE-2008-1483 there. I doubt we're ever going to change this, you should push for your OS vendor for saner behaviour.
Ok agreed, my patch reopens that CVE. The problem is that on Solaris 9 and Solaris 10 if you don't have IPv6 addresses configured, getaddrinfo() returns both AF_INET and AF_INET6 entries, and it returns AF_INET6 *first*. An attempted bind() to an AF_INET6 address on a system without IPv6 addresses configured returns EADDRNOTAVAIL, and the distributed code will not try the AF_INET (IPV4) bind at all; my patch allows it to continue on, but as you say that creates a potential security issue. What probably should happen in this code is that the bind result should be checked for EADDRNOTAVAIL error and not consider that a bail-out case; keep going anyway with other bind attempts; and that way an IPv4 only system will be happy and bind there. Anyway a workaround on such systems is to set this in sshd_config AddressFamily inet so I've undone my change and done that instead. Case closed I guess.
Close all resolved bugs after 7.3p1 release