« November 2009
SunMonTueWedThuFriSat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
     
       
Today
XML

Neat blogs

Navigation

Editing

Powered by Roller Weblogger.

statcounter.com

clustrmaps.com

Locations of visitors to this page

technorati.com

20081005 Sunday October 05, 2008
The myth of security with AUTH_SYS

AUTH_SYS is an insecure security mode, yet it is commonly used within companies. It can be used as the proverbial open lock on a door - the fact that the lock is there means do not enter. But I've seen people terminated for ignoring that lock.

With that in mind, I want to go over the simple security schemes employed within a company and show why they don't work. The punchline will be of course Kerberos. Speaking of myths, one is that you need NFSv4 in order to deploy Kerberos. You don't - common servers and clients easily speak Kerberos with NFSv3. And ignore NFSv2, please, please.

Export Security

With an export (or share), the most lax security is typically the default:

[root@pnfs-9-26 ~]> zfs create rootpool/export/home/secure
[root@pnfs-9-26 ~]> share
[root@pnfs-9-26 ~]> zfs set sharenfs=on rootpool/export/home/secure
[root@pnfs-9-26 ~]> share
-@rootpool/exp  /export/home/secure   rw   ""  

I.e., every machine in the world can mount pnfs-9-26:/export/home/secure. The reasons for this default are simple:

  1. When the model was first developed
    1. the number of exports and clients was limited
    2. the degree of interconnectedness outside of the organization was limited
  2. It is hard to know beforehand where to limit access.

By default, root has access almost like any other user, but it is mapped to the user nobody. We can see this here if we grant wide open permissions on the export:

[root@pnfs-9-26 ~]> chmod 777 /export/home/secure
[root@pnfs-9-26 ~]> ls -la /export/home/secure
total 6
drwxrwxrwx   2 root     root           2 Oct  5 11:39 .
drwxr-xr-x   5 th199096 staff          6 Oct  5 11:39 ..

We should be able to create a file as anyone from another machine:

[root@jhereg ~]> mount -o vers=3 pnfs-9-26:/export/home/secure /mnt
[root@jhereg ~]> touch /mnt/i_am_root

That worked:

[root@pnfs-9-26 secure]> ls -la
total 7
drwxrwxrwx   2 root     root           3 Oct  5 11:51 .
drwxr-xr-x   5 th199096 staff          6 Oct  5 11:39 ..
-rw-r--r--   1 nobody   nobody         0 Oct  5 11:51 i_am_root

Notice that root has been mapped to nobody. What happens if we do it as a normal user:

[th199096@jhereg ~]> touch /mnt/i_am_jhereg
[th199096@jhereg ~]> touch /mnt/i_am_th199096

And we get the correct user:

[root@pnfs-9-26 secure]> ls -la
total 9
drwxrwxrwx   2 root     root           5 Oct  5 11:54 .
drwxr-xr-x   5 th199096 staff          6 Oct  5 11:39 ..
-rw-r--r--   1 th199096 staff          0 Oct  5 11:54 i_am_jhereg
-rw-r--r--   1 nobody   nobody         0 Oct  5 11:51 i_am_root
-rw-r--r--   1 th199096 staff          0 Oct  5 11:54 i_am_th199096

Now what happens if we try to remove i_am_th199096 as root?

[root@jhereg ~]> rm /mnt/i_am_th199096
rm: /mnt/i_am_th199096: override protection 644 (yes/no)? y

anon

We are allowed to do that, but is it a property of being root or the permissions? We can check this with a simple change of the share:

[root@pnfs-9-26 secure]> zfs set sharenfs=anon=-1 rootpool/export/home/secure
[root@pnfs-9-26 secure]> share
-@rootpool/exp  /export/home/secure   anon=-1   ""  

See share_nfs(1M) for a description of anon. Notice I didn't specify whether rw is set or not. We can retry the delete:

[root@jhereg ~]> rm /mnt/i_am_jhereg
NFS3 getattr failed for pnfs-9-26: RPC: Authentication error; s1 = 13, s2 = 0
rm: /mnt/i_am_jhereg: Permission denied

If you want to make sure to deny root level access to a share, then you need to set anon=-1.

Conversely, if you want to enable root level access to a share, you can set anon=0:

[root@pnfs-9-26 secure]> zfs set sharenfs=anon=0 rootpool/export/home/secure
[root@pnfs-9-26 secure]> share
-@rootpool/exp  /export/home/secure   anon=0   ""  

I've recreated the two files in the background (which shows by the way that rw is the default). And when we test the deletion:

[root@jhereg ~]> rm /mnt/i_am_jhereg
[root@jhereg ~]> 

No pesky question that implies I am not a god!

root=

If I want to allow root access from one host but deny it from all others, I can use the root= access list:

[root@pnfs-9-26 secure]> zfs set sharenfs=root=pnfs-9-25.central.sun.com rootpool/export/home/secure
[root@pnfs-9-26 secure]> share
-@rootpool/exp  /export/home/secure   sec=sys,root=pnfs-9-25   ""  

