关于修复Nginx服务器Proxy Disclosure(代理披露)漏洞的技术咨询
Hey there! Let's break down how to fix this proxy disclosure issue properly, building on what you've already done with your Nginx config.
首先,确认你禁用请求方法的配置是否生效
Right now, you've added the request method block in a standalone server section under the http block. The problem here is that this won't apply to your actual business servers (since you're including sites from /etc/nginx/sites-enabled/*). You need to move this rule into your actual site server blocks (the ones handling your portal and API) for it to work as intended.
Alternatively, you can set up a global rule using map for cleaner configuration:
http { # Add this at the top of your http block map $request_method $block_method { default 0; PATCH 1; TRACE 1; OPTIONS 1; } # Then in each of your site server blocks: server { listen 80; server_name your-domain.com; if ($block_method) { return 405; } # Rest of your server config (locations, proxy_pass, etc.) } }
To verify it's working, run this curl command against your domain:
curl -X TRACE your-domain.com
If you get a 405 response, the rule is active.
Hiding Server and X-Powered-By Response Headers
This is the part you were asking about, let's cover both headers:
1. Server Header
You already added server_tokens off; which hides Nginx's version number, but it still returns Server: nginx. To fully customize or remove this:
- First, install the
nginx-extraspackage (on Debian/Ubuntu) — this includes theheaders_moremodule needed to modify the Server header. - Then add this line in your
httpblock or specific server blocks:
If you don't want to install extra packages, note that vanilla Nginx can't fully remove the Server header without compiling custom modules, so themore_set_headers 'Server: Custom-Web-Server'; # Replace with a generic name, or use an empty string if neededheaders_moreapproach is the most straightforward.
2. X-Powered-By Header
This header usually comes from your backend apps (like the Flask services running on 5000/5002). You need to handle it in two places:
- Backend App: Update your Flask code to strip this header. Add this after initializing your app:
@app.after_request def remove_x_powered_by(response): response.headers.pop('X-Powered-By', None) return response - Nginx Proxy Layer: Even if your backend fixes it, add this to your proxy location blocks to act as a safety net:
location / { proxy_pass http://portal; proxy_hide_header X-Powered-By; # This removes the header if the backend sends it # Other proxy configs }
Bonus: Add Custom Error Pages
As per OWASP's suggestion, replace default Nginx error pages with custom ones to avoid leaking server details. Add this to your server blocks:
error_page 404 /custom-404.html; error_page 405 /custom-405.html; # Serve custom error pages internally location = /custom-404.html { root /path/to/your/static/assets; # Update this to your static files directory internal; } location = /custom-405.html { root /path/to/your/static/assets; internal; }
Quick Note on OPTIONS Method
If your app uses CORS (cross-origin requests from frontend), don't block the OPTIONS method entirely. Instead, configure proper CORS rules in Nginx to handle preflight requests safely, rather than returning 405.
After making these changes, reload Nginx with sudo systemctl reload nginx and re-run your OWASP ZAP scan to verify the alerts are resolved.
备注:内容来源于stack exchange,提问作者asap_coder

