Wallace Soares
Processos de autenticação, autorização, controle de acesso e sessão surgem para fazer o gerenciamento dos usuários as mais diversas funções de sistemas. Entretanto existem alguns problemas que surgem a partir de implementação e suposições que acontecem durante o processo de desenvolvimento. Neste documento iremos apresentar tanto as formas de ataque como possíveis formas de prevenção.

Ataques força-bruta

Ataques força-bruta são um dos tipos de ataque mais simples que existem para ganhar acesso privilégiado. Consistem em basicamente realizar várias tentativas de login com credenciais que tem potencial de acesso ao sistema. Em caso de as credenciais estarem corretas o atacante conseguirá acessar a conta do usuário. Pelo fato de existirem múltiplas formas de se implementar autenticação de credenciais é possível que cada sistema possua uma ou mais vulnerabilidades relacionadas. Algumas delas estão descritas abaixo.

Não há qualquer tipo de tratamento a tentativas incorretas de login

Em casos em que não há tratamento para estes tipos de ataques um adversário pode tentar quantas vezes quiser acessar um sistema com quaisquer credenciais sem ser impedido de qualquer forma. Casos de sucesso podem ser diferenciados de casos falhos tanto pelo código HTTP como pelo Content-length da resposta do servidor. Deve sempre existir algum mecanismo para evitar este tipo de situação.

Um HTTP Header é configurado a cada tentativa falha

Em casos quando o HTTP Header é configurado a cada falha no login(e.g.: failedLogin=1) é possivel continuar a explorar a vulnerabilidade sem qualquer impedimento apenas resetando o header a cada tentativa de login usando o Burp Intruder. Portanto não se deve utilizar parâmetros do HTTP Request para limitar a quantidade de tentativas de acesso.

Lock de contas após N tentativas de login

Em casos em que é lock de contas há algumas possibilidades do que pode acontecer:
  • Uma regra muito restritiva pode levar a multiplas contas lockadas se um atacante se dedicar e possuir informações sobre os usuários registrados. Isto também seria uma vulnerabildide associada ao sistema que estaria relacionada a negação de serviço como definido em CWE-645: Overly Restrictive Account Lockout Mechanism.
  • Se o sistema possuir um lock de contas, mas validar as credenciais da mesma forma, é possível, através do tempo de resposta do servidor, supor quando as credenciais foram corretas. Portanto, em casos como estes não se deve verificar de nenhuma forma se as credenciais fornecidades são válidas. Deve-se apenas negar o acesso do usuário, ou até bloquear o IP para estes requests. Isto evita tanto enumeração de usuários registrados, como também não permite que o atacante advinhe as credenciais dos usuários registrados.

Respostas muito verbosas

Muitas vezes os desenvolvedores, como forma de detalhar mais a implementação e ser consistente com o código implementado, logam o tipos de erros que aconteceram. Estas informações, em forma de logs são bastante úteis. Porém quando estas mesmas mensagens são respondidas pelo servidor ao usuário final entregam informações valiosas que podem ser utilizadas para atacar o servidor. Portanto deve-se evitar ao máximo mensagens que dão informações sobre erros no servidor.

Tipos de informações que devem ser evitadas de serem enviadas pelo servidor durante exceções como resposta seriam:
  • Em casos de falha no login não se deve dizer o que causou a falha, como por exemplo "usuário não encontrado" ou "senha incorreta". Estas informações podem dizer se um usuário "A" esta cadastrado no sistema facilitando a um atacante a enumeração de usuários cadastrados.
  • Qualquer exceção de controle de acesso(e.g.: Somente admins podem realizar esta ação.) deve ser tratado de forma genérica. Estas exceções podem ser utilizadas por atacantes para entender como o sistema funciona em um todo.
  • Qualquer exceção não esperada, de forma geral, deve-se mostrada de forma genérica(e.g.: "Erro inesperado"). Isto evita que, por exemplo, exceções de banco exibam informações sobre o banco de dados.

Senhas: possibilidades