PS: The sec=sys is stating this is an AUTH_SYS share. Also, since I am using DNS for hosts in /etc/resolv.conf, I need a FQDN.

Try to remove:

[root@jhereg ~]> rm /mnt/i_am_th199096 
rm: /mnt/i_am_th199096: override protection 644 (yes/no)? yes

Since it worked and we got a prompt, it has to be the permission set which is enabling this. If we tighten things down a bit more:

[root@pnfs-9-26 secure]> zfs set sharenfs=root=pnfs-9-25.central.sun.com,anon=-1 rootpool/export/home/secure
[root@pnfs-9-26 secure]> share
-@rootpool/exp  /export/home/secure   anon=-1,sec=sys,root=pnfs-9-25   ""  

We can see we are locked out:

[root@jhereg ~]> rm /mnt/i_am_root
rm: /mnt/i_am_root: Permission denied

versus

[root@pnfs-9-25 ~]> rm /mnt/i_am_root
[root@pnfs-9-25 ~]> 

And yet the other machine reigns supreme:

We'll revisit the use effectiveness of root= without anon=, when we look at permissions.

rw=

So we can keep machines from getting access altogether by restricting the rw= access list:

[root@pnfs-9-26 ~]> zfs set sharenfs=rw=pnfs-9-25.central.sun.com rootpool/export/home/secure
[root@pnfs-9-26 ~]> share
-@rootpool/exp  /export/home/secure   sec=sys,rw=pnfs-9-25.central.sun.com   ""  

which yields on the two clients:

[root@jhereg ~]> ls -la /mnt
/mnt: Permission denied

and

[root@pnfs-9-25 ~]> ls -la /mnt
drwxrwxrwx   2 root     root           6 Oct  5 19:33 .
drwxr-xr-x  36 root     root          39 Oct  5 19:11 ..
-rw-r--r--   1 th199096 staff          0 Oct  5 13:30 i_am_here
-rw-r--r--   1 th199096 staff          0 Oct  5 13:27 i_am_pnfs-9-25
-rw-r--r--   1 th199096 staff          0 Oct  5 13:27 i_am_pnfs_9_25
-rw-r--r--   1 th199096 staff          0 Oct  5 13:30 i_am_th199096

Note that the client jhereg must be caching a file handle for the root of the export /export/home/secure on the server pnfs-9-26. If it were not, we would have to reissue the mount request, which would have to fail. Also note, it is not just the mountd requests which have to check access list permissions. If it were, then the above operations would always work. SunOS used to work this way and the Solaris NFS team made a change back in the 1995/96 time frame, see for example Brent Callaghan's presentation at the 1996 Connectathon: NFS Client Authentication. And quickly, the security reason for doing so is the implication that if a rogue client someone sniffed out a valid file handle, then it had complete access to all of the information on that share.

ro=

We can likewise grant read only access via the ro= access list.

Access list interactions

All of rw, rw=, ro, and ro= interact as described by sharenfs(1M).

File Permissions

So access lists work on machines. If a machine is able to mount a share from a server, then all users on that client can access everything on that server. Right?

Wrong. The directory and file permissions determine user access. Contrast this with a model derived from a client only having one user logged in at a time. In that situation, it may not be the machine which is important but rather the user..

If I wanted to only grant access to a single user, then I would set the owner of the share to be that user and I would also set the permissions to be 700:

[root@pnfs-9-26 ~]> chown th199096:staff /export/home/secure/
[root@pnfs-9-26 ~]> chmod 700 /export/home/secure/
[root@pnfs-9-26 ~]> ls -la /export/home/secure/
total 10
drwx------   2 th199096 staff          6 Oct  5 19:33 .
drwxr-xr-x   5 th199096 staff          6 Oct  5 11:39 ..
-rw-r--r--   1 th199096 staff          0 Oct  5 13:30 i_am_here
-rw-r--r--   1 th199096 staff          0 Oct  5 13:27 i_am_pnfs-9-25
-rw-r--r--   1 th199096 staff          0 Oct  5 13:27 i_am_pnfs_9_25
-rw-r--r--   1 th199096 staff          0 Oct  5 13:30 i_am_th199096

And lets change the share to be wide open:

[root@pnfs-9-26 ~]> zfs set sharenfs=on rootpool/export/home/secure
[root@pnfs-9-26 ~]> share
-@rootpool/exp  /export/home/secure   rw   ""  

We see root access is denied (because it maps to nobody):

[root@pnfs-9-25 ~]> ls -la /mnt
/mnt: Permission denied
total 3

But on that same machine, th199096 is granted access:

