O que é o OWASP Web Application Top 10?

O OWASP Top 10 é o documento de conscientização mais amplamente reconhecido para a segurança de aplicativos da Web. A edição de 2025 reflete o cenário de ameaças mais recente, introduzindo novas categorias, como Falhas na cadeia de suprimentos de software e Manuseio incorreto de condições excepcionais.

1️⃣ A01 - Controle de acesso quebrado

Critical

Visão geral

O controle de acesso aplica a política de modo que os usuários não possam agir fora das permissões pretendidas. As falhas geralmente levam à divulgação não autorizada de informações, à modificação ou destruição de dados ou à execução de uma função comercial fora dos limites do usuário.

Risco

Os invasores podem explorar as falhas de controle de acesso para acessar as contas de outros usuários, visualizar arquivos confidenciais, modificar os dados de outros usuários ou alterar os direitos de acesso.

Exemplo de código vulnerável

Python ❌ Bad
# User ID taken directly from request without authorization check
@app.route('/api/user/<user_id>/profile')
def get_profile(user_id):
    user = db.get_user(user_id)  # No ownership check!
    return jsonify(user.to_dict())

Exemplo de código seguro

Python ✅ Good
@app.route('/api/user/<user_id>/profile')
@login_required
def get_profile(user_id):
    # Verify the requesting user owns this resource
    if current_user.id != user_id and not current_user.is_admin:
        abort(403)

    user = db.get_user(user_id)
    if not user:
        abort(404)
    return jsonify(user.to_dict())

Lista de verificação de mitigação

2️⃣ A02 - Configuração incorreta de segurança

High

Visão geral

A configuração incorreta da segurança ocorre quando as configurações de segurança são definidas, implementadas ou mantidas incorretamente. Isso inclui a falta de reforço de segurança, recursos desnecessários ativados, contas padrão com senhas inalteradas, mensagens de erro excessivamente detalhadas e cabeçalhos de segurança HTTP mal configurados.

Risco

Servidores, estruturas ou serviços em nuvem mal configurados podem expor dados confidenciais, permitir acesso não autorizado ou fornecer aos invasores informações para planejar outros ataques.

Exemplo de código vulnerável

Python ❌ Bad
# Debug mode enabled in production, verbose errors exposed
app = Flask(__name__)
app.config['DEBUG'] = True  # Exposes stack traces!
app.config['SECRET_KEY'] = 'default-secret'  # Default key!

Exemplo de código seguro

Python ✅ Good
import os

app = Flask(__name__)
app.config['DEBUG'] = False
app.config['SECRET_KEY'] = os.environ['SECRET_KEY']

@app.after_request
def set_security_headers(response):
    response.headers['X-Content-Type-Options'] = 'nosniff'
    response.headers['X-Frame-Options'] = 'DENY'
    response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
    response.headers['Content-Security-Policy'] = "default-src 'self'"
    return response

Lista de verificação de mitigação

3️⃣ A03 - Falhas na cadeia de suprimentos de software

High

Visão geral

Novo em 2025. Concentra-se nos riscos relacionados a componentes de terceiros, dependências e pipelines de CI/CD. Os invasores têm como alvo a cadeia de suprimentos de software comprometendo pacotes, injetando códigos mal-intencionados em bibliotecas de código aberto ou explorando vulnerabilidades de pipeline de compilação.

Risco

Uma única dependência comprometida pode afetar milhares de aplicativos. Os ataques à cadeia de suprimentos podem levar ao roubo de dados, à instalação de backdoors ou ao comprometimento total do sistema com detecção mínima.

Exemplo de código vulnerável

JavaScript ❌ Bad
// package.json with unpinned dependencies
{
  "dependencies": {
    "express": "*",           // Any version!
    "lodash": "^4.0.0",       // Wide range
    "unknown-pkg": "^1.0.0"   // Unvetted package
  }
}

Exemplo de código seguro

