Cognito User Pools

Aprenda hacking na AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras maneiras de apoiar o HackTricks:

Informações Básicas

Um pool de usuários é um diretório de usuários no Amazon Cognito. Com um pool de usuários, seus usuários podem fazer login em seu aplicativo da web ou móvel por meio do Amazon Cognito, ou federar por meio de um provedor de identidade de terceiros (IdP). Seus usuários façam login diretamente ou por meio de um terceiro, todos os membros do pool de usuários têm um perfil de diretório ao qual você pode acessar por meio de um SDK.

Os pools de usuários fornecem:

  • Serviços de registro e login.

  • Uma interface de usuário da web integrada e personalizável para fazer login de usuários.

  • Login social com Facebook, Google, Login com Amazon e Login com Apple, e por meio de provedores de identidade SAML e OIDC do seu pool de usuários.

  • Gerenciamento de diretório de usuários e perfis de usuários.

  • Recursos de segurança, como autenticação multifator (MFA), verificações de credenciais comprometidas, proteção contra takeover de conta e verificação por telefone e e-mail.

  • Fluxos de trabalho personalizados e migração de usuários por meio de gatilhos AWS Lambda.

O código-fonte das aplicações geralmente também contém o ID do pool de usuários e o ID do aplicativo cliente, (e às vezes o segredo do aplicativo?) que são necessários para um usuário fazer login em um Pool de Usuários do Cognito.

Ataques Potenciais

  • Registro: Por padrão, um usuário pode se registrar, então ele poderia criar um usuário para si mesmo.

  • Enumeração de Usuários: A funcionalidade de registro pode ser usada para encontrar nomes de usuários que já existem. Essas informações podem ser úteis para o ataque de força bruta.

  • Ataque de Força Bruta no Login: Na seção de Autenticação você tem todos os métodos que um usuário tem para fazer login, você poderia tentar força bruta para encontrar credenciais válidas.

Ferramentas para Pentesting

  • Pacu, o framework de exploração da AWS, agora inclui os módulos "cognito__enum" e "cognito__attack" que automatizam a enumeração de todos os ativos do Cognito em uma conta e sinalizam configurações fracas, atributos de usuário usados para controle de acesso, etc., e também automatizam a criação de usuários (incluindo suporte a MFA) e escalonamento de privilégios com base em atributos personalizáveis modificáveis, credenciais de pool de identidade utilizáveis, funções assumíveis em tokens de id, etc.

Para uma descrição das funções dos módulos, consulte a parte 2 do post do blog. Para instruções de instalação, consulte a página principal do Pacu.

Uso

Uso de ataque cognito__attack de amostra para tentar a criação de usuários e todos os vetores de escalonamento de privilégios contra um pool de identidade e cliente de pool de usuários específicos:

Pacu (new:test) > run cognito__attack --username randomuser --email XX+sdfs2@gmail.com --identity_pools
us-east-2:a06XXXXX-c9XX-4aXX-9a33-9ceXXXXXXXXX --user_pool_clients
59f6tuhfXXXXXXXXXXXXXXXXXX@us-east-2_0aXXXXXXX

Exemplo de uso do cognito__enum para reunir todos os grupos de usuários, clientes de grupos de usuários, pools de identidade, usuários, etc. visíveis na conta AWS atual:

Pacu (new:test) > run cognito__enum
  • Cognito Scanner é uma ferramenta CLI em python que implementa diferentes ataques no Cognito, incluindo a criação indesejada de contas e oráculo de contas.

Instalação

$ pip install cognito-scanner

Uso

$ cognito-scanner --help

Para mais informações, consulte https://github.com/padok-team/cognito-scanner

Registro

Os Grupos de Usuários permitem, por padrão, registrar novos usuários.

aws cognito-idp sign-up --client-id <client-id> \
--username <username> --password <password> \
--region <region> --no-sign-request

Se qualquer pessoa pode se registrar

Você pode encontrar um erro indicando que você precisa fornecer mais detalhes sobre o usuário:

An error occurred (InvalidParameterException) when calling the SignUp operation: Attributes did not conform to the schema: address: The attribute is required

Você pode fornecer os detalhes necessários com um JSON, como:

--user-attributes '[{"Name": "email", "Value": "carlospolop@gmail.com"}, {"Name":"gender", "Value": "M"}, {"Name": "address", "Value": "street"}, {"Name": "custom:custom_name", "Value":"supername&\"*$"}]'

Você também pode usar essa funcionalidade para enumerar usuários existentes. Esta é a mensagem de erro quando um usuário já existe com esse nome:

An error occurred (UsernameExistsException) when calling the SignUp operation: User already exists

Observe no comando anterior como os atributos personalizados começam com "custom:". Saiba também que ao se registrar, você não pode criar novos atributos personalizados para o usuário. Você só pode atribuir valor aos atributos padrão (mesmo que não sejam obrigatórios) e aos atributos personalizados especificados.

Ou apenas para testar se um ID de cliente existe. Este é o erro se o ID do cliente não existir:

An error occurred (ResourceNotFoundException) when calling the SignUp operation: User pool client 3ig612gjm56p1ljls1prq2miut does not exist.

Se apenas o administrador pode registrar usuários

Você encontrará esse erro e não poderá registrar ou enumerar usuários:

An error occurred (NotAuthorizedException) when calling the SignUp operation: SignUp is not permitted for this user pool

Verificação de Registro

O Cognito permite verificar um novo usuário verificando seu e-mail ou número de telefone. Portanto, ao criar um usuário, geralmente será necessário pelo menos o nome de usuário e senha e o e-mail e/ou número de telefone. Basta definir um que você controle para receber o código e verificar sua conta de usuário recém-criada como este:

aws cognito-idp confirm-sign-up --client-id <cliet_id> \
--username aasdasd2 --confirmation-code <conf_code> \
--no-sign-request --region us-east-1

Mesmo que pareça que você pode usar o mesmo e-mail e número de telefone, quando precisar verificar o usuário criado, o Cognito reclamará sobre o uso das mesmas informações e não permitirá que você verifique a conta.

Escalação de Privilégios / Atualização de Atributos

Por padrão, um usuário pode modificar o valor de seus atributos com algo como:

aws cognito-idp update-user-attributes \
--region us-east-1 --no-sign-request \
--user-attributes Name=address,Value=street \
--access-token <access token>

Privilégio de atributo personalizado

Você pode encontrar atributos personalizados sendo usados (como isAdmin), pois por padrão você pode alterar os valores de seus próprios atributos, você pode ser capaz de aumentar os privilégios alterando o valor você mesmo!

Privilégio de modificação de e-mail/nome de usuário

Você pode usar isso para modificar o e-mail e o número de telefone de um usuário, mas então, mesmo que a conta permaneça como verificada, esses atributos são definidos como não verificados (você precisa verificá-los novamente).

Você não poderá fazer login com e-mail ou número de telefone até verificá-los, mas você será capaz de fazer login com o nome de usuário. Observe que mesmo que o e-mail tenha sido modificado e não verificado, ele aparecerá no Token de ID dentro do campo email e o campo email_verified será falso, mas se o aplicativo não estiver verificando isso, você pode se passar por outros usuários.

Além disso, observe que você pode colocar qualquer coisa dentro do campo name apenas modificando o atributo de nome. Se um aplicativo estiver verificando aquele campo por algum motivo em vez do email (ou qualquer outro atributo), você pode se passar por outros usuários.

De qualquer forma, se por algum motivo você alterou seu e-mail, por exemplo, para um novo, você pode confirmar o e-mail com o código que você recebeu nesse endereço de e-mail:

aws cognito-idp verify-user-attribute \
--access-token <access_token> \
--attribute-name email --code <code> \
--region <region> --no-sign-request

Utilize phone_number em vez de email para alterar/verificar um novo número de telefone.

O administrador também pode habilitar a opção de login com um nome de usuário preferido pelo usuário. Observe que você não poderá alterar esse valor para qualquer nome de usuário ou preferred_username que já esteja em uso para se passar por um usuário diferente.

Recuperar/Alterar Senha

É possível recuperar uma senha apenas sabendo o nome de usuário (ou email ou telefone são aceitos) e tendo acesso a ele, pois um código será enviado lá:

aws cognito-idp forgot-password \
--client-id <client_id> \
--username <username/email/phone> --region <region>

A resposta do servidor sempre será positiva, como se o nome de usuário existisse. Você não pode usar este método para enumerar usuários.

Com o código, você pode alterar a senha com:

aws cognito-idp confirm-forgot-password \
--client-id <client_id> \
--username <username> \
--confirmation-code <conf_code> \
--password <pwd> --region <region>

Para alterar a senha, você precisa saber a senha anterior:

aws cognito-idp change-password \
--previous-password <value> \
--proposed-password <value> \
--access-token <value>

Autenticação

Um pool de usuários suporta diferentes formas de autenticação. Se você tiver um nome de usuário e senha, também existem métodos diferentes suportados para fazer login. Além disso, quando um usuário é autenticado no Pool, 3 tipos de tokens são fornecidos: O Token de ID, o Token de Acesso e o Token de Atualização.

  • Token de ID: Ele contém informações sobre a identidade do usuário autenticado, como nome, e-mail e número de telefone. O token de ID também pode ser usado para autenticar usuários em seus servidores de recursos ou aplicativos de servidor. Você deve verificar a assinatura do token de ID antes de confiar em qualquer informação dentro do token de ID se você o usar em aplicativos externos.

  • O Token de ID é o token que contém os valores dos atributos do usuário, inclusive os personalizados.

  • Token de Acesso: Ele contém informações sobre o usuário autenticado, uma lista dos grupos do usuário e uma lista de escopos. O objetivo do token de acesso é autorizar operações de API no contexto do usuário no pool de usuários. Por exemplo, você pode usar o token de acesso para conceder ao seu usuário acesso para adicionar, alterar ou excluir atributos do usuário.

  • Token de Atualização: Com tokens de atualização, você pode obter novos Tokens de ID e Tokens de Acesso para o usuário até que o token de atualização seja inválido. Por padrão, o token de atualização expira 30 dias após seu usuário do aplicativo entrar no seu pool de usuários. Quando você cria um aplicativo para o seu pool de usuários, você pode definir a expiração do token de atualização do aplicativo para qualquer valor entre 60 minutos e 10 anos.