Senhas são as formas primárias, pelo menos até hoje, de autenticar usuários em sistemas. E junto com elas vem mecanismos de recuperação e alteração para que a conta possa se manter segura. Estes são os mecanismos mais suscetíveis a tentativas de ataques justamente por conta do quanto é possível escalar a partir do sucesso do ataque. Algumas formas de vulnerabilidade que podem ser exploradas são:
  • Quando o request não é propriamente validado é possível manipular os parâmetros durante um reset de senha para que, por exemplo, a URL do reset seja enviado a 2 emails, o da vítima e do atacante. Por exemplo:

    Request Original

    POST /resetPassword
    ...(HTTP Headers)
    "email": "victim@email.com"


    Request Manipulado

    POST /resetPassword
    ...(HTTP Headers)
    "email": ["victim@email.com", "attacker@email"]


    Dessa forma o email de reset da senha será enviado para os dois emails.

  • Da mesma forma alguns sistemas confiam nos mesmos parâmetros do HTTP Header para saber a URL que deve ser enviada para o usuário, durante um reset. Portanto é possível que um atacante mude os parâmetros do request para que a URL enviada a vítima seja manipulada. Por exemplo:

    Request Original

    X-Forward-Host: example.com

    Request Manipulado

    X-Forward-Host: evil.com

    Dessa forma a URL enviada para o email irá iniciar com evil.com onde pode contar códigos maliciosos para roubar o token de alteração de senha.

  • Uma outra forma de ataques esta presente em reset de senhas que passam o ID do usuário durante o request. Por exemplo:

    Request Original

    POST /changePassword
    ...(HTTP Headers)
    "user": "attackerUser"
    "newPass": "pass"
    "newPassAgain": "pass"


    Request manipulado

    POST /changePassword
    ...(HTTP Headers)
    "user": "victimUser"
    "newPass": "pass"
    "newPassAgain": "pass"


    Se caso o backend não valide que o usuário performando a ação é o mesmo usuário que esta sofrendo a alteração de senha um atacante pode alterar a senha de qualquer outro usuário.

Gerenciamento de Sessões

Gerenciamento de sessões é um componente de segurança fundamental para a maioria das aplicações. Por conta de seu papel importante este componente atrai bastante olhos de atacantes. Na maioria das vezes as sessões são controladas através de cookies e tokens. Estes podem oferecer muita informação sobre os usuários e tipos de usuários da aplicação em teste. Estes tokens, em sua maioria, são codificados de alguma forma, seja base64, HEX ou até criptografados. JSON Web Tokens - JWTs - também estão sendo utilizados recentemente para controle de sessões. Exemplos de cookies e tokens de controle de sessão seriam:
  • Cookie: sessionId:45789-145123213

    Estes tipos de tokens que contêm apenas números inteiros são um dos mais primários existentes. Neste tipo de cookie é possivel supor a existência de dois parâmetros que controlem a sessão: id do usuário e um número aleatório. Estes tipos de cookies podem ser muito vulneraveis a session hijacking. Por duas motivos: podem ser simples de deduzir e podem ser simples de ser manipulados.

  • Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0Ij
    oxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c


    Neste tipo de token, que é conhecido como JWTs, estão contidos três conjuntos de informações: o header, payload e signature. Onde cada sessão é separada por um ponto(.) Este tipo de token, particularmente no payload, pode conter uma série de informações que podem ser definidas durante o desenvolvimento. As informações que podem estar presentes são:
    • Nome do usuário
    • ID do usuário
    • Email do usuário
    • Permissões do usuário(admin, editor, viewer)
    JWT podem, se não forem bem utilizados, podem entregar bastante informação sobre como a aplicação funciona. Além de possuirem vulnerabilidades associadas que serão cobertas em um outro post.


Alguns cuidados precisam ser tomados quando se utilizam cookies e tokens para gerenciamento de sessões, alguns deles são:
  • Não deixar a geração de tokens previsíveis. Como por exemplo incrementar de um em um o cookie para controle de sessão. Este tipo de controle tornaria extremamente fácil um atacante roubar a sessão de um usuário.
  • Não expor informações relevantes dentro dos tokens. Ou realizar o controle de acesso ou autorização através de informações presentes no token.
  • Manter o tempo de expiração do token baixo para evitar roubo de sessões.
  • Gere sempre novos tokens a cada sessão, como também após o tempo de expiração. Não mantenha os tokens estáticos.
  • Invalidar tokens assim que usuários realizarem o logout da aplicação.
  • Não passar tokens via parâmetros na query.
  • Não permitir que qualquer usuário gere tokens para qualquer outro usuário, seja por parâmetros em query ou através de POSTs.
  • Trate os tokens de forma segura. Proteja-os nos logs, através de um acesso controlado, e proteja-os através da camada de transporte usando sempre HTTPS.
  • Fique atento a ataques de Cross-site scripting(XSS) na sua aplicação. Em caso vulneráveis um atacante pode roubar a sessão de outros usuários explorando esta fraqueza.
Como é possivel observar há multiplas formas de, tanto entender como a aplicação funciona, em caso de cookies e tokens muito descritivos, como manipular os cookies para roubar sessões, em caso de cookies que não possuem validações no backend. Apesar de forneceram um mecanismo de controle extremamente útil se não forem tratados de forma correta podem gerar sérios problemas.

Controle de Acessos

Como um dos principais métodos de segurança os controles de acesso a funções existentes no sistema são primordiais para defender ações inesperadas de usuários que não possuam privilégios. Vulnerabilidades relacionadas ao controle de acesso pode não somente bagunçar o banco de dados, mas pode comprometer o sistema como um todo. Veremos aqui alguns tipos de vulnerabilidades relacionadas a este tópico.

Funcionalidade completamente desprotegida

Seriam funções e/ou páginas completamente desprotegidas de autenticação. Por exemplo:

POST /createAdmin?user=admin&pass=12345