JavaScript ✅ Good
// package.json with pinned versions + lockfile + audit
{
  "dependencies": {
    "express": "4.21.2",
    "lodash": "4.17.21"
  },
  "scripts": {
    "preinstall": "npx npm-audit-resolver",
    "integrity-check": "npm audit signatures"
  }
}
// Also: use package-lock.json, enable Dependabot/Renovate,
// generate SBOM, verify package provenance

Lista de verificação de mitigação

4️⃣ A04 - Falhas criptográficas

High

Visão geral

Falhas relacionadas à criptografia que geralmente levam à exposição de dados confidenciais. Isso inclui o uso de algoritmos obsoletos, geração de chaves fracas, falta de criptografia para dados em trânsito ou em repouso e validação inadequada de certificados.

Risco

A criptografia fraca ou ausente pode expor senhas, números de cartão de crédito, registros de saúde, informações pessoais e segredos comerciais, o que pode levar a violações regulamentares (GDPR, PCI DSS).

Exemplo de código vulnerável

Python ❌ Bad
import hashlib

# Storing passwords with weak hashing
def store_password(password: str) -> str:
    return hashlib.md5(password.encode()).hexdigest()  # MD5 is broken!

Exemplo de código seguro

Python ✅ Good
import bcrypt

def store_password(password: str) -> bytes:
    # Use bcrypt with automatic salting
    salt = bcrypt.gensalt(rounds=12)
    return bcrypt.hashpw(password.encode(), salt)

def verify_password(password: str, hashed: bytes) -> bool:
    return bcrypt.checkpw(password.encode(), hashed)

Lista de verificação de mitigação

5️⃣ A05 - Injeção

Critical

Visão geral

As falhas de injeção ocorrem quando dados não confiáveis são enviados a um intérprete como parte de um comando ou consulta. Injeção de SQL, injeção de NoSQL, injeção de comando de sistema operacional e XSS (Cross-Site Scripting) são as formas mais comuns. Dados hostis podem induzir o intérprete a executar comandos não intencionais.

Risco

A injeção pode resultar em perda de dados, corrupção, acesso não autorizado, controle total do host ou negação de serviço. A injeção de SQL, por si só, continua sendo um dos vetores de ataque mais perigosos e predominantes.

Exemplo de código vulnerável

Python ❌ Bad
# SQL injection via string concatenation
def get_user(username: str):
    query = f"SELECT * FROM users WHERE name = '{username}'"
    return db.execute(query)  # username = "' OR '1'='1"

Exemplo de código seguro

Python ✅ Good
# Parameterized queries prevent SQL injection
def get_user(username: str):
    query = "SELECT * FROM users WHERE name = %s"
    return db.execute(query, (username,))

# For XSS prevention, escape output
from markupsafe import escape

def render_comment(comment: str) -> str:
    return f"<p>{escape(comment)}</p>"

Lista de verificação de mitigação

6️⃣ A06 - Design inseguro

High

Visão geral

O design inseguro refere-se aos riscos relacionados a falhas de design e arquitetura. Ele exige o uso de modelagem de ameaças, padrões de design seguro e arquiteturas de referência. Um projeto inseguro não pode ser corrigido por uma implementação perfeita; os controles de segurança necessários nunca foram criados para defender-se de ataques específicos.

Risco

As falhas de design podem levar a vulnerabilidades de lógica comercial que são difíceis de detectar com ferramentas automatizadas. A falta de limites de taxa em operações confidenciais, a falta de autenticação multifatorial para ações críticas ou a detecção insuficiente de fraudes são falhas no nível do projeto.

Exemplo de código vulnerável

Python ❌ Bad
# Password reset with no rate limit or verification
@app.route('/reset-password', methods=['POST'])
def reset_password():
    email = request.form['email']
    new_pass = request.form['new_password']
    user = db.find_by_email(email)
    user.password = hash_password(new_pass)  # No token verification!
    db.save(user)

Exemplo de código seguro

Python ✅ Good
from datetime import datetime, timedelta

