Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Criando mecanismos de autenticação seguros

Criando mecanismos de autenticação seguros

Uma das partes mais básicas de um sistema é seu processo de login. E por ser algo que não agrega valor direto ao negócio, acabamos não gastando o tempo necessário para criar um fluxo realmente seguro, fazendo com que ele se torne o principal vetor de ataques de nossa aplicação. Iremos aprender como criar mecanismos seguros de autenticação, utilizando CSRF de forma correta, CAPTCHA, duplo fator de autenticação, prevenção à enumeração de usuários e autenticação em APIs. Veremos também diversas dicas de como implementar as arriscadas (mas muitas vezes necessárias) funções 'Permanecer logado' e 'Esqueci a senha'.

Avatar for Vinícius Campitelli

Vinícius Campitelli

October 19, 2019
Tweet

More Decks by Vinícius Campitelli

Other Decks in Technology

Transcript

  1. QUEM SOU EU? QUEM SOU EU? Vinícius Campitelli Membro do

    Sócio-fundador do GitHub/Twitter: Slides: PHPSP Curseduca @vcampitelli viniciuscampitelli.com 2
  2. AGENDA AGENDA Protegendo CSRF de forma correta; CAPTCHA; Duplo fator

    de autenticação; Prevenção à enumeração de usuários; Funcionalidade "Permanecer logado"; Funcionalidade "Esqueci a senha". Login via terceiros; Autenticação em APIs. 3
  3. O QUE É NA PRÁTICA? O QUE É NA PRÁTICA?

    Imagine que você esteja logado em um site site1.com 4 . 2
  4. O QUE É NA PRÁTICA? O QUE É NA PRÁTICA?

    Imagine que você esteja logado em um site site1.com Então acessa o site site2.com 4 . 2
  5. O QUE É NA PRÁTICA? O QUE É NA PRÁTICA?

    Imagine que você esteja logado em um site site1.com Então acessa o site site2.com E no site site2.com, há uma requisição POST site1.com/transferir? conta=1234&valor=1000 4 . 2
  6. O QUE É NA PRÁTICA? O QUE É NA PRÁTICA?

    Imagine que você esteja logado em um site site1.com Então acessa o site site2.com E no site site2.com, há uma requisição POST site1.com/transferir? conta=1234&valor=1000 Como você está autenticado no site1, essa requisição será válida 4 . 2
  7. O QUE É NA PRÁTICA? O QUE É NA PRÁTICA?

    Imagine que você esteja logado em um site site1.com Então acessa o site site2.com E no site site2.com, há uma requisição POST site1.com/transferir? conta=1234&valor=1000 Como você está autenticado no site1, essa requisição será válida E você irá perder seu precioso dinheiro! 4 . 2
  8. Para garantir que um atacante não faça um usuário passar-se

    por ele Mas por que eu preciso disso na tela de login? 4 . 3
  9. COMO SE PROTEGER? COMO SE PROTEGER? Crie uma sessão "falsa"

    Gere um token para ele e guarde-o nessa sessão 4 . 4
  10. COMO SE PROTEGER? COMO SE PROTEGER? Crie uma sessão "falsa"

    Gere um token para ele e guarde-o nessa sessão Coloque esse token junto da requisição (em campos do formulário ou cabeçalhos do AJAX) 4 . 4
  11. COMO SE PROTEGER? COMO SE PROTEGER? Crie uma sessão "falsa"

    Gere um token para ele e guarde-o nessa sessão Coloque esse token junto da requisição (em campos do formulário ou cabeçalhos do AJAX) Na página que recebe a ação de login, verifique se o token enviado é o mesmo da sessão 4 . 4
  12. COMO SE PROTEGER? COMO SE PROTEGER? Crie uma sessão "falsa"

    Gere um token para ele e guarde-o nessa sessão Coloque esse token junto da requisição (em campos do formulário ou cabeçalhos do AJAX) Na página que recebe a ação de login, verifique se o token enviado é o mesmo da sessão Se quiser, verifique também o cabeçalho Referer (ou Origin) da requisição para garantir que a origem é do seu site 4 . 4
  13. PREMISSAS E RECOMENDAÇÕES PREMISSAS E RECOMENDAÇÕES O token não pode

    se repetir entre usuários diferentes, então é importante utilizar um (Cryptographically Secure Pseudo-Random Number Generator) CSPRNG 4 . 5
  14. PREMISSAS E RECOMENDAÇÕES PREMISSAS E RECOMENDAÇÕES O token não pode

    se repetir entre usuários diferentes, então é importante utilizar um (Cryptographically Secure Pseudo-Random Number Generator) Não pode ser muito pequeno (para evitar brute force) CSPRNG 4 . 5
  15. PREMISSAS E RECOMENDAÇÕES PREMISSAS E RECOMENDAÇÕES O token não pode

    se repetir entre usuários diferentes, então é importante utilizar um (Cryptographically Secure Pseudo-Random Number Generator) Não pode ser muito pequeno (para evitar brute force) Não pode aparecer nos logs do servidor CSPRNG 4 . 5
  16. PREMISSAS E RECOMENDAÇÕES PREMISSAS E RECOMENDAÇÕES O token não pode

    se repetir entre usuários diferentes, então é importante utilizar um (Cryptographically Secure Pseudo-Random Number Generator) Não pode ser muito pequeno (para evitar brute force) Não pode aparecer nos logs do servidor Não pode estar na URL CSPRNG 4 . 5
  17. PREMISSAS E RECOMENDAÇÕES PREMISSAS E RECOMENDAÇÕES (CONTINUAÇÃO) (CONTINUAÇÃO) Você pode

    gerar tokens a cada requisição ao invés de um por sessão, mas isso interfere na usabilidade do sistema (por exemplo, o botão "Voltar" do navegador irá causar uma falha de CSRF) 4 . 6
  18. PREMISSAS E RECOMENDAÇÕES PREMISSAS E RECOMENDAÇÕES (CONTINUAÇÃO) (CONTINUAÇÃO) Você pode

    gerar tokens a cada requisição ao invés de um por sessão, mas isso interfere na usabilidade do sistema (por exemplo, o botão "Voltar" do navegador irá causar uma falha de CSRF) Se você quiser uma abordagem stateless, pode gerar um token criptografado com o Session ID do usuário e um timestamp, por exemplo 4 . 6
  19. REFERÊNCIAS REFERÊNCIAS BIBLIOTECAS BIBLIOTECAS OWASP CheatSheet de prevenção de CSRF

    Paper "Robust Defenses for Cross-Site Request Forgery" de Stanford symfony/security-csrf paragonie/anti-csrf 4 . 7
  20. HOTP HOTP é um algoritmo baseado em que gera uma

    senha a partir de uma chave HMAC-based One-Time Password HMAC 6 . 2
  21. HOTP HOTP é um algoritmo baseado em que gera uma

    senha a partir de uma chave Para garantir a unicidade (afinal, há One-Time no nome), é incrementado um contador a cada geração/checagem do valor HMAC-based One-Time Password HMAC 6 . 2
  22. TOTP TOTP é uma extensão do HOTP, que utiliza o

    horário atual ao invés do contador para a unicidade Time-based One-Time Password 6 . 3
  23. TOTP TOTP é uma extensão do HOTP, que utiliza o

    horário atual ao invés do contador para a unicidade Geralmente, há uma janela de 30 segundos de validade da senha Time-based One-Time Password 6 . 3
  24. public function __construct() { $this->authenticator = new \Sonata\GoogleAuthenticator\G $this->secret =

    getAuthenticatorSecretFromSomewhere(); } public function check(string $code) : bool { return $this->authenticator->checkCode($this->secret, $c } public fuction generateSecret() : string { return $this->authenticator->generateSecret() 6 . 5
  25. BLOQUEIE O USUÁRIO APÓS ALGUMAS TENTATIVAS BLOQUEIE O USUÁRIO APÓS

    ALGUMAS TENTATIVAS INVÁLIDAS DO TOKEN DO 2FA! INVÁLIDAS DO TOKEN DO 2FA! 6 . 6
  26. Tokens de 6 dígitos possuem 1.000.000 de combinações (000000 -

    999999) Se um atacante fizer 1 requisição por segundo ao seu sistema, ele irá demorar 1 milhão de segundos para testar todas as combinações possíveis 6 . 7
  27. Tokens de 6 dígitos possuem 1.000.000 de combinações (000000 -

    999999) Se um atacante fizer 1 requisição por segundo ao seu sistema, ele irá demorar 1 milhão de segundos para testar todas as combinações possíveis 1000000 / 86400 = 11.574074074 6 . 7
  28. Tokens de 6 dígitos possuem 1.000.000 de combinações (000000 -

    999999) Se um atacante fizer 1 requisição por segundo ao seu sistema, ele irá demorar 1 milhão de segundos para testar todas as combinações possíveis 1000000 / 86400 = 11.574074074 Ou seja, o token será quebrado em menos de 12 dias 6 . 7
  29. Tokens de 6 dígitos possuem 1.000.000 de combinações (000000 -

    999999) Se um atacante fizer 1 requisição por segundo ao seu sistema, ele irá demorar 1 milhão de segundos para testar todas as combinações possíveis 1000000 / 86400 = 11.574074074 Ou seja, o token será quebrado em menos de 12 dias Mas que atacante só faz 1 requisição por segundo? 6 . 7
  30. REFERÊNCIAS, BIBLIOTECAS E SOLUÇÕES REFERÊNCIAS, BIBLIOTECAS E SOLUÇÕES Why You

    Don't Need 2 Factor Authentication SMS-based two-factor authentication is not safe sonata-project/google-authenticator twilio/authy-php Twilio SMS Nexmo SMS 6 . 8
  31. O que um sistema que rode o código a seguir

    pode dar de informação a um atacante? 7 . 2
  32. public function login(string $username, string $password) : { $user =

    $this->findByUsername($username); if (! $user) { return false; } return $this->verifyPassword($password, $user->getPasswo } 7 . 3
  33. É possível saber que usuários existem em sua aplicação através

    de timing attack Modifique o código para que a custosa função verifyPassword seja sempre invocada! 7 . 4
  34. public function login(string $username, string $password) : { $storedPassword =

    $this->generateFakePassword(); $user = $this->findByUsername($username); if ($user) { $storedPassword = $user->getPassword(); } return ($this->verifyPassword($password, $storedPassword && ($user !== null); } 7 . 5
  35. Será que não estamos exagerando? É realmente possível ver essa

    diferença? Vamos testar, então! Executando os scripts login-user-enumeration.php e login-user-enumeration-fixed.php 7 . 6
  36. SOLUÇÃO MAIS SIMPLES SOLUÇÃO MAIS SIMPLES Gerar um token único

    Guardá-lo no cookie do browser do usuário 8 . 2
  37. SOLUÇÃO MAIS SIMPLES SOLUÇÃO MAIS SIMPLES Gerar um token único

    Guardá-lo no cookie do browser do usuário Salvar esse token em um banco de dados relacionando ao usuário 8 . 2
  38. SOLUÇÃO MAIS SIMPLES SOLUÇÃO MAIS SIMPLES Gerar um token único

    Guardá-lo no cookie do browser do usuário Salvar esse token em um banco de dados relacionando ao usuário Sempre que é feito o acesso à tela de login, comparar os tokens 8 . 2
  39. CUIDADOS CUIDADOS Garanta que o token será único para o

    usuário e não previsível (novamente, use ) CSPRNG 8 . 3
  40. CUIDADOS CUIDADOS Garanta que o token será único para o

    usuário e não previsível (novamente, use ) Faça comparações que tenham tempo fixo para prevenir timing attacks (por exemplo, hash_equals()) CSPRNG 8 . 3
  41. CUIDADOS CUIDADOS Garanta que o token será único para o

    usuário e não previsível (novamente, use ) Faça comparações que tenham tempo fixo para prevenir timing attacks (por exemplo, hash_equals()) Precisa ser eficiente, para não permitir CSPRNG DoS 8 . 3
  42. 1. Prefixe o token com um identificador (NÃO use diretamente

    o ID do usuário) $identifier = hash('sha256', $userId); // 64 bytes $token = bin2hex(random_bytes(32)); // 64 bytes $cookie = $identifier . $token; 8 . 5
  43. 2. Crie uma tabela no banco de dados com o

    identificador acima e somente o hash do token ao invés dele CREATE TABLE `rememberme_tokens` ( `id` int unsigned AUTO_INCREMENT, `identifier` char(64) NOT NULL, `token_hash` char(128) NOT NULL, PRIMARY KEY (`id`) ) $hashedToken = hash('sha512', $token); $pdo->prepare('INSERT INTO rememberme_tokens (NULL, ?, ?)') ->execute([$identifier, $hashedToken]); 8 . 6
  44. 3. Ao consultar o banco, utilize apenas o identificador $query

    = $pdo->prepare( 'SELECT `token_hash` FROM `rememberme_tokens` WHERE `identifier` = ? LIMIT 1' ); $hashFromDatabase = $query->fetch(PDO::FETCH_COLUMN); 8 . 7
  45. 4. Faça o hash do token informado no cookie do

    usuário e compare-o com o que está no banco (com hash_equals()) $hashedToken = hash('sha512', substr($cookie, 64)); if (hash_equals($hashedToken, $hashFromDatabase)) { redirectToHome(); } else { redirectToLogin(); } 8 . 8
  46. REFERÊNCIA E BIBLIOTECA REFERÊNCIA E BIBLIOTECA "Remember Me" - Long-Term

    Persistent Authentication (Paragon IE) psecio/gatekeeper 8 . 9
  47. PRECAUÇÕES PRECAUÇÕES Perguntas secretas estão cada vez menos secretas por

    causa das redes sociais Emails não são sempre encriptados 9 . 2
  48. PRECAUÇÕES PRECAUÇÕES Perguntas secretas estão cada vez menos secretas por

    causa das redes sociais Emails não são sempre encriptados Emails podem não chegar 9 . 2
  49. PRECAUÇÕES PRECAUÇÕES Perguntas secretas estão cada vez menos secretas por

    causa das redes sociais Emails não são sempre encriptados Emails podem não chegar SMS não são confiáveis 9 . 2
  50. PREPARE-SE! PREPARE-SE! Realmente avalie se seu sistema precisa dessa funcionalidade

    automática NÃO crie uma nova senha e envie por email 9 . 3
  51. PREPARE-SE! PREPARE-SE! Realmente avalie se seu sistema precisa dessa funcionalidade

    automática NÃO crie uma nova senha e envie por email NÃO mande a senha em texto plano por email 9 . 3
  52. PREPARE-SE! PREPARE-SE! Realmente avalie se seu sistema precisa dessa funcionalidade

    automática NÃO crie uma nova senha e envie por email NÃO mande a senha em texto plano por email (o quêêê?????) 9 . 3
  53. PREPARE-SE! PREPARE-SE! Realmente avalie se seu sistema precisa dessa funcionalidade

    automática NÃO crie uma nova senha e envie por email NÃO mande a senha em texto plano por email (o quêêê?????) Se for fornecido um usuário que não existe na base, não o avise! 9 . 3
  54. TENTATIVA DE TENTATIVA DE SOLUÇÃO SOLUÇÃO Utilize a do token

    descrita no slide de "Permanecer logado" mesma abordagem 9 . 4
  55. TENTATIVA DE TENTATIVA DE SOLUÇÃO SOLUÇÃO Utilize a do token

    descrita no slide de "Permanecer logado" Coloque um tempo limite para expiração do token mesma abordagem 9 . 4
  56. TENTATIVA DE TENTATIVA DE SOLUÇÃO SOLUÇÃO Utilize a do token

    descrita no slide de "Permanecer logado" Coloque um tempo limite para expiração do token Envie o código para o usuário (se for por email, criptografe!) mesma abordagem 9 . 4
  57. REFERÊNCIAS E BIBLIOTECA REFERÊNCIAS E BIBLIOTECA Account Recovery (Paragon IE)

    Untangling the Forget-Me Knot: Secure Account Recovery Made Simple paragonie/gpg-mailer 9 . 5
  58. REFERÊNCIAS E BIBLIOTECAS REFERÊNCIAS E BIBLIOTECAS Facebook SDK - Login

    Google Login TwitterOAuth Login GitHub Login openid/php-openid Auth0 10 . 3
  59. DICAS DICAS Use HTTPS sempre (♥ ) Não crie seu

    próprio sistema de autenticação, utilize um protocolo já conhecido ( , , entre outros) Let's Encrypt OpenID OAuth 2.0 11 . 2
  60. DICAS DICAS Use HTTPS sempre (♥ ) Não crie seu

    próprio sistema de autenticação, utilize um protocolo já conhecido ( , , entre outros) Para geração dos identificadores do usuário (por exemplo, client secret no OAuth 2) utilize Let's Encrypt OpenID OAuth 2.0 CSPRNG 11 . 2
  61. DICAS DICAS (CONTINUAÇÃO) (CONTINUAÇÃO) Para tokens, utilize ou Se for

    usar JWT, garanta que seu sistema não permita um algorithm=none JWT Paseto 11 . 3
  62. DICAS DICAS (CONTINUAÇÃO) (CONTINUAÇÃO) Para tokens, utilize ou Se for

    usar JWT, garanta que seu sistema não permita um algorithm=none Mesmo se usar um , não deixe seus microserviços sem autenticação. Repasse o token para todos! JWT Paseto API Gateway 11 . 3
  63. REFERÊNCIAS REFERÊNCIAS BIBLIOTECAS BIBLIOTECAS Critical vulnerabilities in JSON Web Token

    libraries Token Based Authentication Made Easy lcobucci/jwt thephpleague/oauth2-server 11 . 4