|Summary:||CVE-2012-3541 rpcbind: -h fails to control access to rpcbind|
|Product:||[Other] Security Response||Reporter:||Kurt Seifried <kseifried>|
|Component:||vulnerability||Assignee:||Red Hat Product Security <security-response-team>|
|Status:||CLOSED NOTABUG||QA Contact:|
|Version:||unspecified||CC:||carnil, jrusnack, kseifried, mjc, security-response-team, steved|
|Target Milestone:||---||Keywords:||Reopened, Security|
|Fixed In Version:||Doc Type:||Bug Fix|
|Doc Text:||Story Points:||---|
|Last Closed:||2015-02-24 06:17:11 UTC||Type:||---|
|oVirt Team:||---||RHEL 7.3 requirements from Atomic Host:|
|Cloudforms Team:||---||Target Upstream Version:|
|Bug Depends On:||1101882, 1101883, 1101884, 1101885|
Description Kurt Seifried 2012-08-28 06:30:32 UTC
Kurt Seifried (firstname.lastname@example.org) of Red Hat reports: rpcbind offers a "-h" option that binds rpcbind to a specific IP address. If the "-h" option is not used then rpcbind will attach to INADDR_ANY (0.0.0.0 for ipv4, ::: for ipv6). When "rpcbind -h 127.0.0.1" is specified rpcbind still attaches to all IP addresses: # rpcbind -h 127.0.0.1 # ps xauww | grep rpcbind root 24618 0.0 0.0 19172 848 ? Ss 00:19 0:00 rpcbind -h 127.0.0.1 # netstat -vatn | grep 111 tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN tcp 0 0 :::111 :::* LISTEN However if you check using nmap: # nmap -sU -p 111 192.168.1.2 Starting Nmap 5.51 ( http://nmap.org ) at 2012-08-28 00:19 MDT Nmap scan report for 192.168.1.2 Host is up (0.00045s latency). PORT STATE SERVICE 111/udp closed rpcbind MAC Address: 00:00:45:67:89:AB (Cadmus Computer Systems) Nmap done: 1 IP address (1 host up) scanned in 0.39 seconds So this is good right? Except if you run rpcinfo: [root@fw00 ~]# rpcinfo 192.168.1.2 program version netid address service owner 100000 4 tcp6 ::.0.111 portmapper superuser 100000 3 tcp6 ::.0.111 portmapper superuser 100000 4 udp6 ::1.0.111 portmapper superuser 100000 3 udp6 ::1.0.111 portmapper superuser 100000 4 tcp 0.0.0.0.0.111 portmapper superuser 100000 3 tcp 0.0.0.0.0.111 portmapper superuser 100000 2 tcp 0.0.0.0.0.111 portmapper superuser 100000 4 udp 127.0.0.1.0.111 portmapper superuser 100000 3 udp 127.0.0.1.0.111 portmapper superuser 100000 2 udp 127.0.0.1.0.111 portmapper superuser 100000 4 local /var/run/rpcbind.sock portmapper superuser 100000 3 local /var/run/rpcbind.sock portmapper superuser Which results in a disclosure of information. Tested on RHEL 6, Fedora and Debian 6 (all of which include ship 0.2.0 which was released in 2009). As an interim workaround ensure that port 111 is firewalled properly in iptables and ip6tables.
Comment 1 Vincent Danen 2012-11-21 20:49:59 UTC
This also happens with rpc.statd's -n option, which means that it may affect all of the programs in nfs-utils (shared code). For instance: [root@thor sysconfig]# fg rpc.statd -p 662 -o 2020 -n localhost -d -F ^Z + Stopped rpc.statd -p 662 -o 2020 -n localhost -d -F [root@thor sysconfig]# netstat -l --tcp -p|grep statd tcp 0 0 *:pftp *:* LISTEN 2251/rpc.statd tcp 0 0 *:pftp *:* LISTEN 2251/rpc.statd
Comment 2 Vincent Danen 2012-11-21 20:53:59 UTC
Actually, the above would be from nfs-utils while rpcbind is from the rpcbind package. It might be shared code, but maybe not (I thought rpcbind was still from nfs-utils, but it isn't, at least on RHEL6).
Comment 3 Vincent Danen 2012-11-21 20:55:39 UTC
Also forgot to note the Debian bug that brought rpc.statd to my attention: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=457095
Comment 7 Tomas Hoger 2015-02-03 13:00:34 UTC
(In reply to Kurt Seifried from comment #0) > rpcbind offers a "-h" option that binds rpcbind to a specific IP address. If > the "-h" option is not used then rpcbind will attach to INADDR_ANY > (0.0.0.0 for ipv4, ::: for ipv6). Quoting documentation for this option from the rpcbind(8) man page: -h Specify specific IP addresses to bind to for *UDP* requests. This option may be specified multiple times and is typically necessary when running on a multi-homed host. If no -h option is specified, rpcbind will bind to INADDR_ANY, which could lead to problems on a multi-homed host due to rpcbind returning a UDP packet from a different IP address than it was sent to. Note that when specifying IP addresses with -h, rpcbind will automatically add 127.0.0.1 and if IPv6 is enabled, ::1 to the list. Emphasis for UDP is mine. > When "rpcbind -h 127.0.0.1" is specified rpcbind still attaches to all IP > addresses: ... > # netstat -vatn | grep 111 > tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN > tcp 0 0 :::111 :::* LISTEN This only checks TCP sockets, and does not check UDP, which is what should be affected by the use of -h option according to the man page. This is more complete output, first rpcbind without any -h option: # netstat -vatun | grep :111 tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN tcp6 0 0 :::111 :::* LISTEN udp 0 0 0.0.0.0:111 0.0.0.0:* udp6 0 0 :::111 :::* and with -h 127.0.0.1: # netstat -vatun | grep :111 tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN tcp6 0 0 :::111 :::* LISTEN udp 0 0 127.0.0.1:111 0.0.0.0:* udp6 0 0 ::1:111 :::* Use of the -h option makes rpcbind only bind 127.0.0.1/::1 UDP/UDP6. > However if you check using nmap: > > # nmap -sU -p 111 192.168.1.2 ... > PORT STATE SERVICE > 111/udp closed rpcbind This tests UDP port, which is no longer bound to INADDR_ANY. Repeating for both UDP and TCP yields: # nmap -sT -sU -p 111 192.168.1.2 ... PORT STATE SERVICE 111/tcp open rpcbind 111/udp closed rpcbind This is consistent with the netstat output above. > So this is good right? Except if you run rpcinfo: > > [root@fw00 ~]# rpcinfo 192.168.1.2 This uses TCP, which is not restricted by -h. Compare with the following: $ rpcinfo -l -T tcp 192.168.1.2 100000 4 vs. $ rpcinfo -l -T udp 192.168.1.2 100000 4 AFAICS, this works as documented. It does not seem -h is intended be access control mechanism, but rather a way to prevent failures for UDP and multi-homed hosts. So this seems to be the way to control network access to the service: > As an interim workaround ensure that port 111 is firewalled properly in > iptables and ip6tables. Alternative is to use hosts.allow / hosts.deny, as rpcbind uses TCP wrappers. Ok to close:notabug?
Comment 8 Kurt Seifried 2015-02-03 19:54:14 UTC
So CVE-2012-3541 (https://bugzilla.redhat.com/show_bug.cgi?id=852282) is a somewhat odd case, rpcbind -h controls rpc binding for UDP (but not TCP, that's a whole other discussion). If you bind rpcbind to localhost you cannot connect remotely as expected, but locally you still can for example connect to an IP bound to the system (e.g. 10.1.2.3) and connect. So for example: /usr/sbin/rpcbind -w -h 127.0.0.1 # lsof -P | grep ":111" Output information may be incomplete. rpcbind 16669 rpc 6u IPv4 57635 0t0 UDP *:111 rpcbind 16669 rpc 8u IPv4 57637 0t0 TCP *:111 (LISTEN) rpcbind 16669 rpc 9u IPv6 57638 0t0 UDP *:111 rpcbind 16669 rpc 11u IPv6 57640 0t0 TCP *:111 (LISTEN) So the CVE stays as this violates the stated security policy of -h
Comment 9 Tomas Hoger 2015-02-03 21:29:58 UTC
(In reply to Kurt Seifried from comment #8) > If you bind rpcbind to localhost you cannot connect remotely as expected, > but locally you still can for example connect to an IP bound to the system > (e.g. 10.1.2.3) and connect. Can you hint how to demonstrate that? > So for example: ... > # lsof -P | grep ":111" When running with -h 127.0.0.1, I see: # lsof -P | grep ":111" rpcbind 24530 rpc 6u IPv4 129144 0t0 UDP localhost:111 rpcbind 24530 rpc 10u IPv4 129150 0t0 TCP *:111 (LISTEN) rpcbind 24530 rpc 11u IPv6 129152 0t0 UDP localhost:111 rpcbind 24530 rpc 14u IPv6 129156 0t0 TCP *:111 (LISTEN)
Comment 10 Kurt Seifried 2015-02-24 06:17:11 UTC
So unfortunately I forgot that Linux has the loose IP matching, e.g. from a local system packets will get delivered that maybe should not be, that's just how things are. Redid my testing from a remote system and confirmed I was wrong. Please REJECT CVE-2012-3541, I have confirmed it behaves as expected, annoyingly it does filter UDP, but not TCP, as the man page states (this feature is a whole other discussion). Why the -h option only handles UDP and not TCP... anyways.