Nginx安全漏洞修复指南

前言

安全扫描经常发现服务器存在信息泄露和安全头缺失漏洞。

这些漏洞会为攻击者提供关键信息增加系统被攻击的风险。

本文针对每个问题提供快速修复方案直接给出解决方法。

Nginx服务版本信息泄露

问题描述

检测到Nginx服务运行并暴露版本号。

响应头显示Server: nginx/1.18.0

解决方法

1
cd /usr/local/nginx/conf

修改根配置

1
vi nginx.conf

nginx.confhttp块中添加。

1
2
3
http {
server_tokens off;
}

响应头变为Server: nginx

完全隐藏需修改源码src/core/nginx.h重新编译。

HTTP协议版本信息泄漏

问题描述

泄漏HTTP协议版本信息扫描器可获取服务器详情。

解决方法

关闭server_tokens并隐藏后端敏感头。

1
2
3
4
5
server {
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
proxy_hide_header X-AspNet-Version;
}

WWW服务信息暴露

问题描述

通过HTTP和HTTPS可获取服务详细信息。

解决方法

server块中隐藏敏感响应头。

1
2
3
4
5
server {
proxy_hide_header X-Powered-By;
proxy_hide_header X-Generator;
proxy_hide_header Server;
}

404错误页面配置不当

问题描述

没有正确返回404错误页面。

解决方法

配置自定义404页面。

1
2
3
4
5
6
7
server {
error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
internal;
}
}

使用try_files确保正确返回状态码。

1
2
3
location / {
try_files $uri $uri/ =404;
}

X-Permitted-Cross-Domain-Policies 缺失

问题描述

缺少跨域策略控制头。

解决方法

1
add_header X-Permitted-Cross-Domain-Policies "none" always;

Cross-Origin-Embedder-Policy 缺失

问题描述

缺少跨域资源加载控制头。

解决方法

1
add_header Cross-Origin-Embedder-Policy "require-corp" always;

Referrer-Policy 缺失

问题描述

缺少Referer控制头可能导致信息泄露。

解决方法

1
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

Strict-Transport-Security 缺失

问题描述

缺少HSTS头可能导致降级攻击。

解决方法

1
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

X-Frame-Options 缺失

问题描述

缺少该头可能导致点击劫持攻击。

解决方法

1
add_header X-Frame-Options "SAMEORIGIN" always;

X-Download-Options 缺失

问题描述

IE浏览器可能将下载文件当作页面执行。

解决方法

1
add_header X-Download-Options "noopen" always;

Access-Control-Allow-Credentials 缺失

问题描述

跨域请求缺少凭证控制头。

解决方法

1
add_header Access-Control-Allow-Credentials "true" always;

Access-Control-Max-Age 缺失

问题描述

缺少该头导致每次跨域请求都发送预检请求。

解决方法

1
add_header Access-Control-Max-Age "3600" always;

Clear-Site-Data 缺失

问题描述

登出时无法清除浏览器本地数据。

解决方法

全局添加会每次响应都清理缓存和Cookie一般不建议。

更常见做法是在登出接口或特定路径上返回该头。

仅对路径以/login结尾的地址添加该头时使用正则location匹配。

location匹配的是去掉查询串的路径例如/user/login?redirect=/仍按/user/login匹配。

下面示例在加头的同时走反代请把proxy_pass与头字段改成与你location /一致。

纯静态站点可在此块内改用roottry_files不要与proxy_pass混在同一location里。