ADMIN_NO_SRP_AUTH & ADMIN_USER_PASSWORD_AUTH

Este é o fluxo de autenticação do lado do servidor:

  • O aplicativo do lado do servidor chama a operação de API AdminInitiateAuth (em vez de InitiateAuth). Esta operação requer credenciais da AWS com permissões que incluem cognito-idp:AdminInitiateAuth e cognito-idp:AdminRespondToAuthChallenge. A operação retorna os parâmetros de autenticação necessários.

  • Depois que o aplicativo do lado do servidor tem os parâmetros de autenticação, ele chama a operação de API AdminRespondToAuthChallenge. A operação de API AdminRespondToAuthChallenge só tem sucesso quando você fornece credenciais da AWS.

Este método NÃO está habilitado por padrão.

Para fazer login, você precisa saber:

  • ID do pool de usuários

  • ID do cliente

  • nome de usuário

  • senha

  • segredo do cliente (apenas se o aplicativo estiver configurado para usar um segredo)

Para poder fazer login com este método, o aplicativo deve permitir o login com ALLOW_ADMIN_USER_PASSWORD_AUTH. Além disso, para realizar esta ação, você precisa de credenciais com as permissões cognito-idp:AdminInitiateAuth e cognito-idp:AdminRespondToAuthChallenge

aws cognito-idp admin-initiate-auth \
--client-id <client-id> \
--auth-flow ADMIN_USER_PASSWORD_AUTH \
--region <region> \
--auth-parameters 'USERNAME=<username>,PASSWORD=<password>,SECRET_HASH=<hash_if_needed>'
--user-pool-id "<pool-id>"

# Check the python code to learn how to generate the hsecret_hash
Código para Login

```python import boto3 import botocore import hmac import hashlib import base64

client_id = "" user_pool_id = "" client_secret = "" username = "" password = ""

boto_client = boto3.client('cognito-idp', region_name='us-east-1')

def get_secret_hash(username, client_id, client_secret): key = bytes(client_secret, 'utf-8') message = bytes(f'{username}{client_id}', 'utf-8') return base64.b64encode(hmac.new(key, message, digestmod=hashlib.sha256).digest()).decode()

If the Client App isn't configured to use a secret

just delete the line setting the SECRET_HASH

def login_user(username_or_alias, password, client_id, client_secret, user_pool_id): try: return boto_client.admin_initiate_auth( UserPoolId=user_pool_id, ClientId=client_id, AuthFlow='ADMIN_USER_PASSWORD_AUTH', AuthParameters={ 'USERNAME': username_or_alias, 'PASSWORD': password, 'SECRET_HASH': get_secret_hash(username_or_alias, client_id, client_secret) } ) except botocore.exceptions.ClientError as e: return e.response

print(login_user(username, password, client_id, client_secret, user_pool_id))

</details>

### AUTENTICAÇÃO\_DE\_USUÁRIO\_E\_SENHA

Este método é outro fluxo de autenticação simples e **tradicional de usuário e senha**. É recomendado **migrar um método de autenticação tradicional** para o Cognito e **recomendado** então **desabilitá-lo** e **usar** o método **ALLOW\_USER\_SRP\_AUTH** em vez disso (pois esse nunca envia a senha pela rede).\
Este **método NÃO está habilitado** por padrão.

A principal **diferença** com o **método de autenticação anterior** no código é que você **não precisa saber o ID do pool de usuários** e que você **não precisa de permissões extras** no Cognito User Pool.

Para **fazer login** você **precisa** saber:

* ID do cliente
* nome de usuário
* senha
* segredo do cliente (apenas se o aplicativo estiver configurado para usar um segredo)

<div data-gb-custom-block data-tag="hint" data-style='info'>

Para **poder fazer login com este método**, a aplicação deve permitir o login com ALLOW\_USER\_PASSWORD\_AUTH.

</div>

```python
aws cognito-idp initiate-auth  --client-id <client-id> \
--auth-flow USER_PASSWORD_AUTH --region <region> \
--auth-parameters 'USERNAME=<username>,PASSWORD=<password>,SECRET_HASH=<hash_if_needed>'

# Check the python code to learn how to generate the secret_hash

REFRESH_TOKEN_AUTH & REFRESH_TOKEN

Este método será sempre válido (não pode ser desativado), mas você precisa ter um token de atualização válido.

aws cognito-idp initiate-auth \
--client-id 3ig6h5gjm56p1ljls1prq2miut \
--auth-flow REFRESH_TOKEN_AUTH \
--region us-east-1 \
--auth-parameters 'REFRESH_TOKEN=<token>'

Última actualización