[root@pnfs-9-25 ~]> su - th199096
[th199096@pnfs-9-25 ~]> ls -la /mnt
total 12
drwx------   2 th199096 staff          6 Oct  5 19:33 .
drwxr-xr-x  36 root     root          39 Oct  5 19:11 ..
-rw-r--r--   1 th199096 staff          0 Oct  5 13:30 i_am_here
-rw-r--r--   1 th199096 staff          0 Oct  5 13:27 i_am_pnfs-9-25
-rw-r--r--   1 th199096 staff          0 Oct  5 13:27 i_am_pnfs_9_25
-rw-r--r--   1 th199096 staff          0 Oct  5 13:30 i_am_th199096

By the way, if we grant either root= or anon=0 access, then this all goes out the window:

[root@pnfs-9-26 ~]> zfs set sharenfs=rw,anon=0 rootpool/export/home/secure

yields:

[root@pnfs-9-25 ~]> ls -la /mnt
total 12
drwx------   2 th199096 staff          6 Oct  5 19:33 .
drwxr-xr-x  36 root     root          39 Oct  5 19:11 ..
-rw-r--r--   1 th199096 staff          0 Oct  5 13:30 i_am_here
-rw-r--r--   1 th199096 staff          0 Oct  5 13:27 i_am_pnfs-9-25
-rw-r--r--   1 th199096 staff          0 Oct  5 13:27 i_am_pnfs_9_25
-rw-r--r--   1 th199096 staff          0 Oct  5 13:30 i_am_th199096

A client's root only gets to boss things around if the server grants permission.

The final myth of AUTH_SYS

Take a server for which the root account is locked down. Assume admins who don't want an inadvertent 'rm -rf /net' to nuke their server, so by default they create shares of the form:

[root@pnfs-9-26 ~]> zfs set sharenfs=rw,anon=-1 rootpool/export/home/secure

And further, at some point someone decides to lock down a share's permissions, i.e., 700 on the user th199096.

How long would it take someone to get access over AUTH_SYS?

Not long - even though we know root access is out and we can assume they do not know my password. Since we use NIS, they can do a 'ypcat passwd | grep th199096' and grab my uid. Then they only have to create a dummy account a test machine.

What if we create a special account, not in NIS? Well, they may not have root access on the server, but if they have any access, then they could cd to the parent directory, issue an 'ls -la', see the user name, and then grep for it out of /etc/passwd.

You could lock down the machine, lock down the NIS database, etc. But the fact remains that if I can mount it, then I can create a simple script to try every UID until I get access. How many servers out there check for getattr storms?

The answer is to further restrict the access lists. But eventually, if I'm able to gain access to one of the restricted machines or if I can bring up my box with the same IP as one of the restricted machines, I can get access.

Kerberos

But all I need to do to combat this without all of these "extreme" measures is to enable Kerberos on the server:

[root@pnfs-9-26 ~]> zfs set sharenfs=sec=krb5,rw,anon=-1 rootpool/export/home/secure
[root@pnfs-9-26 ~]> share
-@rootpool/exp  /export/home/secure   anon=-1,sec=krb5,rw   ""  

I am the right user (actually my uid on pnfs-9-25 matches that of the uid of the user th199096 on pnfs-9-26), but it fails:

[th199096@pnfs-9-25 ~]> ls -al /mnt
NFS3 access failed for pnfs-9-26: RPC: Authentication error; s1 = 13, s2 = 0
/mnt: Permission denied
total 3

Originally posted on Kool Aid Served Daily
Copyright (C) 2008, Kool Aid Served Daily

Trackback URL: http://blogs.sun.com/tdh/entry/the_myth_of_security_with
Comments:

This looks great and all, except for one thing: all of the corporate user ID's and passwords are in ldap, and we have yet to find a way to sync the ldap password with the one in Sun's kerberos server.

It took us long enough to go with one password repository, and folks are not very happy with the prospect of going back to two.

Anybody have any ideas? We did note that the ldap server can do a passthrough to kerberos, but then we would have to shift the password store, resulting in a layer of complexity that would not benefit 90% of our users who never use nfs. Then there is the not so nice method of using AD as a kerberos server. (There is something fundamentally wrong with having to use sun's ldap -> ad sync tool in order to get the functionality of ldap -> kerberos password sync)

Posted by john on October 05, 2008 at 10:03 PM CDT #

The Solaris Kerberos KDC does not, but should provide a password synchronization hook.

I think there's an RFE open for this. I'll dig it up. Meanwhile you can always build such a hook via DTrace on the KDC.

Posted by Nicolas Williams on October 06, 2008 at 03:56 PM CDT #

I'd recommend using krb5i or krb5p in practice though. "krb5" is only Kerberos auth it doesn't protect the data from being modified on the wire.

Posted by Darren Moffat on October 07, 2008 at 06:27 AM CDT #

Darren,

I'd like to get them started with any form of Kerberos.

Thanks,
Tom

Posted by Tom Haynes on October 07, 2008 at 11:59 AM CDT #

Post a Comment:

Name:
E-Mail:
URL:

Your Comment:

HTML Syntax: NOT allowed