Solaris NFS Client Module Vulnerability
Release date: 27-06-2009
1. Summary
There is a vulnerability in Solaris 10 kernel RPC implementation resulting in
an attacker being able to perform a denial of service attack on an NFS server
service. One crafted UDP packet is sufficient to send to port 2049 (rpc program
number 100003 or program number 100227) to trigger the kernel panic and
subsequent core dump. Remote code execution is very unlikely though.
Solaris 10 SPARC, x86 and x64 platforms are affected, all with the latest
10_Recommended patches applied. Other versions were not tested. The source
code references come from the Nevada projects sources available on
http://cvs.opensolaris.org dated on 25.02.2007.
2. Details
The code snippets aren taken from http://cvs.opensolaris.org, and may be
different than the Solaris 10 code which I tested and debugged this issue on
(see section 5). The line numbers correspond to the current source tree on the
webpage.
The kernel RPC implementation performs insufficient sanitization checks on RPC
functions parameters coming in via the network, packaged using the eXternal
Data Representation (XDR) language (RFC-1014). Specifically, when the variable
length opaque data type parameter is being passed via XDR to NFS server (such
as the file handle for the NFS operation, see RFC mentioned), the data is
followed by the 4 byte length field. If the length is modified to be negative,
the system crashes with the panic message similar to the below:
panic[cpu0]/thread=d5e50400:
BAD TRAP: type=e (#pf Page fault) rp=d5df0a08 addr=9a6be424 occurred in module "
genunix" due to an illegal access to a user address
nfsd:
#pf Page fault
Bad kernel fault at addr=0x9a6be424
pid=4722, pc=0xfe9790c2, sp=0xd5df0b3c, eflags=0x10216
cr0: 8005003b<pg,wp,ne,et,ts,mp,pe> cr4:6b8<xmme,fxsr,pge,pae,pse,de>
cr2: 9a6be424 cr3: 701b020
gs: 534601b0 fs: 45530000 es: 54540160 ds: 6c630160
edi: 0 esi: d4d7a444 ebp: d5df0a58 esp: d5df0a40
ebx: d41b2e80 edx: d4d7a444 ecx: d4d7a444 eax: 9a6be424
trp: e err: 0 eip: fe9790c2 cs: 158
efl: 10216 usp: d5df0b3c ss: d5df0a68
d5df0968 unix:die+a7 (e, d5df0a08, 9a6be4)
d5df09f4 unix:trap+103f (d5df0a08, 9a6be424,)
d5df0a08 unix:_cmntrap+9a (534601b0, 45530000,)
d5df0a58 genunix:xdrmblk_getint32+72 (d4d7a444, d5df0a8c,)
d5df0a68 genunix:xdr_u_int+32 (d4d7a444, d5df0a8c)
d5df0a90 nfs:xdr_string3+4c (d4d7a444, d5df0b3c,)
d5df0aa8 nfs:xdr_diropargs3+5f (d4d7a444, d5df0af0,)
d5df0ab8 rpcsec:svc_authany_wrap+e (d4d7a404, d4d7a444,)
d5df0ad0 rpcmod:svc_clts_kgetargs+1b (d4d7a3c0, fa0e1f98,)
d5df0d24 nfssrv:common_dispatch+e2 (d5df0d9c, d4d7a3c0,)
d5df0d44 nfssrv:rfs_dispatch+1c (d5df0d9c, d4d7a3c0)
d5df0dd0 rpcmod:svc_getreq+158 (d4d7a3c0, d437b400)
d5df0df8 rpcmod:svc_run+125 (d5f44d50)
d5df0e0c rpcmod:rdmadrhashstat+24c20430 (1)
d5df0f84 nfs:nfssys+4cf (e, d2970fd4, d686, )
3. Code analysis
The xdrmblk_control() function is responsible for getting the arguments out of
the UDP packet and moving the pointer forward to the next argument. If the
length is negative, the xdrmblk_control() will not verify this and will
execute the following code:
m->b_rptr += len
As the len is a negative number, it makes the m->b_rptr point to a buggy address
(the address depends on the current memory layout). If this pointer is later
referenced to pick up the next argument from the packet, it will most likely
reference the unmapped address and cause the unhandled page fault with a
subsequent panic. For example, if the next argument is supposed to be an integer
(like in setfattr() call), the following part of the xdrmblk_getint32() function
is to be executed:
xdr_mblk.c#133 ::
int32p = ntohl(((int32_t *)(m->b_rptr)));
As the m->b_rptr pointer points to the buggy address, the system will crash with
the panic message similar to the one section 2 while trying to dereference
m->b_rptr.
Remote code execution is unlikely, because the m->b_rprt (EAX register in the
above x86 panic message) value depends on a current kernel memory allocation
layout.
4. Exploit
The malicious udp packet makes the system call the setfattr() NFS function
(function number 2 in the program interface number 100003) with a negative
length (0xAABBCCDD) of the following filehandle parameter. If the `share'
command has been executed and the nfs server is running, the system will crash.
The malicious UDP packet is not included in this advisory.
5. Fix
This bug seems to be corrected in http://cvs.opensolaris.org code I viewed:
if (len < 0)
return (FALSE);
But still all my Solaris 10 boxes are vulnerable to this issue (with the latest Recommended patches applied). This patch seems not to be included in Solaris 10 (at least I couldn't find the assembly part that matches this code). Neither I could find any Sun Alert describing this issue either.
UPDATE: this issue has been fixed by the vendor: http://sunsolve.sun.com/search/document.do?assetkey=1-26-102911-1
