服务器状态页面(如Apache的server-status、Nginx的stub_status)默认开启后,会直接暴露你的服务器版本号、操作系统类型、运行模块、连接数、请求处理详情等敏感信息。攻击者只需要访问一个URL就能拿到这些情报,然后针对性地查找已知漏洞进行攻击。解决方法很简单:在服务器配置文件中明确禁用这些状态页面,或者限制只允许本地IP访问,同时配合防火墙规则做二次防护。这不是什么高深操作,但90%的中小型网站都没做,等于把家门钥匙挂在了门上。
一、服务器状态页面到底暴露了什么信息
很多站长觉得状态页面只是个监控工具,打开看看没什么大不了。但你要知道,这个页面输出的信息对攻击者来说就是一份"攻击指南"。具体来说,它会暴露以下几类关键信息:
第一,服务器软件版本。比如Apache 2.4.49、Nginx 1.18.0,攻击者拿到版本号后直接去漏洞数据库比对,如果你的版本存在已知CVE漏洞,攻击成本几乎为零。第二,操作系统和架构信息。Linux发行版、内核版本、32位还是64位,这些都能帮助攻击者筛选 exploits。第三,当前连接状态和请求详情。包括每个连接的来源IP、处理的URL、运行时间、线程ID等,等于把服务器的实时运行状态全部摊开给外人看。第四,已加载的模块列表。比如mod_ssl、mod_php、mod_proxy等,攻击者可以据此判断你的服务器功能配置,找到可利用的攻击面。
二、为什么默认配置会开启这些页面
这其实是个历史遗留问题。Apache和Nginx在默认安装时,为了方便管理员本地调试,会把状态页面的配置写进示例文件或者默认配置中。比如Apache的httpd.conf里经常能看到这段代码:
<Location "/server-status">
SetHandler server-status
Require ip 127.0.0.1
</Location>
看起来它限制了只允许本地访问,但问题在于很多人在部署时会把Require那行删掉或者改成Require all granted,甚至有些云主机的镜像默认就把这个限制去掉了。Nginx的情况类似,stub_status模块如果被编译进去并且配置了location块,就可能对外可访问。所以不要以为"我没主动开"就安全,你得主动去检查、主动去关。
三、Apache服务器禁用状态页面的具体操作
针对Apache,有三种方式可以彻底解决这个问题。第一种是直接注释掉或删除相关配置。打开你的主配置文件httpd.conf或者conf.d目录下的相关文件,找到包含server-status的Location块,直接删掉或者用#注释:
# <Location "/server-status"> # SetHandler server-status # Require ip 127.0.0.1 # </Location>
第二种是在虚拟主机配置中显式拒绝访问。如果你不确定哪个文件里有这个配置,可以在每个VirtualHost块里加一段明确的拒绝规则:
<Location "/server-status">
Require all denied
</Location>
第三种是从模块层面禁用。如果你确定不需要mod_status模块,可以直接在加载模块的地方把它注释掉:
# LoadModule status_module modules/mod_status.so
改完之后记得重启Apache服务:systemctl restart httpd 或者 systemctl restart apache2,然后用curl测试一下状态页面是否还能访问。
四、Nginx服务器禁用状态页面的具体操作
Nginx的处理逻辑类似。首先检查你的nginx.conf或者conf.d目录下的配置文件,找到类似这样的location块:
location /stub_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
如果你看到这段配置,要么直接删掉整个location块,要么把deny all改成更严格的限制。但更彻底的做法是,如果你的Nginx编译时包含了http_stub_status_module,但你从来不用它,可以在编译参数里去掉这个模块,从源头解决问题。对于已经运行的服务,直接删除或注释掉location块后执行nginx -s reload重新加载配置即可。
另外要特别注意一种情况:有些运维为了监控方便,会把stub_status的访问限制改成allow all或者allow 0.0.0.0/0,这等于完全开放。如果你发现自己的配置里有这种写法,立刻改回来。
五、用防火墙做第二道防线
光改服务器配置还不够,万一配置文件被误改或者有其他地方漏了,防火墙可以兜底。用iptables或者firewalld直接在网络层封掉对状态页面路径的访问:
# iptables方式 iptables -A INPUT -p tcp --dport 80 -m string --string "GET /server-status" --algo bm -j DROP iptables -A INPUT -p tcp --dport 80 -m string --string "GET /stub_status" --algo bm -j DROP # firewalld方式 firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="0.0.0.0/0" port protocol="tcp" port="80" reject'
当然,更推荐的做法是直接在防火墙层面限制只有你的监控服务器IP才能访问80或443端口的特定路径,而不是粗暴地封掉整个端口。这样既不影响正常业务,又能确保状态页面不会被外部扫描到。
六、其他容易被忽略的信息泄露点
状态页面只是其中一个点,实际上还有很多类似的"信息泄露口"需要一并处理。比如:
服务器签名信息。Apache默认会在HTTP响应头里加上Server: Apache/2.4.49 (Ubuntu)这样的字段,Nginx也会暴露版本。解决方法是在配置里加上ServerTokens Prod和ServerSignature Off:
# Apache ServerTokens Prod ServerSignature Off # Nginx server_tokens off;
错误页面信息。很多网站的404、500错误页面会直接输出调试信息、文件路径、代码片段。生产环境一定要关闭display_errors,并且配置自定义错误页面,不要用默认的。
目录浏览功能。如果你的网站根目录没有index文件,Apache的mod_autoindex会自动生成文件列表页面,把所有文件名暴露出去。确保Options -Indexes在配置中生效。
PHP信息泄露。phpinfo()函数如果被意外调用或者有测试文件遗留,会暴露大量系统信息。定期扫描网站目录,删除所有测试文件和调试脚本。
七、如何验证你的服务器是否还在泄露信息
做完以上所有操作后,你需要验证效果。方法很简单,用命令行工具模拟外部访问:
# 检查Apache状态页面 curl -I http://你的域名/server-status # 检查Nginx状态页面 curl -I http://你的域名/stub_status # 检查服务器签名 curl -I http://你的域名/ | grep -i server # 检查目录浏览 curl http://你的域名/某个没有index文件的目录/
如果返回403 Forbidden或者404 Not Found,说明你的防护生效了。如果还能看到状态信息,回去检查配置文件是否有遗漏,特别注意是否有多个配置文件同时定义了相同的location,后面的配置可能会覆盖前面的。
八、从安全策略层面建立长效机制
禁用状态页面不是一次性的工作,而是需要纳入日常运维流程。建议做到以下几点:第一,把服务器 hardening(加固)做成标准化文档,新服务器上线前必须按清单逐项检查。第二,定期用漏洞扫描工具对自己的网站做渗透测试,很多开源工具都能自动检测信息泄露类问题。第三,关注你所使用的服务器软件的安全公告,一旦发现新版本修复了已知漏洞,及时升级,同时重新检查配置有没有被更新覆盖。第四,日志监控要到位,如果发现有人频繁访问server-status、stub_status这些路径,说明你的服务器已经被扫描到了,需要立即排查并加固。
说到底,服务器安全不是靠某一个功能或者某一次操作就能搞定的,它是一个持续的、系统化的工程。禁用状态页面只是其中一个最基础、最容易被忽视、但又最容易被利用的环节。把这个口子堵上,你的服务器安全等级至少能提升一个档次。别等到被攻击了才想起来,那时候损失的可不只是数据,还有用户信任和业务声誉。