@app.route('/reset-password', methods=['POST'])
@rate_limit("3/hour")
def reset_password():
    token = request.form['token']
    new_pass = request.form['new_password']

    # Verify time-limited, single-use token
    reset_req = db.find_reset_token(token)
    if not reset_req or reset_req.used or reset_req.expires < datetime.utcnow():
        abort(400, "Invalid or expired token")

    # Enforce password complexity
    if not meets_password_policy(new_pass):
        abort(400, "Password does not meet requirements")

    reset_req.user.password = hash_password(new_pass)
    reset_req.used = True
    db.save_all([reset_req.user, reset_req])

Lista de verificação de mitigação

7️⃣ A07 - Falhas de autenticação

High

Visão geral

A confirmação da identidade, da autenticação e do gerenciamento de sessões de um usuário é fundamental. As falhas de autenticação ocorrem quando os aplicativos permitem o preenchimento de credenciais, força bruta, senhas fracas ou têm falhas no gerenciamento de sessões, como IDs de sessão não rotativos após o login.

Risco

Os invasores podem obter acesso às contas dos usuários por meio de preenchimento automático de credenciais, força bruta ou sequestro de sessão. Contas comprometidas podem levar a roubo de identidade, fraudes e violações de dados.

Exemplo de código vulnerável

Python ❌ Bad
# No brute force protection, weak session handling
@app.route('/login', methods=['POST'])
def login():
    user = db.find_by_email(request.form['email'])
    if user and user.password == request.form['password']:  # Plain comparison!
        session['user'] = user.id  # Session ID not rotated
        return redirect('/dashboard')

Exemplo de código seguro

Python ✅ Good
from flask_limiter import Limiter

limiter = Limiter(app, default_limits=["100/hour"])

@app.route('/login', methods=['POST'])
@limiter.limit("5/minute")
def login():
    user = db.find_by_email(request.form['email'])
    if not user or not bcrypt.checkpw(
        request.form['password'].encode(), user.password_hash
    ):
        # Generic error to prevent user enumeration
        return "Invalid credentials", 401

    # Rotate session ID after authentication
    session.regenerate()
    session['user'] = user.id

    # Check for MFA requirement
    if user.mfa_enabled:
        return redirect('/mfa-verify')
    return redirect('/dashboard')

Lista de verificação de mitigação

8️⃣ A08 - Falhas de integridade de software ou dados

High

Visão geral

As falhas de integridade de software e dados estão relacionadas ao código e à infraestrutura que não protegem contra violações de integridade. Isso inclui desserialização insegura, uso de CDNs ou plug-ins não confiáveis sem verificação de integridade e mecanismos de atualização automática sem atualizações assinadas.

Risco

A desserialização insegura pode levar à execução remota de códigos. O carregamento de scripts de CDNs não confiáveis sem Subresource Integrity (SRI) pode permitir que os invasores injetem códigos mal-intencionados em seu aplicativo.

Exemplo de código vulnerável

HTML ❌ Bad
<!-- Loading external scripts without integrity checks -->
<script src="https://cdn.example.com/lib.js"></script>

<!-- Insecure deserialization in Python -->
import pickle
data = pickle.loads(user_input)  # Arbitrary code execution!

Exemplo de código seguro

HTML ✅ Good
<!-- Use Subresource Integrity (SRI) for external scripts -->
<script src="https://cdn.example.com/lib.js"
  integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K..."
  crossorigin="anonymous"></script>

# Use safe deserialization in Python
import json
data = json.loads(user_input)  # Safe: only parses JSON data

Lista de verificação de mitigação

9️⃣ A09 - Falhas no registro de segurança e alertas

Medium

Visão geral

Sem registros, monitoramento e alertas suficientes, as violações não podem ser detectadas em tempo hábil. O registro insuficiente, a integração ineficaz com sistemas de resposta a incidentes e a falta de alertas em tempo real permitem que os invasores ataquem ainda mais os sistemas, mantenham a persistência e adulterem ou extraiam dados.

Risco

Sem o registro adequado, os invasores podem operar sem serem detectados por longos períodos. A maioria dos estudos sobre violações mostra que o tempo médio para detectar uma violação é superior a 200 dias, geralmente descoberto por partes externas em vez de monitoramento interno.

