ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

CVE-1999-0554:showmount -e NFS 信息泄露加固

CVE-1999-0554:showmount -e NFS 信息泄露加固 1. 从一条命令说起showmount -e 究竟把什么端上了桌很多运维同学第一次看到扫描报告里那行目标主机 showmount -e 信息泄露CVE-1999-0554心里其实是懵的。因为这条命令平时自己也在用查查看服务器导出了哪些目录挺方便的一个工具怎么就成了漏洞。要理解这个问题得先站到攻击者的视角去跑一遍。在一台能连通目标主机的机器上敲下showmount -e 10.0.0.20如果对方 NFS 服务配得比较随意终端会直接吐出一张表导出路径、允许访问的客户端网段全都在上面。比如/data 10.0.0.0/24、/home *(rw)这种。对防守方来说这几个字其实泄露了不少东西——服务器上挂了哪些数据盘、业务目录叫什么名字、权限范围开到了多大甚至连内网网段划分都能顺出来。这个问题的危险不在于它能直接拿到文件而在于它是后续攻击的情报入口。知道了/backup、/dbdata、/www这些目录名攻击者就能有针对性地去尝试挂载、碰撞权限、寻找弱配置知道了允许网段是10.0.0.0/24就能判断自己所在的机器是不是在信任范围内。信息泄露类漏洞从来不是单打独斗它是踩点阶段的关键一环。CVE-1999-0554 这个编号本身年代非常久远属于上世纪末就登记的老问题。它描述的正是远程用户可以通过 RPC 的 mount 服务获取 NFS 导出列表。之所以二十多年后还在各种扫描器里高频出现原因很现实NFS 这种共享方式在很多内网依然被大量使用而且不少管理员装完 nfs-utils 之后随手在/etc/exports里写个*就上线了压根没考虑过暴露面的问题。老漏洞配上新环境就成了常年不消的钉子户。这篇文章面向的是真正要动手修的人负责内网服务器加固的运维、做等保整改的安全工程师、以及被扫描报告追着要闭环的同学。我会把原理讲透把修复按层次拆开把每一步为什么这么做的逻辑说清楚最后附上我自己踩过的坑和排查套路。目标是你看完之后能独立完成一台 Linux 服务器的 NFS 信息泄露闭环并且知道怎么验证、怎么防止反弹。2. 端口与协议拆解为什么改一处往往堵不住2.1 rpcbind、mountd、nfsd 三个角色的分工要修得干净先得搞清楚 NFS 这一套东西是谁在对外说话。NFS 不是单一进程单端口而是典型的 RPC远程过程调用体系最常打交道的三个组件分工很明确。rpcbind老系统叫 portmap监听 111 端口它相当于一个黄页。任何 RPC 服务启动时都要先到它这里注册我叫什么、我版本多少、我在哪个端口。客户端想找某个服务先问 111 端口拿到端口号再进行真正的连接。这个设计是历史遗留因为很多 RPC 服务的端口是动态分配的。mountd就是这次漏洞的主角。它负责处理挂载请求管理导出列表端口默认是动态的。showmount -e这条命令本质上就是向 mountd 发送一个 MOUNTPROC_DUMP 类型的 RPC 请求让它把当前的导出列表吐出来。注意这个吐出来是协议层面的设计行为不是 bug所以它才会被归类为信息泄露而不是越权执行。nfsd监听 2049 端口是真正处理文件读写请求的进程。它不直接产生这次的信息泄露但如果不做限制攻击者拿到导出列表后就能直接对它发起挂载尝试。理解了这三个角色你就能明白为什么有些修复看着改了却没用只关了 mountd攻击者照样能通过rpcinfo -p从 111 端口看到注册信息只封了 111但如果你没有固定 mountd 端口并封掉攻击者直连 mountd 照样能 dump。环环相扣得成体系地堵。2.2 showmount -e 背后的 RPC 调用链我把调用链拆细一点这样你排查的时候心里有图。客户端执行showmount -e 10.0.0.20时大致经历这么几步第一步客户端向目标 111 端口发起查询问mount 服务的 v3 版本在哪个端口。这一步用的是 rpcbind 协议。第二步rpcbind 返回 mountd 当前实际监听的端口比如 32768 这种随机大端口。第三步客户端拿着这个端口直接向 mountd 发送 MOUNTPROC_DUMP 请求。第四步mountd 读取/etc/exports以及内核里当前的导出表把结果返回给客户端。整个链条里真正的信息是从 mountd 出来的但入口是 rpcbind。所以有一条经验如果目标 111 端口不通普通的 showmount 也就无从下手了。但要注意攻击者完全可以用rpcinfo或者直接扫描大端口范围的方式绕过 111只要他拿到 mountd 的端口DUMP 请求照样发得出去。这就是为什么我从来不建议只关 111 就算修完。还有一种情况值得注意有些环境下 mountd 被配置成固定端口这也是我们后面要做的加固动作之一那攻击者连猜端口的时间都省了。所以固定端口这件事要配合防火墙一起做单独做反而是帮了攻击者。2.3 为什么单纯改 exports 有时管不住泄露这是很多人最困惑的一点我在/etc/exports里明明写了只允许某几台机器为什么扫描器还是报我泄露原因在于 exports 里的客户端限制主要作用于挂载请求MNT 过程和读写访问对 DUMP 过程的返回内容不同版本的 mountd 实现行为不完全一致。在不少 Linux 发行版的实现里showmount -e依然会把整个导出列表列出来哪怕发起查询的机器并不在允许范围内。也就是说导出列表的可见性和访问权限是两套逻辑。这就解释了一个常见现象扫描报告说泄露管理员在服务器上showmount -e localhost一看确实有几个目录但在 exports 里其实已经限制了 IP。加了限制也没用因为泄露的是列表本身。所以正确的认知是exports 的访问控制管的是能不能挂不是能不能看。要管住看得靠网络层的访问控制把 111 和 mountd 端口对非授权来源直接掐掉。这个认知是整套修复方案的地基后面所有动作都建立在这上面。注意不要以为把 exports 里的*改成具体 IP 就万事大吉这只解决了一半问题扫描器大概率还会继续报。真正闭环需要网络层配合。3. 修复前后的检测与风险确认3.1 靠得住的自查命令清单动手之前先摸清现状别上来就改。这几条命令我每次都会跑一遍能快速判断暴露程度。从外部机器非授权网段执行showmount -e 目标IP。如果能返回列表说明信息泄露实锤。在目标机上执行rpcinfo -p 目标IP或者rpcinfo -p localhost看看 111 端口对外能暴露哪些 RPC 程序。输出里会列出 program、vers、proto、port 四列mountd 和 nfs 会赫然在列。这条命令的价值在于它模拟了攻击者踩点的第一步。在目标机上看cat /etc/exports重点关注有没有*、有没有/24这种大网段、有没有no_root_squash这种高危参数。再看systemctl status nfs-server rpcbind和ss -tulnp | grep -E 111|2049确认服务状态和实际监听地址。有些机器监听的是0.0.0.0有些做了绑定差别很大。最后exportfs -v能列出当前内核实际生效的导出表比看文件更准因为改了文件没 reload 是不生效的。3.2 判断是真暴露还是扫描器误报扫描器不是永远对的我遇到过好几次假阳性。判断方法很简单从一台确实不在授权网段的机器上再跑一次 showmount如果返回空、超时或者RPC: Program not registered而扫描器还是报那可能就是扫描器从授权网段发起的或者它判定依据是 111 端口可达而非真的拿到了列表。还有一种情况是扫描器看到 111 端口开着就直接判定存在 NFS 信息泄露风险并不真的去 dump。遇到这种你得看报告的详细描述很多产品会把NFS Exported Shares List和portmapper 可访问分开报。理解扫描器的判定逻辑才能在闭环时给出有说服力的证据——要么真修了要么拿授权网段的测试结果作为反证。不管真假我的习惯是只要 111 端口对非授权来源可达就按真漏洞处理。因为允许无关来源访问 rpcbind 本身就是不必要的暴露面。3.3 先理清谁在依赖这个 NFS加固最怕的不是改不动是改完把业务搞挂。所以在动手前必须搞清楚这台机器上的 NFS 谁在用。方法有几个。看cat /etc/exports的导出目录对应到业务看last或者审计日志里有没有挂载记录更直接的是看当前连接ss -tnp | grep 2049或者看cat /proc/fs/nfsd/clients/*/info内核 4.16 支持能看到当前挂载的客户端列表。还有一个容易被忽略的点有些机器自己就是 NFS 客户端挂载了别处的存储。这时候mount | grep nfs能看到本机挂载情况处理时要注意别把客户端相关的服务也停了。服务端和客户端是两套东西nfs-server是服务端nfs-client或者nfs是客户端。把依赖关系画清楚你才能决定是彻底停用还是精确放行。这一步花的时间会在后面省下大麻烦。4. 分层修复方案从服务面到网络面一步步收紧4.1 第一层能不用就不用先做服务最小化安全加固的第一原则永远是减少暴露面能用不到的服务就别开。如果这台机器根本不需要对外提供 NFS 共享那最干脆的做法就是停掉整条链路。停服务之前先确认客户端依赖已经解除然后执行systemctl stop nfs-server systemctl stop rpcbind systemctl disable nfs-server systemctl disable rpcbind在 CentOS/RHEL 系上服务名可能是nfs、nfs-server、rpcbind这几个用systemctl list-unit-files | grep -E nfs|rpc确认一下。Debian/Ubuntu 上是nfs-kernel-server和rpcbind。停掉之后别忘了检查有没有残留的 RPC 服务rpcinfo -p localhost应该返回空或者连接拒绝。有些系统上rpcbind.socket是 socket 激活的光 disable service 不够得一并处理systemctl stop rpcbind.socket systemctl disable rpcbind.socket如果业务暂时不能停那就往下走后面几层。但我要强调停用永远是最省事、最彻底的方案很多被反复报的机器其实那些 NFS 共享早就没人用了只是没人敢停。花点时间确认往往能一劳永逸。4.2 第二层exports 精细化把口子收到最小如果 NFS 确实要用那/etc/exports就得认真写。核心原则是按需授权、最小权限、显式声明。一条典型的加固型配置长这样/data/share 10.0.0.15(rw,sync,root_squash,no_subtree_check) /data/share 10.0.0.16(ro,sync,root_squash,no_subtree_check)这里每个参数都有讲究。rw/ro决定读写能只读就别给写。sync保证写操作同步落盘避免异步带来的数据风险。root_squash是关键它把客户端的 root 用户映射成匿名用户防止客户端 root 在共享目录里为所欲为——这是 NFS 历史上有名的提权路径默认就该开着。no_subtree_check是为了减少文件句柄失效问题性能更稳。要避免的写法*通配所有来源、/24大网段一把梭、no_root_squash图省事。这些在等保测评和漏洞扫描里都是扣分项。改完之后必须重新加载exportfs -ra exportfs -v-r是重新导出-a是全部。然后再用showmount -e从授权和非授权机器分别验证。再提醒一次exports 主要管访问权限对信息泄露的可见性控制有限所以这一层是基础但不够得配合下一层。提示/etc/exports支持seckrb5这类 Kerberos 认证参数如果环境里有统一认证体系加上它能大幅提升安全性但配置复杂度也上去了按团队能力取舍。4.3 第三层防火墙与网络访问控制才是治本前面说过管住看得靠网络层。这一层是整个修复的核心思路是把 111 端口和 mountd、nfsd 的端口只对真正需要的来源开放。先要固定 mountd 的端口否则你没法写防火墙规则。nfs-utils 2.3.0 以上版本用/etc/nfs.conf[mountd] port20048老版本改/etc/sysconfig/nfsMOUNTD_PORT20048然后固定 nfsd 端口默认就是 2049一般不用动重启相关服务。接着写防火墙规则。以 iptables 为例假设授权网段是10.0.0.0/24# 允许授权网段访问 rpcbind iptables -A INPUT -p tcp --dport 111 -s 10.0.0.0/24 -j ACCEPT iptables -A INPUT -p udp --dport 111 -s 10.0.0.0/24 -j ACCEPT # 允许授权网段访问 mountd 和 nfsd iptables -A INPUT -p tcp --dport 20048 -s 10.0.0.0/24 -j ACCEPT iptables -A INPUT -p tcp --dport 2049 -s 10.0.0.0/24 -j ACCEPT # 其余来源全部丢弃 iptables -A INPUT -p tcp --dport 111 -j DROP iptables -A INPUT -p udp --dport 111 -j DROP iptables -A INPUT -p tcp --dport 20048 -j DROP iptables -A INPUT -p tcp --dport 2049 -j DROP注意 111 是 TCP/UDP 都有的别只封 TCP。如果用的是 firewalld可以用 rich rule 或者 zone 的方式思路一致firewall-cmd --permanent --add-rich-rulerule familyipv4 source address10.0.0.0/24 port port111 protocoltcp accept firewall-cmd --permanent --add-rich-rulerule familyipv4 port port111 protocoltcp drop firewall-cmd --reload这里有个细节防火墙规则要放在最前面检查或者确认已有规则没有提前放行。iptables 是按顺序匹配的如果前面有一条-A INPUT -j ACCEPT你后面写的 DROP 就是摆设。规则顺序是我见过的最高频翻车点之一。4.4 第四层rpcbind 自身与挂载权限的收尾加固防火墙是外围服务自身也要收一收。rpcbind 支持只监听指定地址减少暴露。编辑/etc/sysconfig/rpcbind或者 systemd 的 drop-in加上-h 10.0.0.20 -l这类参数让它只绑定内网地址不监听0.0.0.0。这样即使防火墙有疏漏公网侧也够不着。挂载权限上还有几个值得做的动作。一是在 exports 里尽量用只读ro二是避免导出整个根目录或者宽泛路径只导出业务真正需要的子目录。三是考虑配合all_squash加上匿名用户和匿名组映射把客户端身份进一步弱化。如果你的系统还支持 tcp_wrappers可以在/etc/hosts.deny里加上rpcbind: ALL mountd: ALL然后在/etc/hosts.allow里放行授权网段。不过现在很多新发行版已经不再默认编译 tcp_wrappers 支持了用之前先确认别写了不生效还以为修好了。我一般把它当作补充手段主力还是防火墙。另外从生命周期角度看如果这台机器只是临时共享数据记得在项目结束后及时下线 NFS 服务别让它变成无人认领的僵尸共享。4.5 第五层修复验证与效果回归改完不复验等于没改。我的验证清单是这样的从一台非授权机器执行showmount -e 目标IP期望结果是超时、连接拒绝或者空列表。从授权机器执行同样的命令期望能正常列出业务挂载不受影响。rpcinfo -p 目标IP从非授权侧执行期望超时或拒绝。nmap -p 111,2049,20048 目标IP从非授权侧扫期望是 filtered 或 closed。业务侧做一次读写测试确认共享目录仍可正常访问。这一步别省我就见过封完规则把授权网段也误伤的。最后把结果整理成闭环证据修复前截图、修复后截图、授权侧验证截图三张图配上命令和结果说明提交给扫描方复核。5. 常见问题与排查实战记录5.1 封完之后业务断了怎么快速定位这是最让人心跳加速的场景。第一反应是回滚但要回滚得有依据。先在服务器上iptables -L -n --line-numbers看规则顺序确认是不是误伤了授权网段——最常见的就是网段写错、掩码写错或者授权客户端实际来自另一个网段。然后用tcpdump -i any -n host 客户端IP and port 111抓一下看客户端的包有没有到达、被哪条规则处理。如果包到了但没回基本就是被 DROP 了。再看ss -tnp | grep 2049有没有客户端处于 SYN 状态能判断是连接建立阶段的问题还是数据阶段的问题。定位之后临时iptables -I INPUT 1 ...ACCEPT插一条放行规则救急再回头修正永久配置。记住-I是插入到顶部-A是追加到尾部救急用-I。5.2 showmount 还能查到问题出在哪修完还在报通常就那么几种原因。我把排查过的情形整理成表方便对照。现象可能原因排查命令处理方式非授权侧仍能 dump 列表防火墙规则顺序被前面的 ACCEPT 放行iptables -L -n --line-numbers调整规则顺序或加更高优先级 DROP111 封了但还能连mountd 端口未固定且未封rpcinfo -p、ss -tulnp固定端口并加规则改了 exports 没生效未执行 exportfs -raexportfs -v重新加载导出表服务停了 rpcinfo 还有响应rpcbind.socket 未停systemctl status rpcbind.socket停用 socket 单元扫描器仍报判定依据是 111 可达非真实 dump查看报告详情关闭 111 或提交复测证据5.3 排查速查表与操作禁忌再补几条我踩过的坑。一是改配置前先备份cp /etc/exports /etc/exports.bak.$(date %F)改坏了能秒回。二是别在生产机上直接敲iptables -F清空规则可能把 SSH 一起封掉你会直接失联这我吃过亏。三是NFSv3 和 NFSv4 对 rpcbind 的依赖不一样v4 基本只用 2049如果你能全量切到 v4111 端口的暴露面自然就小了这是从架构上解决问题的思路。四是容器环境里的 NFS 别按物理机思路处理规则可能被宿主或者 CNI 覆盖。五是变更要挑窗口期NFS 加固有一定概率影响正在运行的业务 IO别在业务高峰动刀。6. 我在这类加固里的一些体会做多了这类整改我越来越觉得showmount 这个漏洞本身技术含量不高难的是判断和取舍。它不像一个能直接 getshell 的高危漏洞那样逼着你立刻动手它是那种看起来没什么、但一直在报告里挂着的类型。很多团队的处理方式是给扫描结果打个误报标签糊弄过去其实只要花半小时把端口一封问题就彻底解决了。从更长的时间线看NFS 这类基于老 RPC 体系的共享方式本身就是上个时代的设计。如果条件允许把内网文件共享迁移到更现代的方案上比如对象存储、SMB3 加上加密和细粒度 ACL暴露面和运维成本都会降到另一个量级。我在几个项目里推过这种迁移前期改造有点痛但后续再也没被 NFS 相关的扫描项追着跑。最后分享一个小习惯把showmount -e和rpcinfo -p这两条命令加进日常巡检脚本每周对内网服务器扫一遍。因为加固最怕的不是第一次没修好而是新上线的机器又带着默认配置进来把已经堵上的口子重新打开。把检测前置比事后一遍遍整改要省心得多。这个思路同样适用于其他老牌信息泄露类问题——与其被动整改不如在部署阶段就把安全基线卡住。
返回列表