COMMAND
rpc.bind
SYSTEMS AFFECTED
Solaris
PROBLEM
Ivan Arce posted following. While this is hardly a new bug and
the dangers of not having proper anti-spoofing checks in your
perimeter router/firewall has been discussed over and over in the
past years. The following can be taken as an example of how a
combination of bugs, protocol flaws and bad coding practices can
bring to life new incarnations of ancient security problems.
This was discussed months ago with Oliver Friederichs and Theo de
Raadt over considerable amounts of beer, since then Ivan didn't
have time to investigate further till last week. Sebastian R.
Wain provided a lot of his time testing and figuring out the
detailst.
Bypassing restrictions for the PMAPPROC_CALLIT procedure in rpcbind
===================================================================
Altho. rpcbind/portmap explicitly restricts which programs can be
contacted using PMAPPROC_CALLIT there is a way to bypass these
restrictions in Solaris. Upon startup Solaris' rpcbind opens a
socket that will be used to service PMAPPROC_CALLIT requests,
this is refered as the 'Non Standard Port' in the NAI-0015:
Solaris rpcbind weaknesses advisory and Sun's Security Bulleting
#142 and on these pages is available too. The advisory makes
clear that older rpcbind programs also allowed and serviced
incoming RPC calls on that port. This is no longer the case, but
the port is used to send outgoing RPC calls that correspond to RPC
PMAPPROC_CALLIT requests received on the standard rpcbind port
(111/udp and tcp).
For that purpose rpcbind allocates an internal table that maps
the received CALLIT requests to the requests forwarded by rpcbind
to service those requests. This mapping is done by matching the
RPC XIDs of both the received and forwarded calls. The XIDS
generated for the forwarded calls can be guessed since they are
not entirely random. The source port of the forwarded calls does
not vary between different PMAPPROC_CALLIT calls.
Provided that one can inject spoofed packets on the network that
is running the RPC services it is possible to communicate with
ANY RPC service AND obtain RPC replies using PMAP_CALLIT. As an
example, lets describe how one could still grab file handles out
of mountd [assuming that attacked.host.com is exporting a
filesystem and allows bouncing.host.com to mount it,
attacking.host.com is able to mount it following these steps]:
1. Attacker sends a spoofed PMAPPROC_SET call to register a
service named "bogusd" on the any available port on
localhost.
src addr : 127.0.0.1
dst addr : bouncing.host.com
dst port : 111
program : rpcbind
procedure: PMAPPROC_SET
data : BOGUSPROG,BOGUSVERS,BOGUS_PORT,etc
2. Attacker sends NON-spoofed calls to PMAPPROC_CALLIT asking
to call bogusd procedure FOO.
src addr : attacking.host.com
dst addr : bouncing.host.com
dst port : 111
program : rpcbind
procedure: PMAPPROC_CALLIT
data : BOGUSPROG,BOGUSVERS,BOGUS_PROCFOO,etc
3. Attacker sends a set of spoofed replies to the port that
rpcbind uses for forwarding of RPC calls. Each reply in
this set has a different XID choosen from a given range.
For each spoofed reply:
src addr : 127.0.0.1
src port : BOGUS_PORT
dst addr : bouncing.host.com
dst port : rpcbind_forwarding_port (usually around 32500 )
XID : xid_i ( 0 < i < I ; xid_0 is calculated using information
about the bouncing.host.com's uptime)
4. Attacker waits for a RPC reply to one of his CALLIT calls
to bogusd, procedure BOGUS_NULL. The attacker will receive
a reply when one of the spoofed replies sent in (3) had a
matching XID. The attacker has guessed the XID that
rpcbind used (XID_j / i < j < I) and can predict the next
one (we call it XID_j+1)
5. attacker sends rpcbind a NON-spoofed CALLIT call to BOGUSPROG
src addr : attacking.host.com
dst addr : bouncing.host.com
program : rpcbind
procedure: PMAPPROC_CALLIT
data : BOGUSPROG,BOGUSVERS,BOGUS_PROCFOO,etc
This will generate a RPC call from rpcbind on the bouncing
host to BOGUS_PROGRAMNUM on the bouncing host as follows:
src addr : bouncing.host.com
src port : rpcbind_forwarding_port
dst addr : bouncing.host.com
dst port : BOGUS_PORT
program : BOGUSPROG
procedure: BOGUS_PROCFOO
XID : xid_j+1
6. attacker sends a spoofed call to mountd's RPCMNT_MOUNT
procedure with:
src addr : bouncing.host.com
src port : rpcbind_forwarding_port
dst addr : attacked.host.com
dst port : MOUNTD_PORT
program : MOUNTPROG
procedure: MOUNT_PROCMNT
XID : xid_j+1
7. mountd on the attacked host replies to this request with
the proper filehandle, rpcbind will get the reply, match it
to a previous CALLIT request, and pass it back to the
caller.
The attacker has just grabbed a filehandle, bypassing the
restrictions imposed in rpcbind for CALLIT calls.
Its important to notice that altho the attacker is spoofing
she does receive the responses from the service being
attacked, this is done by the kind vulnerable rpcbind on
the bouncing host.
This is possible because:
1. XIDs of the forwarded calls are predictable
Assuming that our RPC calls to rpcbind, PROC_CALLIT are the
first CALLIT requests received by the bouncing host since
it was booted (this is a fair assumption) and knowning or
being able to aproximate. The uptime of the target host,
the XIDs that rpcbind will generate for the forwarded
requests can be easily predicted.
2. Theres no check for the src address and port of the replies
to forwarded calls to match the dst address and port of the
original call. rpcbind does not check that RPC reply
messages, received on the socket used to forward CALLIT
requests, have a valid source address, port, prognum,
progvers, etc.
Given this, the exploit can be used to 'bounce' mount requests off
any Solaris host allowed to mount a NFS file system local or
remote. However, in order to succeed, the target mountd must
allow mount requests from unpriviledged ports. This same scheme
can be used to comunicate with any RPC service.
Altho. no exploit code is provided, it is believed the detailed
explanation of the steps to follow is more than enough to code
your own testing program.
Keep in mind that this arises from several trivialy fixed
problems:
. DO NOT allow spoofed packets into your network
. allowing connections to rpcbind from external addresses is
not a good idea.
. mount requests from unpriviledged ports are not a good idea
. Exposing server information that by itself can be deemed
inocuos can help attackers in their efforts, in this case,
exposing the uptime of your Solaris box is... not a good
idea.. who would have thought eh?
As for localnet... well, no one has to go thru all this if you
have access to the local net and can sniff and spoof NFS packets..
SOLUTION
These attacks only work on unpatched Solaris 2.6 and before. The
relevant Sun bug is:
4070261 predictable RPC XIDs when forwarding CALLIT RPCs
The following patches that have been around for quite some time
fix this problem:
102034-05: SunOS 5.3: usr/sbin/rpcbind patch
102070-06: SunOS 5.4: usr/sbin/rpcbind patch
102071-06: SunOS 5.4_x86: usr/sbin/rpcbind patch
104331-07: SunOS 5.5.1: /usr/sbin/rpcbind patch
104332-07: SunOS 5.5.1_x86: /usr/sbin/rpcbind patch
104357-06: SunOS 5.5: usr/sbin/rpcbind patch
104358-05: SunOS 5.5_x86: usr/sbin/rpcbind patch
105216-03: SunOS 5.6: /usr/sbin/rpcbind patch
105217-03: SunOS 5.6_x86: /usr/sbin/rpcbind patch
Solaris 7 has this bug fixed.