Attacking NGINX
Attacking NGINX
COM
Attacking Nginx
· Aug 12, 2024 · 18 min read
Table of contents
Missing Root Location in Nginx Configuration
Explanation:
The Missing Root Location Issue:
Attack Scenario: Exploiting the Missing Root Location
Mitigating the Risk
Unsafe Path Restriction in Nginx
Explanation:
Potential Bypass Techniques
Attack Scenario: Exploiting Path Restriction Bypass
Scenario: Gaining Access to Restricted Admin Page
Mitigation Strategies
Unsafe variable use / HTTP Request Splitting
1. Unsafe Use of Variables: $uri and $document_uri
2. Regex Vulnerabilities
Safe Configuration
Example of a Safe Configuration:
Attack Scenarios and Detection Techniques
1. CRLF Injection and HTTP Request Splitting
2. Bypassing Path Restrictions Using Encoded Characters
Examples of Vulnerable Configurations
Raw Backend Response Reading
Example Scenario: Exposing Raw Backend Responses
Example uWSGI Application:
Nginx Configuration
Example Nginx Configuration:
Example Invalid HTTP Request:
Example Output for Invalid Request:
Attack Scenario
Mitigation Strategies
merge_slashes set to off
1. merge_slashes Directive
Attack Scenario:
Mitigation:
2. Malicious Response Headers
Attack Scenario:
Mitigation:
3. map Directive Default Value
Example:
Attack Scenario:
Mitigation:
4. DNS Spoofing Vulnerability
Attack Scenario:
Mitigation:
5. proxy_pass and internal Directives
Example:
Attack Scenario:
Mitigation:
Attack Scenario
proxy_set_header Upgrade & Connection
Vulnerable Configuration:
Vulnerability:
Attack Scenario:
Example of an Attack:
Mitigation:
Additional Attack Scenarios and Commands:
Resources
Show less
Nginx, a popular web server and reverse proxy, is a critical component in many web
infrastructures, making it a prime target for attacks. Common vulnerabilities in Nginx
configurations include improper handling of headers, such as Upgrade and
Connection , which can lead to h2c smuggling attacks, allowing attackers to bypass
security controls and access internal endpoints. Additionally, issues like insufficient
path restrictions, unsafe variable use, and default settings like merge_slashes can
expose the server to local file inclusion (LFI) attacks, HTTP request splitting, and
other exploitation techniques. These vulnerabilities can be exploited to gain
unauthorized access, manipulate traffic, or expose sensitive information.
To secure Nginx, it’s crucial to apply best practices in configuration. This includes
disabling or carefully managing headers that can be exploited, setting strict access
controls on sensitive endpoints, and ensuring that directives like merge_slashes are
configured appropriately to prevent URL-based attacks. Moreover, using features like
proxy_intercept_errors and proxy_hide_header can help mask backend server errors
and prevent the leakage of sensitive information. Regular audits of the Nginx
configuration, alongside keeping the software up to date, are essential steps in
maintaining a robust security posture.
server {
root /etc/nginx;
location /hello.txt {
try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1:8080/;
}
}
Explanation:
1. Root Directive: The root /etc/nginx; directive sets the base directory for all file
requests. In this case, files will be served from the /etc/nginx directory.
2. Location Directive: The location /hello.txt { ... } block defines specific
behavior for requests targeting /hello.txt . The try_files directive attempts to
serve the file if it exists, and if not, returns a 404 error. The proxy_pass directive
forwards the request to another server, here, http://127.0.0.1:8080/ .
The Missing Root Location Issue:
The issue here arises from the lack of a location / { ... } block. This omission
means that the root directive ( /etc/nginx ) applies globally, affecting all requests to
the server, including those to the root path / . As a result, any request to the root
path or other undefined locations could potentially access sensitive files within
/etc/nginx .
For example, a request to GET /nginx.conf could serve the Nginx configuration file
located at /etc/nginx/nginx.conf . This exposes sensitive server configurations, which
could include paths, credentials, and other vital details.
curl http://example.com/nginx.conf
2. Accessing Other Files: If the root directory is set to a broader location like /etc ,
attackers could access other sensitive files, such as:
COPY
curl http://example.com/passwd
This could expose the /etc/passwd file, which, while not containing password hashes,
provides a list of user accounts on the system.
COPY
curl http://example.com/shadow
1. If accessible, this would expose the /etc/shadow file, which contains password
hashes (although typically it should be protected by system permissions).
Mitigating the Risk
root /var/www/html;
server {
root /var/www/html;
location / {
try_files $uri $uri/ =404;
}
location /hello.txt {
try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1:8080/;
}
}
This ensures that requests to the root path or any undefined location are handled
securely.
3. Use Permissions and Access Controls: Ensure that sensitive files like
/etc/nginx/nginx.conf are not readable by the Nginx worker processes, or are
location = /admin {
deny all;
}
location = /admin/ {
deny all;
}
Explanation:
The second block, location = /admin/ { deny all; } , denies access to the
/admin/ directory and any content within it.
These configurations seem to cover the most straightforward access attempts to the
/admin and /admin/ paths. However, Nginx's behavior in handling URL requests
Even though the configuration appears secure, certain tricks can bypass these path
restrictions, leading to unauthorized access:
1. Trailing Slash Mismatch: Nginx handles URLs with and without trailing slashes
differently. If a developer misconfigures the paths, attackers can exploit this
behavior.
For instance, if /admin is denied but /admin. (with a trailing dot or other
characters) isn't, it might be treated as a different path:
COPY
curl http://example.com/admin.
If the server doesn’t explicitly block /admin. , it might bypass the deny all; directive
and serve the page.
URL Encoding: By encoding parts of the URL, an attacker might bypass simple
string matching:
COPY
curl http://example.com/%61dmin
If the server doesn't properly decode the URL, %61dmin might be processed as a
separate path, potentially bypassing the restriction.
Case Sensitivity: Depending on the configuration, case sensitivity might be
exploitable:
COPY
curl http://example.com/ADMIN
If Nginx is configured to treat paths case-insensitively (which is not the default but
can happen in certain setups), this could bypass the restriction.
Adding Null Bytes: In some server setups, appending a null byte ( ) might
%00
curl http://example.com/admin%00/
However, Nginx itself typically handles these correctly, but the backend application
might not.
Attack Scenario: Exploiting Path Restriction Bypass
location = /admin {
deny all;
}
location = /admin/ {
deny all;
}
If the server does not decode the path correctly before applying the deny rules,
this request might bypass the restriction.
2. Adding a Trailing Dot: The attacker tries appending a dot to the path:
curl http://example.com/admin .
This could trick the server into interpreting the path as different from /admin ,
potentially bypassing the restriction.
3. Using Case Variation: The attacker tries a different case:
curl http://example.com/ADMIN
To protect against these bypass techniques, it's important to strengthen your Nginx
configuration:
Use Regex to Cover Variations: Use regular expressions to cover different variations
of the path:
COPY
location ~* ^/admin(/|$) {
deny all;
}
This ensures that paths like /admin , /admin/ , /Admin , and others are all denied.
Normalize Paths: Ensure that URL paths are normalized (decoded, lowercased,
etc.) before applying the rules.
Use Secure URI Handling: Implement strict URI handling and filtering, ensuring
that paths are handled consistently and securely across the entire stack.
Test for Bypass Techniques: Regularly test your server configurations for
potential bypass techniques using tools like curl and other security testing tools
to identify weaknesses.
In Nginx, the $uri and $document_uri variables are often used to capture the request
URI. However, these variables automatically decode URL-encoded characters, which
can introduce vulnerabilities, especially when handling user inputs directly.
For example:
COPY
location / {
return 302 https://example.com$uri;
}
In this configuration, the $uri variable is used directly in the redirection URL. If an
attacker crafts a request like:
COPY
http://localhost/%0d%0aDetectify:%20clrf
The Nginx server will decode the %0d%0a characters to \r\n (Carriage Return and
Line Feed), potentially allowing the injection of a new header in the response:
COPY
Regex patterns used in Nginx configurations can also be vulnerable if they are not
carefully constructed. For instance:
COPY
This regex pattern does not check for spaces, which can lead to unexpected behavior
if the input contains a space or a newline character.
A safer version would be:
COPY
location ~ /docs/([^/\s])? { … $1 …
} # Not vulnerable (checks for spaces)
Alternatively:
COPY
Safe Configuration
To mitigate these risks, you should avoid using $uri and $document_uri directly in
configurations where user input could be present. Instead, use $request_uri , which
preserves the original, unmodified request, including any URL-encoded characters.
Example of a Safe Configuration:
COPY
location / {
return 302 https://example.com$request_uri;
}
In this configuration, $request_uri preserves the URL encoding, preventing the server
from accidentally interpreting characters that could lead to HTTP response splitting.
Attack Scenarios and Detection Techniques
curl "http://localhost/%0d%0aX-Injected-Header:%20Test"
If the server is vulnerable, the response will include the injected header:
COPY
curl -I "https://example.com/%20X" #
Should return any HTTP code if vulnerable
curl -I "https://example.com/%20H" # Should return a 400 Bad Request
If the first request succeeds and the second returns an error, the server is likely
vulnerable.
2. Bypassing Path Restrictions Using Encoded Characters
curl "http://localhost/lite/api/%0d%0aX-Injected-Header:%20Test"
If the Nginx server uses $uri in its proxy_pass directive, the request might be passed
to the backend without proper sanitization, leading to header injection.
Detection Techniques: Test paths with encoded spaces and special characters:
COPY
curl -I "http://company.tld/%20HTTP/1.1%0D%0AXXXX:%20x"
curl -I "http://company.tld/%20HTTP/1.1%0D%0AHost:%20x"
The first request might succeed if the server is vulnerable, while the second
should cause a 400 Bad Request error.
Examples of Vulnerable Configurations
Vulnerable because $uri is directly passed to the backend, which could lead to CRLF
injection.
Rewrite with $uri:
COPY
location ~ ^/dna/payment {
rewrite ^/dna/([^/]+) /registered/main.pl?
cmd=unifiedPayment&context=$1&native_uri=$uri break;
proxy_pass http://$back;
}
location /s3/ {
proxy_pass https://company-bucket.s3.amazonaws.com$uri;
}
COPY
This application, when encountering an error, sends an HTTP 500 response along
with a custom header Secret-Header containing sensitive information.
Nginx Configuration
Nginx can be configured to handle such situations by intercepting errors and hiding
sensitive headers.
Example Nginx Configuration:
COPY
http {
error_page 500 /html/error.html;
proxy_intercept_errors on;
proxy_hide_header Secret-Header;
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
location = /html/error.html {
internal;
root /usr/share/nginx/html;
}
}
being forwarded to the client, even if the backend includes it in the response.
Under normal circumstances, this setup works as intended. However, when an invalid
HTTP request is sent to the server, Nginx may forward this malformed request
directly to the backend without processing it properly. The backend's raw response,
including any headers and content, is then sent directly to the client without Nginx's
intervention.
Example Invalid HTTP Request:
COPY
(CRLF) is sent, Nginx might not correctly intercept the response. The backend's
raw response, including the Secret-Header , is sent directly to the client.
Example Output for Invalid Request:
COPY
Attack Scenario
To mitigate the risk of exposing raw backend responses, consider the following
strategies:
1. Strict Request Validation:
Implement strict validation of incoming requests to ensure they adhere to
proper HTTP standards. This can be done using Nginx’s if directive or by
setting up custom error handling for malformed requests.
2. Custom Error Handling for All Scenarios:
Ensure that even in cases of malformed requests, Nginx serves a generic
error page instead of forwarding the request to the backend. You can do this
by defining error pages for common invalid requests.
COPY
server {
listen 80;
location / {
if ($request_uri ~* "%0D|%0A") {
return 400 "Bad Request";
}
proxy_pass http://backend;
}
}
1. merge_slashes Directive
http://example.com//etc/passwd
Attack Scenario:
Mitigation:
Turn off the merge_slashes directive in Nginx to ensure that URLs are forwarded to
the backend without modification.
COPY
http {
merge_slashes off;
}
Certain headers in the HTTP response can alter Nginx’s behavior, potentially leading
to security vulnerabilities. These headers include:
X-Accel-Redirect : Triggers an internal redirect in Nginx.
X-Accel-Buffering : Controls whether Nginx should buffer the response.
X-Accel-Charset : Sets the charset for the response when using X-Accel-Redirect .
X-Accel-Redirect: /.env
Attack Scenario:
If the Nginx configuration has root / , this header could cause Nginx to internally
redirect the request to the .env file, exposing sensitive environment variables to the
client.
Mitigation:
Ensure that the backend does not send headers like X-Accel-Redirect unless
explicitly intended. Additionally, carefully review the Nginx configuration to prevent
unintended access.
The map directive in Nginx is often used to map one value to another, frequently for
controlling access or other logic. However, failing to specify a default value in a map
can lead to unintended behavior.
Example:
COPY
http {
map $uri $mappocallow {
/map-poc/private 0;
/map-poc/secret 0;
/map-poc/public 1;
}
}
server {
location /map-poc {
if ($mappocallow = 0) { return 403; }
return 200 "Hello. It is a private area: $mappocallow";
}
}
Attack Scenario:
http {
map $uri $mappocallow {
default 0;
/map-poc/private 0;
/map-poc/secret 0;
/map-poc/public 1;
}
}
If Nginx is configured to use an external DNS server, there’s a risk of DNS spoofing if
an attacker can intercept and manipulate DNS responses.
COPY
resolver 8.8.8.8;
Attack Scenario:
If an attacker gains control over the DNS server or can spoof DNS responses, they
could redirect Nginx to a malicious server.
Mitigation:
To mitigate this risk, configure Nginx to use a trusted, internal DNS server (e.g.,
127.0.0.1 ):
COPY
resolver 127.0.0.1;
The proxy_pass directive is used to forward requests to another server, while the
internal directive ensures that certain locations are only accessible within Nginx.
Example:
COPY
location /internal/ {
internal;
proxy_pass http://backend/internal/;
}
Attack Scenario:
If the internal directive is not properly configured, it could allow external access to
sensitive internal locations, potentially exposing sensitive data or allowing
unauthorized operations.
Mitigation:
Ensure that internal locations are correctly configured and not accessible from
outside:
COPY
location /internal/ {
internal;
proxy_pass http://backend/internal/;
}
location /public/ {
proxy_pass http://backend/public/;
}
Also, use proper access controls and authentication mechanisms to restrict access to
sensitive locations.
Attack Scenario
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /usr/local/nginx/conf/cert.pem;
ssl_certificate_key /usr/local/nginx/conf/privkey.pem;
location / {
proxy_pass http://backend:9999;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
}
location /flag {
deny all;
}
}
1. proxy_set_header Upgrade $http_upgrade; :
This line forwards the Upgrade header from the client to the backend server.
The Upgrade header is typically used in WebSocket connections to switch
protocols from HTTP/1.1 to WebSocket or from HTTP/1.1 to HTTP/2.
2. proxy_set_header Connection $http_connection; :
This line forwards the Connection header, which controls whether the
network connection stays open after the current transaction finishes. When
combined with Upgrade , it can lead to the backend server establishing a
different type of connection (e.g., HTTP/2).
Vulnerability:
backend server ( http://backend:9999 ). This means the attacker can access any
other internal path, such as /flag , bypassing Nginx’s security rules.
Attack Scenario:
1. Crafted Request:
An attacker sends an HTTP/1.1 request to the Nginx server with the Upgrade:
h2c header.
The Nginx server, due to the configuration, forwards this request to the
backend server.
2. Backend Connection:
The backend interprets the Upgrade: h2c header and switches the
connection to HTTP/2 cleartext mode.
The attacker now has direct access to the backend server and can issue
additional HTTP/2 requests that bypass Nginx entirely.
3. Accessing Protected Endpoint:
The attacker can then request protected endpoints, such as /flag , which
would otherwise be denied by Nginx.
Example of an Attack:
To exploit this vulnerability, an attacker could use a tool like curl or a custom script
to send the following request:
COPY
If the backend supports HTTP/2 in cleartext mode, this request could smuggle a
connection upgrade to HTTP/2 and allow the attacker to bypass Nginx’s path
restrictions.
Mitigation:
To protect against this vulnerability, avoid forwarding the Upgrade and Connection
headers unless they are absolutely necessary and you are confident in the backend
server’s ability to handle them securely.
Secure Configuration:
COPY
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /usr/local/nginx/conf/cert.pem;
ssl_certificate_key /usr/local/nginx/conf/privkey.pem;
location / {
proxy_pass http://backend:9999;
proxy_http_version 1.1;
# Remove or restrict the following headers unless necessary:
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection $http_connection;
}
location /flag {
deny all;
}
}
In scenarios where WebSockets or HTTP/2 upgrades are necessary, ensure that the
backend server is properly secured and does not allow the misuse of these headers
to access unauthorized resources.
Additional Attack Scenarios and Commands:
Resources
https://book.hacktricks.xyz/network-services-pentesting/pentesting-
web/nginx#proxy_set_header-upgrade-and-connection
Written by
Reza Rashidi Add your bio
Published on
DevSecOpsGuides Add blog description
MORE ARTICLES
Reza Rashidi Reza Rashidi
Attacking OpenStack Attacking CI/CD
Attacking OpenStack, an open-source In CI/CD (Continuous
cloud computing platform, involves Integration/Continuous Deployment)
exploiting vulnerabilities in…
Reza Rashidi environments, several methods and
attacks ca…
Attacking Pipeline
DevOps pipelines, which integrate and
automate the processes of software
development and IT operatio…
©2024 DevSecOpsGuides
Archive · Privacy policy · Terms
Write on Hashnode
Powered by Hashnode - Home for tech writers and readers