# Common NGINX Misconfigurations

Veja também em vídeo aqui:  
[https://youtu.be/0Kn9RmUByXQ](https://youtu.be/0Kn9RmUByXQ)

---

Aposto que você já teve que criar algum arquivo de rotas usando NGINX, seja para distribuir assets de uma pasta específica, seja para redirecionar o tráfego para outra aplicação interna.

Contudo, todavia, entretanto, se você acabar comentendo alguns destes 3 erros clássicos, você pode acabar com um set de vulnerabilidades bem facinho aí.

## 1 - Missing Root

Todo arquivo de NGINX pode ter um ponto de partida onde ele vai procurar por arquivos. Para isto, utilizamos o `root`:

```nginx
server {
    listen       80;
    server_name  localhost;
    root /etc/nginx; # <-- AQUI

    location /home/ {
        alias   /usr/share/nginx/html/;
        index  home.html home.htm;
        try_files $uri $uri/ =404;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
```

Porém perceba que em nossas configurações, não temos nenhum `location` que aponta para `/`.

A falta desta configuração faz com que o NGINX tenha a permissão de entregar qualquer arquivo que esteja dentro da pasta definida no `root` (`/etc/nginx`).

Ou seja, se você fizer uma request para \`/nginx.conf\`, o NGINX vai procurar por este arquivo dentro do diretório root. Se encontrar, vai entregar para você.

```plaintext
=== REQUEST ===
curl http://localhost/nginx.conf

=== RESPONSE ===
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    keepalive_timeout  65;

    # include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/conf.d/server.conf;
}
```

Para corrigir este problema, basta definir uma rota raiz. Ela pode redirecionar para o index do site ou outra página que deseje.

```nginx
server {
    listen       80;
    server_name  localhost;
    root /etc/nginx;

    location / { # <-- AQUI
        return 302 https://my-site-index.com;
    }

    location /home/ {
        alias   /usr/share/nginx/html/;
        index  home.html home.htm;
        try_files $uri $uri/ =404;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
```

## 2 - Alias Traversal

Um erro bastante comum e inclusive fácil de cometermos é expormos os arquivos do servidor por causa da falta de um `/`.

Veja a configuração a seguir:

```nginx
server {
    listen       80;
    server_name  localhost;

    location /health {
        return 200 "healthy\n";
        add_header Content-Type text/plain;
    }

    location /assets {
        alias /var/assets/;
    }

    location / {
        root   /usr/share/nginx/html;
        index  home.html home.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
```

Justamente onde temos o `/assets` , estamos mapeando que todo request recebido neste path, devemos buscar por resources dentro de `/var/assets/` .

Até aí tudo bem, mas o problema aqui é justamente usarmos `/assets` e não `/assets/` .

A falta desta `/` ao final, permite que um atacante busque por outros arquivos no servidor, usando um traversal (`../`).

Com isso, deixamos nosso server vulnerável a ataques como este aqui:

```bash
curl http://mysite.com/assets../log/nginx/access.log
```

Onde o NGINX vai permitir que uma busca a nível mais alto na hierarquia de diretorios seja realizada, concendo acessos à outros arquivos na qual não deveriam ser expostos externamente.

Para corrigir isso, basta colocar uma `/` ao final:

```nginx
# ❌ NOOOP
location /assets {
    alias /var/assets/;
}

# ✅ YEEEP
location /assets/ {
    alias /var/assets/;
}
```

## 3 - Unsafe $uri

O terceiro e um dos mais legais na minha opinião é você ser capaz de adicionar header qualquer na resposta de uma requisição via URL.

Simples:

1. Você monta uma URL maliciosa.
    
2. Manda para a vítima (qualquer técnica de phishing).
    
3. Ela clica.
    
4. Faz um request para o server.
    
5. O server responde com seu Header customizado.
    
6. Se a aplicação confia nos headers de resposta do servidor e faz algo com ela, boooom 💀.
    

Veja a configuração a seguir:

```nginx
server {
    listen       80;
    server_name  localhost;
    root  /usr/share/nginx/html/;

    location / {
        return 302 http://localhost/v2$uri;
    }

    location /v2/ {
        return 200 "Hello\n";
        add_header Content-Type text/plain;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
```

Perceba onde mapeamos o `location /` estamos redirecionando todos para a versão 2 do nosso site ou api (beeem comum aqui). Porém contatenamos tudo que o usuário colocar na URL, para preservar paths, query strings, etc (com o `$uri` ).

O problema aqui é justamente o uso do `$uri` e abertura para um CRLF Injection.

Se o atacante enviar este link para a vítima:

```bash
https://mysite.com/%0d%0aSet-Cookie:%20session=12345
```

O servidor vai responder que deve criar este cookie session=12345 no navegador da vítima.

Porque isto acontece?

Este `%0d%0a` é uma *quebra de linha*. Ao montar a resposta, o pacote HTTP vai ficar assim:

```http
HTTP/2 302 Found
Location: http://localhost/v2/
Set-Cookie: session=12345
```

E isso aconteceu porque:

1. Vítima abre o link `https://mysite.com/%0d%0aSet-Cookie:%20session=12345`
    
2. Servidor recebe requisição.
    
3. Servidor encontra rota no NGINX (`location /`)
    
4. Servidor ve que precisa redirecionar para v2 mantendo o path etc (`return 302 http://localhost/v2$uri;`)
    
5. Todo redirect (301, 302) seta um header location. Neste caso, vai definir este header com o redirecionamento, que é `http://localhost/v2$uri`
    
6. Mas para redirecionar, precisa colocar o valor da variável `$uri` .
    
7. Ao substituir a variável, fica assim: `http://localhost/v2/%0d%0aSet-Cookie:%20session=12345`
    
8. Por estar usando a variável `$uri` , precisa parsear os caracteres especiais, no caso de `%0d%0a` , é uma nova linha.
    
9. No protocolo HTTP, uma nova linha é... UM HEADER NOVO.
    
10. É adicionado a nova linha `Set-Cookie:%20session=12345` , que vira um novo header.
    
11. Este header é devolvido na resposta.
    
12. O navegador lê os headers da resposta.
    
13. Vê um header `Set-Cookie` e cria o cookie.
    

Ou seja, se sua aplicação confia cegamente nas respostas da api e você possui esta config, possui uma vulnerabilidade que pode ser explorada.

Para corrigir isso, basta utilizar `$request_uri` e não `$uri` ou `$document_uri`.

Igual, não se esqueça de sanitizar os headers Location, uma vez que esta mesma vulnerabilidade pode estar presente em outros mecanismos de redirecionamento em sua infraestrutra.

## References

* [https://labs.hakaioffsec.com/nginx-alias-traversal/](https://labs.hakaioffsec.com/nginx-alias-traversal/)
    
* [https://blog.detectify.com/2020/11/10/common-nginx-misconfigurations/](https://blog.detectify.com/2020/11/10/common-nginx-misconfigurations/)
    
* [https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/nginx](https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/nginx)