Este tipo de endpoint deve, a primeira vista, criar um usuário do tipo administrador que possuirá privilégios máximos no sistema. E sendo assim deveria ser protegida no lado do servidor e ser somente realizada através de outros usuários do tipo administrador. Em caso negativo, qualquer usuário pode acabar criando uma conta com altos privilégios que poderá executar ações críticas do sistema. Sempre se deve verificar se o usuário pode realizar uma ação, principalmente se for uma ação crítica no sistema.

Falta restrição de acesso à novas features

Muitas vezes, novas features são colocadas em produção e não são diretamente referenciadas através de links e botões na UI. Entretanto não se deve assumir que atacantes não encontrariam esses caminhos porque não são referenciados. Deve-se sempre proteger esses caminhos para evitar que informações sejam vistas antes do lançamento oficial evitando assim geração de inconsistências.

Insecure Direct Object Reference - IDOR

Muitas vezes objetos e dados são referenciados através de IDs. Estes IDs podem possuir um grau de entropia baixo para sua geração(incrementando de um em um) ou podem ser gerados de forma pseudo-aleatória(GUID). Estes objetos e dados devem sempre estar protegidos através de um componente de autorização verificando sempre se o usuário que esta tentando acessar o recurso pode visualizar o conteúdo. Quando este componente não existe, ou não esta validando corretamente, informações sensíveis podem estar sendo exibidas a usuários que não deveriam estar às visualizando, conforme o exemplo de URL abaixo:

http://example.com/confidentialDoc1234

Este tipo de URL deve sempre validar as credenciais no lado do servidor e se o usuário logado possui autorização de visualizar a página.

Vulnerabilidades em ações de multi-estágios

Em casos em que existem multiplas etapas para executar ações, como por exemplo realizar um pedido, ou compra, o valor deve ser validado em todas as etapas. O desenvolvedor não deve nunca confiar que, dado que o usuário chegou a um passo, os passos anteriores já foram validados e checados e sendo assim algo que não deve se preocupar.

Falta de restrições entre verbos HTTP

Existem métodos e endpoints que executam ações sensíveis, mas que retornam também informações sensíveis quando recebem os parâmetros e os verbos corretos. Entretanto se utilizados verbos diferentes, com os mesmos parâmetros, servidores que não possuem as devidas validações podem mesmo assim trazer respostas e realizar ações. Por exemplo:

POST /createAdmin?user=admin&pass=12345
...(HTTP Headers)
"user": "attacker"


Como o usuário logado é um atacante e não possui privilégios de criação de admins, o POST retorna como resposta um código 403 Forbidden.

HEAD /createAdmin?user=admin&pass=12345
...(HTTP Headers)
"user": "attacker"


Porém em casos de que o servidor não valida os verbos utilizados, esta chamada acima talvez possa ser e ser executada. Sempre mantenha dos verbos e dos tipos de ações que cada um pode realizar não os deixando de forma genérica.

Controles de acesso baseado em parâmetros

É extremamente comum aplicações confiarem nos parâmetros passados ao servidor para validar e checar se ações podem ser executadas. Isto é uma das formas mais primárias de ataque e manipulação utilizada por adversários que tentam explorar aplicações. É o primeiro escopo explorado. Algumas delas seriam:
  • Controles de acesso baseado em parâmetro

    http://example.com/confidentialDoc1234.pdf?&isAdmin=true

    http://example.com/adminPage?&isAdmin=true

    Este tipo de controle pode ser explorado para realizar as mais diversas ações de um sistema, desde visualização até modificações de pontos importantes do sistema. Uma simples mudança na flag isAdmin pode permitir o/a acesso/ação a uma área restrita do sistema.

  • Controles de acesso baseado no header Referer

    http://example.com/confidentialDoc1234.pdf?&isAdmin=true

    Referer: example.com/viewer


    A resposta deste request acima será 403 pois o referer esta apontando para uma página de um usuário que possui apenas privilégios de visualizador.

    http://example.com/confidentialDoc1234.pdf?&isAdmin=true

    Referer: example.com/admin


    Entretanto se mudarmos o parâmetro para uma página referenciando usuários do tipo admin a visualização do documento será permitada e retornará com sucesso a informação.

Log e alerte

Neste post vimos um pouco sobre ataques e vulnerabildiades em autenticação, controle de acesso e sessão. É de extrema importância que, para cada uma destas acções críticas, exista um monitoramento e um controle. Somente assim será possível tanto detectar como tomar as devidas ações de mitigação para evitar novos eventos no futuro. Um log para cada ação crítica realizada pode entregar muito e ajudaria bastante em uma investigação de um possível ataque.

Para cada um dos tópicos demonstrado aqui é possível encontrar mais outras "mil possibilidades" de explorar vulnerabilidades. O objetivo deste documento era dar apenas uma perspectiva e fazer os leitores entenderem como ações de atacantes que envolvem justamente estas partes críticas do sistema podem causar uma série de problemas se não forem mitigadas de forma correta por estes mesmos controles.

@soareswallace