Bug 852282 - (CVE-2012-3541) CVE-2012-3541 rpcbind: -h fails to control access to rpcbind
CVE-2012-3541 rpcbind: -h fails to control access to rpcbind
Status: CLOSED NOTABUG
Product: Security Response
Classification: Other
Component: vulnerability (Show other bugs)
unspecified
All Linux
medium Severity medium
: ---
: ---
Assigned To: Red Hat Product Security
impact=moderate,public=20140708,repor...
: Reopened, Security
Depends On: 1101882 1101883 1101884 1101885
Blocks: 852284
  Show dependency treegraph
 
Reported: 2012-08-28 02:30 EDT by Kurt Seifried
Modified: 2015-02-25 04:20 EST (History)
7 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2015-02-24 01:17:11 EST
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)

  None (edit)
Description Kurt Seifried 2012-08-28 02:30:32 EDT
Kurt Seifried (kseifried@redhat.com) 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 15:49:59 EST
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
[1]+  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 15:53:59 EST
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 15:55:39 EST
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 08:00:34 EST
(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 14:54:14 EST
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 16:29:58 EST
(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 01:17:11 EST
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.

Note You need to log in before you can comment on or make changes to this bug.