xorl %eax, %eax

Solaris NFSv4 Source Port Security Bypass

leave a comment »

This issue was disclosed by Sun Microsystems on 30 June 2009 and it affects Solaris 10 as well as OpenSolaris based upon builds snv_01 through snv_118. Solaris NFS implementation provides an additional security measure, that is the force of using specific source ports during the connection. As we can read from src/uts/common/fs/nfs/nfs_server.c:

/*
* If nfs_portmon is set, then clients are required to use privileged
* ports (ports < IPPORT_RESERVED) in order to get NFS services. * * N.B.: this attempt to carry forward the already ill-conceived notion * of privileged ports for TCP/UDP is really quite ineffectual. Not only * is it transport-dependent, it's laughably easy to spoof. If you're * really interested in security, you must start with secure RPC instead. */ static int nfs_portmon = 0; [/sourcecode] This means that the clients are required to have root privileges in order to use a privileged port. However, even though the function responsible for authentication checks on NFS V3 and V2 performs the source port check: [sourcecode language="c"] /* * checkauth() will check the access permission against the export * information. Then map root uid/gid to appropriate uid/gid. * * This routine is used by NFS V3 and V2 code. */ static int checkauth(struct exportinfo *exi, struct svc_req *req, cred_t *cr, int anon_ok, bool_t publicfh_ok) { ... /* * Check for privileged port number * N.B.: this assumes that we know the format of a netbuf. */ if (nfs_portmon) { ... cmn_err(CE_NOTE, "nfs_server: client %s%ssent NFS request from " "unprivileged port", client_name(req), client_addr(req, buf)); return (0); ... } [/sourcecode] The equivalent checkauth4() function for the NFS V4 has no check for nfs_portmon. This way a user is able to completely bypass the source port check simply by using NFSv4. The fix to this vulnerability was to add the missing check to chechauth4(). [sourcecode language="c"] + * Check for privileged port number + * N.B.: this assumes that we know the format of a netbuf. + */ + if (nfs_portmon) { + struct sockaddr *ca; + ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; + + if (ca == NULL) + return (0); + + if ((ca->sa_family == AF_INET && + ntohs(((struct sockaddr_in *)ca)->sin_port) >= + IPPORT_RESERVED) || + (ca->sa_family == AF_INET6 && + ntohs(((struct sockaddr_in6 *)ca)->sin6_port) >= + IPPORT_RESERVED)) { + cmn_err(CE_NOTE, + "nfs_server: client %s%ssent NFSv4 request from " + "unprivileged port", + client_name(req), client_addr(req, buf)); + return (0); + } + } + + /* [/sourcecode]

Written by xorl

July 3, 2009 at 14:18

Posted in bugs, solaris

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s