Sem Agente · Sem Instalação

Nginx Hardening: Complete Guide

Nginx Hardening: The Guide to Amplify Your Security (with everything that can go wrong if you don't) Every default Nginx configuration line you ignore is a door left ajar. This guide shows exactly what each one means in practice — and how to close it, one by one.

Nginx Hardening: The Guide to Amplify Your Security (with everything that can go wrong if you don't) Every default Nginx configuration line you ignore is a door left ajar. This guide shows exactly what each one means in practice — and how to close it, one by one. Introduction Nginx was born in 2004 with a different proposal than Apache: to be lightweight, fast, and handle thousands of simultaneous connections without breaking a sweat. In 20 years it became the most widely used web server in the world among top 1 million sites. And, just like Apache, its default configuration is designed to work anywhere — not to be secure everywhere . The good news is that Nginx has a cleaner and more centralized configuration than Apache. The bad news is that precisely because of this, when something is wrong, it's wrong on all sites at once. This guide follows the same logic as the previous post about Apache: for each item, we explain what the default configuration does , what an attacker can do with it (with real scenarios), and how to fix it with configuration ready to copy. server tokens: Nginx also shouts its version What happens by default Every Nginx response includes a Server header like this: And on error pages, an equally revealing footer appears. What this causes An attacker scans the internet with Shodan, Censys, or a script Filters for "nginx/1.24.0" — finds all CVEs for that version Filters ready-made exploits on Exploit-DB, Metasploit, GitHub If your version has an unpatched vulnerability, the attack begins in seconds Nginx-specific aggravating factor: many people run versions compiled with third-party modules (Brotli, ModSecurity, RTMP) that fall behind on updates. The fix To completely hide the header (not just the version), use the headers-more module: fastcgi param SERVER SOFTWARE: the PHP leak What happens by default When Nginx passes requests to PHP-FPM, it automatically sends a SERVER SOFTWARE variable with the Nginx version. Combined with expose php = On, it leaks both versions. What this causes The same problem as the previous item, in stereo. An attacker discovers both Nginx and PHP versions with a single request. The fix In php.ini: In Nginx's PHP block: The fastcgi hide header directive prevents headers from the upstream from being passed to the client. Always use it. Dangerous HTTP methods What happens by default Nginx accepts any HTTP method the client sends and passes it to the backend application. What this causes Poorly protected API that accepts DELETE /api/users/123 without proper authentication Node/Python application with PUT route accidentally left open Misconfigured WebDAV in another component Compliance scanners marking it as a vulnerability The fix For REST APIs that need PUT, DELETE, PATCH: Strict-Transport-Security (HSTS) What happens by default Nginx does not send HSTS. Even on HTTPS-only sites, the browser makes the first request via HTTP until it receives a redirect. What this causes SSL Stripping : an attacker on public Wi-Fi intercepts the first HTTP request, maintains an HTTP connection with the victim and HTTPS with the real server. The victim never sees the padlock, but types the password anyway. With HSTS, the browser refuses to speak HTTP with the domain after the first visit. The attack stops working. The fix CRITICAL WARNING about always: without this suffix, the header is only sent on successful responses and redirects, not on error responses . With always, it's sent on all. Always use always on security headers in Nginx. Warning about HSTS itself: once applied with a long max-age, the browser locks the domain to HTTPS. If the certificate expires, users lose access. Start with max-age=300 (5 minutes), validate everything, then increase. X-Frame-Options: clickjacking What happens by default Without this header, any site can embed yours inside an iframe. What this causes Clickjacking : an attacker creates any site (raffle, game) that loads your admin panel inside an invisible iframe, with fake buttons overlaid. The victim — logged in another tab of your system — clicks "win prize" and actually clicks "delete account" in your panel. The fix X-Content-Type-Options: MIME sniffing What happens by default When it receives a file with an ambiguous Content-Type, the browser tries to guess the real type by looking at the content (MIME sniffing). What this causes An attacker sends photo.png with HTML/JavaScript content inside. You validate only the extension. When another victim accesses it, the browser looks at the content, thinks "this is HTML" and executes it. Stored XSS without even needing to bypass a filter. The fix Referrer-Policy What happens by default When a user clicks on an external link, the browser sends the full origin URL to the destination. What this causes Suppose URLs like: Any external link (or image from another domain, or tracking pixel) causes the entire URL to leak to the destination. Tokens, IDs, sensitive data. US health systems leaked patient identifier…