
你的Nginx跑得好好的。你不知道的是,它正在主动告诉全世界:版本号是1.18.0,你服务器上有一个叫/backup的目录可以直接看,有人正用PUT方法往你服务器传文件。Nginx默认配置是为方便,不是为安全。有几个关键设置,改了能挡掉很多扫描器。
先看一个数据
某安全团队扫描了10万台公网Nginx服务器,超过65%暴露了版本号,超过40%开启了目录列表,超过80%允许不必要的HTTP方法(PUT、DELETE、TRACE)。攻击者不需要0day,只需要知道你版本号,然后去搜对应版本的漏洞。你没必要把底牌亮给所有人看。
第一项:隐藏版本号
Nginx默认在HTTP响应头里加Server: nginx/1.18.0,错误页面也会显示版本号。攻击者知道版本号,就能查这个版本有什么已知漏洞,针对性攻击。
配置方法:
nginx
server_tokens off;
放在http块里全局生效。重启Nginx后,响应头变成Server: nginx,不再显示具体版本号。只改这一个参数,就能过滤掉依赖版本号的批量扫描。
验证:
bash
curl -I http://你的域名
看Server头。
第二项:关闭目录列表
如果你有一个目录没有index.html,Nginx默认会把目录里的文件列表展示出来。这是安全隐患。
访问http://你的域名/backup/,如果看到文件列表,说明目录列表没关。攻击者直接看到你的备份文件、配置文件、敏感数据。有些目录本来就不该被访问,你却把目录里的文件全列出来。
配置方法:
在server或location块里加:
nginx
autoindex off;
Nginx默认是off。检查你的配置,有没有地方不小心开了autoindex on。如果你的确需要一个文件下载站,给那个特定目录加密码保护,或者只允许特定IP访问。
正则批量关闭:
nginx
location ~ ^/(backup|logs|config)/ {
autoindex off;
return 403;
}
backup、logs、config这些敏感目录直接返回403。
第三项:限制HTTP方法
Nginx默认允许所有HTTP方法:GET、POST、PUT、DELETE、OPTIONS、TRACE、PATCH……你的网站只需要GET和POST。PUT和DELETE不应该对公网开放。有人用PUT上传恶意文件,用DELETE删你的东西。TRACE方法可能被用于XST攻击,跨站追踪,获取cookie信息。
配置方法:
nginx
if ($request_method !~ ^(GET|POST)$) {
return 405;
}
只允许GET和POST,其他方法返回405。放在server块里。如果某些路径需要支持其他方法(如API更新需要PUT),针对那个location单独放行。
nginx
location /api/ {
limit_except GET POST PUT {
deny all;
}
}
limit_except更优雅,只限制需要限制的方法。
第四项:限制请求大小
客户端可以POST大文件,如果没限制,可能耗尽服务器内存或磁盘。
nginx
client_max_body_size 10M;
放在http、server或location里。普通网站10-20M足够,需要上传大文件的路径单独设大一点。
第五项:添加安全响应头
几个安全头能有效防范常见Web攻击:
nginx
add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always;
- X-Frame-Options:防止网站被嵌入iframe,防点击劫持
- X-Content-Type-Options:禁止浏览器嗅探MIME类型
- X-XSS-Protection:开启浏览器内置XSS防护
HTTPS网站建议加:
nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
强制浏览器用HTTPS访问,有效期1年。
第六项:限制IP访问
敏感路径只允许特定IP访问:
nginx
location /admin/ {
allow 192.168.1.100;
allow 10.0.0.0/8;
deny all;
}
公司办公网IP放进去,其他IP一律拒绝。外部用户访问/admin/会看到403。
第七项:禁用非必要模块
Nginx编译时可以禁用不需要的模块。如果你是自己编译的,去掉--with-http_dav_module(支持PUT/DELETE等WebDAV方法)、--with-http_autoindex_module(目录列表)等。大部分用户用包管理器安装,没法重编译,上面的配置改好就行。
完整安全配置示例
把上面的配置整合到/etc/nginx/nginx.conf:
nginx
http {
# 隐藏版本号
server_tokens off;
# 限制请求大小
client_max_body_size 10M;
# 默认关闭目录列表
autoindex off;
# 全局安全响应头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# 其他配置...
}
server {
listen 80;
# 只允许GET和POST
if ($request_method !~ ^(GET|POST)$) {
return 405;
}
# 敏感目录禁止访问
location ~ ^/(backup|logs|config)/ {
return 403;
}
# 管理后台限制IP
location /admin/ {
allow 你的IP;
deny all;
}
}
改完后测试语法:
bash
nginx -t
没问题就重载:
bash
systemctl reload nginx
真实案例
一个朋友的Nginx服务器,没有限制请求方法。攻击者利用某个上传接口的漏洞,用PUT方法上传了webshell。事后分析,如果限制了PUT方法,攻击链第一步就被卡住了。
另一个案例:目录列表没关,/backup目录里的数据库备份被爬虫抓走,几万条用户数据泄露。
都不是0day,都是配置问题。
最后一句
Nginx默认配置不是为安全设计的。隐藏版本号、关目录列表、限制HTTP方法、加安全头,几行配置的事。改完之后,批量扫描器会忽略你,因为你看起来不像默认配置的软柿子。
去检查你的Nginx配置,该加的都加上。这几种攻击方式,攻击者天天在试。你不关门,总有一天会有人进来。