1
2
3
4
5
6
7
8
location ~* /login$ {
add_header Clear-Site-Data "cache, cookies, storage" always;

proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

若还需要匹配末尾带斜杠的/login/可把正则改为/login/?$

~*表示路径大小写不敏感。

若仅需在全局某类响应上加头可写。

1
add_header Clear-Site-Data "cache, cookies, storage" always;

Cross-Origin-Opener-Policy 缺失

问题描述

缺少该头可能导致跨窗口攻击。

解决方法

1
add_header Cross-Origin-Opener-Policy "same-origin" always;

Permission-Policy 缺失

问题描述

缺少该头可能导致页面滥用浏览器API。

解决方法

1
add_header Permission-Policy "camera=(), microphone=(), geolocation=()" always;

XSS-Protection Header 缺失

问题描述

缺少XSS防护头。

解决方法

1
add_header X-XSS-Protection "1; mode=block" always;

Access-Control-Allow-Methods 缺失

问题描述

跨域请求缺少允许的方法列表。

解决方法

1
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;

Cross-Origin-Resource-Policy 缺失

问题描述

资源可能被恶意网站跨域加载。

解决方法

1
add_header Cross-Origin-Resource-Policy "same-origin" always;

Access-Control-Allow-Headers 缺失

问题描述

跨域请求缺少允许的请求头列表。

解决方法

1
add_header Access-Control-Allow-Headers "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization" always;

X-Content-Type-Options 缺失

问题描述

浏览器可能错误解析MIME类型。

解决方法

1
add_header X-Content-Type-Options "nosniff" always;

Access-Control-Allow-Origin 缺失

问题描述

跨域请求缺少允许的来源头。

解决方法

允许所有来源。

1
add_header Access-Control-Allow-Origin "*" always;

限制指定来源。

1
add_header Access-Control-Allow-Origin "https://psvmc.cn" always;

Access-Control-Expose-Headers 缺失

问题描述

前端无法读取自定义响应头。

解决方法

1
add_header Access-Control-Expose-Headers "Authorization, X-Total-Count" always;

Content-Security-Policy 缺失

问题描述

缺少CSP头无法限制资源加载来源。

解决方法

基础配置。

1
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'self';" always;

完整安全配置

Nginx版本升级

https://www.psvmc.cn/article/2026-04-08-arm-server-nginx-update.html

Nginx 1.22.0漏扫发现很多漏洞,这里考虑升级后的配置兼容性建议升级到1.26.3

这个版本经过了充分测试,适合生产环境,修复了 1.22 的所有已知高危漏洞。

全局配置

全局配置在nginx.confhttp块中添加。

1
2
3
4
5
6
7
http {
# 不影响业务 推荐添加
server_tokens off;

# 影响上传文件大小 默认10m 大文件上传需调大
# client_max_body_size 100m;
}

阻拦IP访问

default_server_blockip.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 拦截 HTTP 请求
server {
listen 80 default_server;
server_name _;
return 444;
}

# 如果你有 HTTPS (SSL) 服务,也需要拦截 443 端口的 IP 访问
server {
listen 443 ssl default_server;
server_name _;

# 必须配置证书,否则浏览器会报证书错误而不是直接拒绝
# 建议生成一个自签名证书用于此处,避免暴露真实业务证书
ssl_certificate /etc/nginx/cert/zmeduyun.cn.pem;
ssl_certificate_key /etc/nginx/cert/zmeduyun.cn.key;

return 444;
}

项目配置

下面按两种常见部署方式分别给出完整server示例。

SSL与安全响应头部分两种场景可共用。

rooterror_page路径请按实际修改。

不要在同一location里同时写try_filesproxy_pass除非你很清楚匹配顺序。

示例中注释含义如下。

【不影响业务】对正常访问与功能影响可忽略。

【一般不影响】多数项目无感个别场景需留意说明。

【可能影响】部署后建议针对性联调或压测。

【高影响需测】易与第三方资源或跨域逻辑冲突上线前必测。

Web容器

静态站点或本机root直出前端无proxy_pass时适用。

无反代时proxy_hide_header不会生效可省略。

下面示例为典型前端部署根目录加try_files回退到index.html

路径以/login结尾时在响应中加Clear-Site-Data逻辑与location /一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
server {
# 【不影响业务】监听端口按实际修改
listen 80;
listen 443 ssl;
server_name psvmc.cn;

# 【可能影响】证书路径或链错误会导致 HTTPS 无法访问
ssl_certificate /etc/nginx/cert/psvmc.cn.pem;
ssl_certificate_key /etc/nginx/cert/psvmc.cn.key;
# 【一般不影响】仅 TLS1.2/1.3 极老旧客户端可能无法握手
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:!aNULL:!MD5:!RC4:!3DES:!DES';
ssl_prefer_server_ciphers on;

# 【不影响业务】仅隐藏版本号
server_tokens 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;
add_header X-Download-Options "noopen" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permission-Policy "camera=(), microphone=(), geolocation=()" always;
# 【可能影响】需被外站 iframe 嵌入或用到跨窗口通信时要测
add_header Cross-Origin-Opener-Policy "same-origin" always;
# 【可能影响】跨域图片脚本 worker 未带 CORP 时可能加载失败
add_header Cross-Origin-Embedder-Policy "require-corp" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;

# 【可能影响】证书异常时浏览器仍强制走 HTTPS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 【高影响需测】外链 CDN 统计内联脚本等需放宽白名单
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';" always;

# 【业务核心】路径错误直接导致站点打不开
root /data/web_front/psvmc;
index index.html;

# 【可能影响】404.html 必须添加404.html
error_page 404 /404.html;
location = /404.html {
root /etc/nginx/html;
internal;
}

location / {
try_files $uri $uri/ /index.html;
}

# 【一般不影响】禁止访问以点开头的路径如 .git
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}

纯多页静态站可把try_files改为try_files $uri $uri/ =404并与error_page配合。

注意

如果网页使用hash模式

例如https://school.psvmc.cn/#/login,是不会触发浏览器清理缓存与 Cookie的。

只能前端清除或者使用history模式。

1
2
3
4
5
# 【可能影响】每次命中该路径会触发浏览器清理缓存与 Cookie 等按需求决定是否保留
location ~* /login$ {
add_header Clear-Site-Data "cache, cookies, storage" always;
try_files $uri $uri/ /index.html;
}

接口代理

请求全部或部分转发到上游应用例如127.0.0.1:8080时适用。

此时用proxy_hide_header隐藏上游返回的敏感头。

跨域头若上游已处理则不要在本机重复添加。

路径以/login结尾时加Clear-Site-Data并与location /使用相同proxy_pass与转发头。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
server {
# 【不影响业务】监听端口按实际修改
listen 80;
listen 443 ssl;
server_name api.psvmc.cn;

# 【可能影响】证书路径或链错误会导致 HTTPS 无法访问
ssl_certificate /etc/nginx/cert/psvmc.cn.pem;
ssl_certificate_key /etc/nginx/cert/psvmc.cn.key;
# 【一般不影响】仅 TLS1.2/1.3 极老旧客户端可能无法握手
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:!aNULL:!MD5:!RC4:!3DES:!DES';
ssl_prefer_server_ciphers on;

# 【不影响业务】仅隐藏版本号
server_tokens off;

# 【一般不影响】隐藏上游返回头除非客户端或调试依赖这些头
proxy_hide_header X-Powered-By;
proxy_hide_header X-Generator;
proxy_hide_header Server;

# 【一般不影响】基础安全头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Download-Options "noopen" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permission-Policy "camera=(), microphone=(), geolocation=()" always;
# 【可能影响】纯 API 一般无页面嵌入仍建议联调移动端或特殊客户端
add_header Cross-Origin-Opener-Policy "same-origin" always;
# 【可能影响】若 API 响应需被跨域页面以特殊方式引用资源需评估
add_header Cross-Origin-Embedder-Policy "require-corp" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;

# 【可能影响】证书异常时浏览器仍强制走 HTTPS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 【高影响需测】纯 JSON API 常可删 CSP 或改为极宽松策略按扫描要求决定
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';" always;

# 【高影响】仅当需要由 Nginx 统一出 CORS 且上游未处理时再打开与上游重复会跨域失败
add_header Access-Control-Allow-Origin "*" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
add_header Access-Control-Allow-Headers "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization" always;
add_header Access-Control-Max-Age "3600" always;
add_header Access-Control-Expose-Headers "Authorization, Xh-St, Content-Disposition" always;

# 【可能影响】纯 API 可改用 JSON 错误体或去掉 error_page 按项目约定
error_page 404 /404.html;
location = /404.html {
root /etc/nginx/html;
internal;
}

# 【业务核心】
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

# 【一般不影响】禁止访问以点开头的路径
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}

验证修复效果

使用curl检查响应头。

1
curl -I http://psvmc.cn

不应包含版本号、X-Powered-ByX-Generator等敏感信息。

应包含所有安全响应头。

检查404页面。

1
curl -I http://psvmc.cn/nonexistent-page

应返回404状态码和自定义页面。

总结

修复安全漏洞的核心措施。

  1. 设置server_tokens off关闭版本显示。

  2. 反代场景使用proxy_hide_header隐藏上游敏感头纯静态Web容器无反代可省略。

  3. 配置自定义404错误页面。

  4. 添加所有缺失的安全响应头。

  5. 移除CMS特征头如Drupal的Generator。

  6. 限制敏感路径访问。

注意事项。

跨域相关头根据实际需求添加不需要可省略。

Content-Security-Policy需根据项目资源来源调整白名单。

信息隐藏只是安全加固的一部分需配合防火墙、WAF等措施。

定期更新软件版本修复已知漏洞。