Exemplo de código vulnerável

Python ❌ Bad
# No logging of security-relevant events
@app.route('/login', methods=['POST'])
def login():
    user = authenticate(request.form)
    if not user:
        return "Login failed", 401  # No record of failure
    return redirect('/dashboard')

Exemplo de código seguro

Python ✅ Good
import logging
from datetime import datetime

security_log = logging.getLogger('security')

@app.route('/login', methods=['POST'])
def login():
    user = authenticate(request.form)
    if not user:
        security_log.warning(
            "LOGIN_FAILED | ip=%s | email=%s | time=%s",
            request.remote_addr,
            request.form.get('email', 'unknown'),
            datetime.utcnow().isoformat(),
        )
        check_brute_force(request.remote_addr)
        return "Invalid credentials", 401

    security_log.info(
        "LOGIN_SUCCESS | user_id=%s | ip=%s",
        user.id, request.remote_addr,
    )
    return redirect('/dashboard')

Lista de verificação de mitigação

🔟 A10 - Manuseio incorreto de condições excepcionais

Medium

Visão geral

Novo em 2025. Os aplicativos que tratam erros, exceções e casos extremos de forma inadequada podem expor informações confidenciais, entrar em estados inconsistentes ou criar condições exploráveis. Isso inclui mensagens de erro detalhadas na produção, exceções não capturadas que ignoram os controles de segurança e condições de corrida.

Risco

O tratamento inadequado de erros pode expor rastros de pilha, detalhes do banco de dados ou caminhos internos. As condições de corrida nas verificações de segurança podem permitir ataques do tipo tempo de verificação para tempo de uso (TOCTOU), contornando a autorização ou a validação de pagamento.

Exemplo de código vulnerável

Python ❌ Bad
# Exposing internal details in error messages
@app.route('/api/data')
def get_data():
    try:
        result = db.query(request.args['q'])
        return jsonify(result)
    except Exception as e:
        return jsonify({"error": str(e)}), 500  # Leaks DB details!

Exemplo de código seguro

Python ✅ Good
import uuid, logging

logger = logging.getLogger(__name__)

@app.errorhandler(Exception)
def handle_exception(e):
    error_id = str(uuid.uuid4())
    logger.error("Unhandled exception [%s]: %s", error_id, e, exc_info=True)

    # Return generic error with reference ID for support
    return jsonify({
        "error": "An internal error occurred",
        "reference": error_id,
    }), 500

@app.route('/api/data')
def get_data():
    q = request.args.get('q')
    if not q or not is_valid_query(q):
        return jsonify({"error": "Invalid query parameter"}), 400

    result = db.query(q)
    return jsonify(result)

Lista de verificação de mitigação

📊 Tabela de resumo

ID Vulnerabilidade Gravidade Principais medidas de mitigação
A01Controle de acesso quebradoCriticalVerificações de acesso no lado do servidor, negação por padrão, propriedade de registros
A02Configuração incorreta da segurançaHighProcesso de fortalecimento, cabeçalhos de segurança, desativação de padrões
A03Falhas na cadeia de suprimentos de softwareHighDependências fixas, SBOM, varredura de dependências
A04Falhas criptográficasHighAlgoritmos robustos, TLS 1.2+, gerenciamento de chaves
A05InjeçãoCriticalConsultas parametrizadas, codificação de saída, validação de entrada
A06Design inseguroHighModelagem de ameaças, padrões seguros, testes de casos de abuso
A07Falhas de autenticaçãoHighMFA, proteção contra força bruta, rotação de sessão
A08Falhas de integridade de software ou de dadosHighSRI, atualizações assinadas, desserialização segura
A09Falhas nos registros e alertas de segurançaMediumRegistro centralizado, alertas em tempo real, resposta a incidentes
A10Manuseio incorreto de condições excepcionaisMediumManipulador de erros global, mensagens genéricas, prevenção de TOCTOU