mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-01-08 19:30:51 -08:00
Recreating repository history for branch master
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
# AWS - Cognito Enum
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="../../../../.gitbook/assets/image (1) (1) (1) (1).png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../.gitbook/assets/image (1) (1) (1) (1).png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../../../.gitbook/assets/image (2) (1).png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../../.gitbook/assets/image (2) (1).png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Support HackTricks</summary>
|
||||
|
||||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
||||
## Cognito
|
||||
|
||||
Amazon Cognito is utilized for **authentication, authorization, and user management** in web and mobile applications. It allows users the flexibility to sign in either directly using a **user name and password** or indirectly through a **third party**, including Facebook, Amazon, Google, or Apple.
|
||||
|
||||
Central to Amazon Cognito are two primary components:
|
||||
|
||||
1. **User Pools**: These are directories designed for your app users, offering **sign-up and sign-in functionalities**.
|
||||
2. **Identity Pools**: These pools are instrumental in **authorizing users to access different AWS services**. They are not directly involved in the sign-in or sign-up process but are crucial for resource access post-authentication.
|
||||
|
||||
### **User pools**
|
||||
|
||||
To learn what is a **Cognito User Pool check**:
|
||||
|
||||
{% content-ref url="cognito-user-pools.md" %}
|
||||
[cognito-user-pools.md](cognito-user-pools.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### **Identity pools**
|
||||
|
||||
The learn what is a **Cognito Identity Pool check**:
|
||||
|
||||
{% content-ref url="cognito-identity-pools.md" %}
|
||||
[cognito-identity-pools.md](cognito-identity-pools.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## Enumeration
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
# List Identity Pools
|
||||
aws cognito-identity list-identity-pools --max-results 60
|
||||
aws cognito-identity describe-identity-pool --identity-pool-id "eu-west-2:38b294756-2578-8246-9074-5367fc9f5367"
|
||||
aws cognito-identity list-identities --identity-pool-id <ident-pool-id> --max-results 60
|
||||
aws cognito-identity get-identity-pool-roles --identity-pool-id <ident-pool-id>
|
||||
|
||||
# Identities Datasets
|
||||
## Get dataset of identity id (inside identity pool)
|
||||
aws cognito-sync list-datasets --identity-pool-id <ident-pool-id> --identity-id <ident-id>
|
||||
## Get info of the dataset
|
||||
aws cognito-sync describe-dataset --identity-pool-id <value> --identity-id <value> --dataset-name <value>
|
||||
## Get dataset records
|
||||
aws cognito-sync list-records --identity-pool-id <value> --identity-id <value> --dataset-name <value>
|
||||
|
||||
# User Pools
|
||||
## Get pools
|
||||
aws cognito-idp list-user-pools --max-results 60
|
||||
|
||||
## Get users
|
||||
aws cognito-idp list-users --user-pool-id <user-pool-id>
|
||||
|
||||
## Get groups
|
||||
aws cognito-idp list-groups --user-pool-id <user-pool-id>
|
||||
|
||||
## Get users in a group
|
||||
aws cognito-idp list-users-in-group --user-pool-id <user-pool-id> --group-name <group-name>
|
||||
|
||||
## List App IDs of a user pool
|
||||
aws cognito-idp list-user-pool-clients --user-pool-id <user-pool-id>
|
||||
|
||||
## List configured identity providers for a user pool
|
||||
aws cognito-idp list-identity-providers --user-pool-id <user-pool-id>
|
||||
|
||||
## List user import jobs
|
||||
aws cognito-idp list-user-import-jobs --user-pool-id <user-pool-id> --max-results 60
|
||||
|
||||
## Get MFA config of a user pool
|
||||
aws cognito-idp get-user-pool-mfa-config --user-pool-id <user-pool-id>
|
||||
|
||||
## Get risk configuration
|
||||
aws cognito-idp describe-risk-configuration --user-pool-id <user-pool-id>
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
### Identity Pools - Unauthenticated Enumeration
|
||||
|
||||
Just **knowing the Identity Pool ID** you might be able **get credentials of the role associated to unauthenticated** users (if any). [**Check how here**](cognito-identity-pools.md#accessing-iam-roles).
|
||||
|
||||
### User Pools - Unauthenticated Enumeration
|
||||
|
||||
Even if you **don't know a valid username** inside Cognito, you might be able to **enumerate** valid **usernames**, **BF** the **passwords** of even **register a new user** just **knowing the App client ID** (which is usually found in source code). [**Check how here**](cognito-user-pools.md#registration)**.**
|
||||
|
||||
## Privesc
|
||||
|
||||
{% content-ref url="../../aws-privilege-escalation/aws-cognito-privesc.md" %}
|
||||
[aws-cognito-privesc.md](../../aws-privilege-escalation/aws-cognito-privesc.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## Unauthenticated Access
|
||||
|
||||
{% content-ref url="../../aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum.md" %}
|
||||
[aws-cognito-unauthenticated-enum.md](../../aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## Persistence
|
||||
|
||||
{% content-ref url="../../aws-persistence/aws-cognito-persistence.md" %}
|
||||
[aws-cognito-persistence.md](../../aws-persistence/aws-cognito-persistence.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="../../../../.gitbook/assets/image (1) (1) (1) (1).png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../.gitbook/assets/image (1) (1) (1) (1).png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../../../.gitbook/assets/image (2) (1).png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../../.gitbook/assets/image (2) (1).png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Support HackTricks</summary>
|
||||
|
||||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
@@ -0,0 +1,225 @@
|
||||
# Cognito Identity Pools
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="../../../../.gitbook/assets/image (1) (1) (1) (1).png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../.gitbook/assets/image (1) (1) (1) (1).png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../../../.gitbook/assets/image (2) (1).png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../../.gitbook/assets/image (2) (1).png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Support HackTricks</summary>
|
||||
|
||||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
||||
## Basic Information
|
||||
|
||||
Identity pools serve a crucial role by enabling your users to **acquire temporary credentials**. These credentials are essential for accessing various AWS services, including but not limited to Amazon S3 and DynamoDB. A notable feature of identity pools is their support for both anonymous guest users and a range of identity providers for user authentication. The supported identity providers include:
|
||||
|
||||
* Amazon Cognito user pools
|
||||
* Social sign-in options such as Facebook, Google, Login with Amazon, and Sign in with Apple
|
||||
* Providers compliant with OpenID Connect (OIDC)
|
||||
* SAML (Security Assertion Markup Language) identity providers
|
||||
* Developer authenticated identities
|
||||
|
||||
```python
|
||||
# Sample code to demonstrate how to integrate an identity provider with an identity pool can be structured as follows:
|
||||
import boto3
|
||||
|
||||
# Initialize the Amazon Cognito Identity client
|
||||
client = boto3.client('cognito-identity')
|
||||
|
||||
# Assume you have already created an identity pool and obtained the IdentityPoolId
|
||||
identity_pool_id = 'your-identity-pool-id'
|
||||
|
||||
# Add an identity provider to the identity pool
|
||||
response = client.set_identity_pool_roles(
|
||||
IdentityPoolId=identity_pool_id,
|
||||
Roles={
|
||||
'authenticated': 'arn:aws:iam::AWS_ACCOUNT_ID:role/AuthenticatedRole',
|
||||
'unauthenticated': 'arn:aws:iam::AWS_ACCOUNT_ID:role/UnauthenticatedRole',
|
||||
}
|
||||
)
|
||||
|
||||
# Print the response from AWS
|
||||
print(response)
|
||||
```
|
||||
|
||||
### Cognito Sync
|
||||
|
||||
To generate Identity Pool sessions, you first need to **generate and Identity ID**. This Identity ID is the **identification of the session of that user**. These identifications can have up to 20 datasets that can store up to 1MB of key-value pairs.
|
||||
|
||||
This is **useful to keep information of a user** (who will be always using the same Identity ID).
|
||||
|
||||
Moreover, the service **cognito-sync** is the service that allow to **manage and syncronize this information** (in the datasets, sending info in streams and SNSs msgs...).
|
||||
|
||||
### Tools for pentesting
|
||||
|
||||
* [Pacu](https://github.com/RhinoSecurityLabs/pacu), the AWS exploitation framework, now includes the "cognito\_\_enum" and "cognito\_\_attack" modules that automate enumeration of all Cognito assets in an account and flag weak configurations, user attributes used for access control, etc., and also automate user creation (including MFA support) and privilege escalation based on modifiable custom attributes, usable identity pool credentials, assumable roles in id tokens, etc.
|
||||
|
||||
For a description of the modules' functions see part 2 of the [blog post](https://rhinosecuritylabs.com/aws/attacking-aws-cognito-with-pacu-p2). For installation instructions see the main [Pacu](https://github.com/RhinoSecurityLabs/pacu) page.
|
||||
|
||||
#### Usage
|
||||
|
||||
Sample cognito\_\_attack usage to attempt user creation and all privesc vectors against a given identity pool and user pool client:
|
||||
|
||||
```bash
|
||||
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
|
||||
```
|
||||
|
||||
Sample cognito\_\_enum usage to gather all user pools, user pool clients, identity pools, users, etc. visible in the current AWS account:
|
||||
|
||||
```bash
|
||||
Pacu (new:test) > run cognito__enum
|
||||
```
|
||||
|
||||
* [Cognito Scanner](https://github.com/padok-team/cognito-scanner) is a CLI tool in python that implements different attacks on Cognito including unwanted account creation and identity pool escalation.
|
||||
|
||||
#### Installation
|
||||
|
||||
```bash
|
||||
$ pip install cognito-scanner
|
||||
```
|
||||
|
||||
#### Usage
|
||||
|
||||
```bash
|
||||
$ cognito-scanner --help
|
||||
```
|
||||
|
||||
For more information check https://github.com/padok-team/cognito-scanner
|
||||
|
||||
## Accessing IAM Roles
|
||||
|
||||
### Unauthenticated
|
||||
|
||||
The only thing an attacker need to know to **get AWS credentials** in a Cognito app as unauthenticated user is the **Identity Pool ID**, and this **ID must be hardcoded** in the web/mobile **application** for it to use it. An ID looks like this: `eu-west-1:098e5341-8364-038d-16de-1865e435da3b` (it's not bruteforceable).
|
||||
|
||||
{% hint style="success" %}
|
||||
The **IAM Cognito unathenticated role created via is called** by default `Cognito_<Identity Pool name>Unauth_Role`
|
||||
{% endhint %}
|
||||
|
||||
If you find an Identity Pools ID hardcoded and it allows unauthenticated users, you can get AWS credentials with:
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
region = "us-east-1"
|
||||
id_pool_id = 'eu-west-1:098e5341-8364-038d-16de-1865e435da3b'
|
||||
url = f'https://cognito-identity.{region}.amazonaws.com/'
|
||||
headers = {"X-Amz-Target": "AWSCognitoIdentityService.GetId", "Content-Type": "application/x-amz-json-1.1"}
|
||||
params = {'IdentityPoolId': id_pool_id}
|
||||
|
||||
r = requests.post(url, json=params, headers=headers)
|
||||
json_resp = r.json()
|
||||
|
||||
if not "IdentityId" in json_resp:
|
||||
print(f"Not valid id: {id_pool_id}")
|
||||
exit
|
||||
|
||||
IdentityId = r.json()["IdentityId"]
|
||||
|
||||
params = {'IdentityId': IdentityId}
|
||||
|
||||
headers["X-Amz-Target"] = "AWSCognitoIdentityService.GetCredentialsForIdentity"
|
||||
r = requests.post(url, json=params, headers=headers)
|
||||
|
||||
print(r.json())
|
||||
```
|
||||
|
||||
Or you could use the following **aws cli commands**:
|
||||
|
||||
```bash
|
||||
aws cognito-identity get-id --identity-pool-id <identity_pool_id> --no-sign
|
||||
aws cognito-identity get-credentials-for-identity --identity-id <identity_id> --no-sign
|
||||
```
|
||||
|
||||
{% hint style="warning" %}
|
||||
Note that by default an unauthenticated cognito **user CANNOT have any permission, even if it was assigned via a policy**. Check the followin section.
|
||||
{% endhint %}
|
||||
|
||||
### Enhanced vs Basic Authentication flow
|
||||
|
||||
The previous section followed the **default enhanced authentication flow**. This flow sets a **restrictive** [**session policy**](../../aws-basic-information/#session-policies) to the IAM role session generated. This policy will only allow the session to [**use the services from this list**](https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html#access-policies-scope-down-services) (even if the role had access to other services).
|
||||
|
||||
However, there is a way to bypass this, if the **Identity pool has "Basic (Classic) Flow" enabled**, the user will be able to obtain a session using that flow which **won't have that restrictive session policy**.
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
# Get auth ID
|
||||
aws cognito-identity get-id --identity-pool-id <identity_pool_id> --no-sign
|
||||
|
||||
# Get login token
|
||||
aws cognito-identity get-open-id-token --identity-id <identity_id> --no-sign
|
||||
|
||||
# Use login token to get IAM session creds
|
||||
## If you don't know the role_arn use the previous enhanced flow to get it
|
||||
aws sts assume-role-with-web-identity --role-arn "arn:aws:iam::<acc_id>:role/<role_name>" --role-session-name sessionname --web-identity-token <token> --no-sign
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
{% hint style="warning" %}
|
||||
If you receive this **error**, it's because the **basic flow is not enabled (default)**
|
||||
|
||||
`An error occurred (InvalidParameterException) when calling the GetOpenIdToken operation: Basic (classic) flow is not enabled, please use enhanced flow.`
|
||||
{% endhint %}
|
||||
|
||||
Having a set of IAM credentials you should check [which access you have](../../#whoami) and try to [escalate privileges](../../aws-privilege-escalation/).
|
||||
|
||||
### Authenticated
|
||||
|
||||
{% hint style="info" %}
|
||||
Remember that **authenticated users** will be probably granted **different permissions**, so if you can **sign up inside the app**, try doing that and get the new credentials.
|
||||
{% endhint %}
|
||||
|
||||
There could also be **roles** available for **authenticated users accessing the Identity Poo**l.
|
||||
|
||||
For this you might need to have access to the **identity provider**. If that is a **Cognito User Pool**, maybe you can abuse the default behaviour and **create a new user yourself**.
|
||||
|
||||
{% hint style="success" %}
|
||||
The **IAM Cognito athenticated role created via is called** by default `Cognito_<Identity Pool name>Auth_Role`
|
||||
{% endhint %}
|
||||
|
||||
Anyway, the **following example** expects that you have already logged in inside a **Cognito User Pool** used to access the Identity Pool (don't forget that other types of identity providers could also be configured).
|
||||
|
||||
<pre class="language-bash"><code class="lang-bash">aws cognito-identity get-id \
|
||||
--identity-pool-id <identity_pool_id> \
|
||||
--logins cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>=<ID_TOKEN>
|
||||
|
||||
# Get the identity_id from the previous commnad response
|
||||
aws cognito-identity get-credentials-for-identity \
|
||||
--identity-id <identity_id> \
|
||||
--logins cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>=<ID_TOKEN>
|
||||
|
||||
|
||||
# In the IdToken you can find roles a user has access because of User Pool Groups
|
||||
# User the --custom-role-arn to get credentials to a specific role
|
||||
aws cognito-identity get-credentials-for-identity \
|
||||
--identity-id <identity_id> \
|
||||
<strong> --custom-role-arn <role_arn> \
|
||||
</strong> --logins cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>=<ID_TOKEN>
|
||||
</code></pre>
|
||||
|
||||
{% hint style="warning" %}
|
||||
It's possible to **configure different IAM roles depending on the identity provide**r the user is being logged in or even just depending **on the user** (using claims). Therefore, if you have access to different users through the same or different providers, if might be **worth it to login and access the IAM roles of all of them**.
|
||||
{% endhint %}
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="../../../../.gitbook/assets/image (1) (1) (1) (1).png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../.gitbook/assets/image (1) (1) (1) (1).png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../../../.gitbook/assets/image (2) (1).png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../../.gitbook/assets/image (2) (1).png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Support HackTricks</summary>
|
||||
|
||||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
@@ -0,0 +1,529 @@
|
||||
# Cognito User Pools
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="../../../../.gitbook/assets/image (1) (1) (1) (1).png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../.gitbook/assets/image (1) (1) (1) (1).png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../../../.gitbook/assets/image (2) (1).png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../../.gitbook/assets/image (2) (1).png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Support HackTricks</summary>
|
||||
|
||||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
||||
## Basic Information
|
||||
|
||||
A user pool is a user directory in Amazon Cognito. With a user pool, your users can **sign in to your web or mobile app** through Amazon Cognito, **or federate** through a **third-party** identity provider (IdP). Whether your users sign in directly or through a third party, all members of the user pool have a directory profile that you can access through an SDK.
|
||||
|
||||
User pools provide:
|
||||
|
||||
* Sign-up and sign-in services.
|
||||
* A built-in, customizable web UI to sign in users.
|
||||
* Social sign-in with Facebook, Google, Login with Amazon, and Sign in with Apple, and through SAML and OIDC identity providers from your user pool.
|
||||
* User directory management and user profiles.
|
||||
* Security features such as multi-factor authentication (MFA), checks for compromised credentials, account takeover protection, and phone and email verification.
|
||||
* Customized workflows and user migration through AWS Lambda triggers.
|
||||
|
||||
**Source code** of applications will usually also contain the **user pool ID** and the **client application ID**, (and some times the **application secret**?) which are needed for a **user to login** to a Cognito User Pool.
|
||||
|
||||
### Potential attacks
|
||||
|
||||
* **Registration**: By default a user can register himself, so he could create a user for himself.
|
||||
* **User enumeration**: The registration functionality can be used to find usernames that already exists. This information can be useful for the brute-force attack.
|
||||
* **Login brute-force**: In the [**Authentication**](cognito-user-pools.md#authentication) section you have all the **methods** that a user have to **login**, you could try to brute-force them **find valid credentials**.
|
||||
|
||||
### Tools for pentesting
|
||||
|
||||
* [Pacu](https://github.com/RhinoSecurityLabs/pacu), now includes the `cognito__enum` and `cognito__attack` modules that automate enumeration of all Cognito assets in an account and flag weak configurations, user attributes used for access control, etc., and also automate user creation (including MFA support) and privilege escalation based on modifiable custom attributes, usable identity pool credentials, assumable roles in id tokens, etc.\
|
||||
For a description of the modules' functions see part 2 of the [blog post](https://rhinosecuritylabs.com/aws/attacking-aws-cognito-with-pacu-p2). For installation instructions see the main [Pacu](https://github.com/RhinoSecurityLabs/pacu) page.
|
||||
|
||||
```bash
|
||||
# Run cognito__enum usage to gather all user pools, user pool clients, identity pools, users, etc. visible in the current AWS account
|
||||
Pacu (new:test) > run cognito__enum
|
||||
|
||||
# cognito__attack usage to attempt user creation and all privesc vectors against a given identity pool and user pool client:
|
||||
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
|
||||
```
|
||||
|
||||
* [Cognito Scanner](https://github.com/padok-team/cognito-scanner) is a CLI tool in python that implements different attacks on Cognito including unwanted account creation and account oracle. Check [this link](https://github.com/padok-team/cognito-scanner) for more info.
|
||||
|
||||
```bash
|
||||
# Install
|
||||
pip install cognito-scanner
|
||||
# Run
|
||||
cognito-scanner --help
|
||||
```
|
||||
|
||||
* [CognitoAttributeEnum](https://github.com/punishell/CognitoAttributeEnum): This script allows to enumerate valid attributes for users.
|
||||
|
||||
```bash
|
||||
python cognito-attribute-enu.py -client_id 16f1g98bfuj9i0g3f8be36kkrl
|
||||
```
|
||||
|
||||
## Registration
|
||||
|
||||
User Pools allows by **default** to **register new users**.
|
||||
|
||||
```bash
|
||||
aws cognito-idp sign-up --client-id <client-id> \
|
||||
--username <username> --password <password> \
|
||||
--region <region> --no-sign-request
|
||||
```
|
||||
|
||||
#### If anyone can register
|
||||
|
||||
You might find an error indicating you that you need to **provide more details** of abut the user:
|
||||
|
||||
```
|
||||
An error occurred (InvalidParameterException) when calling the SignUp operation: Attributes did not conform to the schema: address: The attribute is required
|
||||
```
|
||||
|
||||
You can provide the needed details with a JSON such as:
|
||||
|
||||
```json
|
||||
--user-attributes '[{"Name": "email", "Value": "carlospolop@gmail.com"}, {"Name":"gender", "Value": "M"}, {"Name": "address", "Value": "street"}, {"Name": "custom:custom_name", "Value":"supername&\"*$"}]'
|
||||
```
|
||||
|
||||
You could use this functionality also to **enumerate existing users.** This is the error message when a user already exists with that name:
|
||||
|
||||
```
|
||||
An error occurred (UsernameExistsException) when calling the SignUp operation: User already exists
|
||||
```
|
||||
|
||||
{% hint style="info" %}
|
||||
Note in the previous command how the **custom attributes start with "custom:"**.\
|
||||
Also know that when registering you **cannot create for the user new custom attributes**. You can only give value to **default attributes** (even if they aren't required) and **custom attributes specified**.
|
||||
{% endhint %}
|
||||
|
||||
Or just to test if a client id exists. This is the error if the client-id doesn't exist:
|
||||
|
||||
```
|
||||
An error occurred (ResourceNotFoundException) when calling the SignUp operation: User pool client 3ig612gjm56p1ljls1prq2miut does not exist.
|
||||
```
|
||||
|
||||
#### If only admin can register users
|
||||
|
||||
You will find this error and you own't be able to register or enumerate users:
|
||||
|
||||
```
|
||||
An error occurred (NotAuthorizedException) when calling the SignUp operation: SignUp is not permitted for this user pool
|
||||
```
|
||||
|
||||
### Verifying Registration
|
||||
|
||||
Cognito allows to **verify a new user by verifying his email or phone number**. Therefore, when creating a user usually you will be required at least the username and password and the **email and/or telephone number**. Just set one **you control** so you will receive the code to **verify your** newly created user **account** like this:
|
||||
|
||||
```bash
|
||||
aws cognito-idp confirm-sign-up --client-id <cliet_id> \
|
||||
--username aasdasd2 --confirmation-code <conf_code> \
|
||||
--no-sign-request --region us-east-1
|
||||
```
|
||||
|
||||
{% hint style="warning" %}
|
||||
Even if **looks like you can use the same email** and phone number, when you need to verify the created user Cognito will complain about using the same info and **won't let you verify the account**.
|
||||
{% endhint %}
|
||||
|
||||
### Privilege Escalation / Updating Attributes
|
||||
|
||||
By default a user can **modify the value of his attributes** with something like:
|
||||
|
||||
```bash
|
||||
aws cognito-idp update-user-attributes \
|
||||
--region us-east-1 --no-sign-request \
|
||||
--user-attributes Name=address,Value=street \
|
||||
--access-token <access token>
|
||||
```
|
||||
|
||||
#### Custom attribute privesc
|
||||
|
||||
{% hint style="danger" %}
|
||||
You might find **custom attributes** being used (such as `isAdmin`), as by default you can **change the values of your own attributes** you might be able to **escalate privileges** changing the value yourself!
|
||||
{% endhint %}
|
||||
|
||||
#### Email/username modification privesc
|
||||
|
||||
You can use this to **modify the email and phone number** of a user, but then, even if the account remains as verified, those attributes are **set in unverified status** (you need to verify them again).
|
||||
|
||||
{% hint style="warning" %}
|
||||
You **won't be able to login with email or phone number** until you verify them, but you will be **able to login with the username**.\
|
||||
Note that even if the email was modified and not verified it will appear in the ID Token inside the **`email`** **field** and the filed **`email_verified`** will be **false**, but if the app **isn't checking that you might impersonate other users**.
|
||||
|
||||
Moreover, note that you can put anything inside the **`name`** field just modifying the **name attribute**. If an app is **checking** **that** field for some reason **instead of the `email`** (or any other attribute) you might be able to **impersonate other users**.
|
||||
{% endhint %}
|
||||
|
||||
Anyway, if for some reason you changed your email for example to a new one you can access you can **confirm the email with the code you received in that email address**:
|
||||
|
||||
```bash
|
||||
aws cognito-idp verify-user-attribute \
|
||||
--access-token <access_token> \
|
||||
--attribute-name email --code <code> \
|
||||
--region <region> --no-sign-request
|
||||
```
|
||||
|
||||
Use **`phone_number`** instead of **`email`** to change/verify a **new phone number**.
|
||||
|
||||
{% hint style="info" %}
|
||||
The admin could also enable the option to **login with a user preferred username**. Note that you won't be able to change this value to **any username or preferred\_username already being used** to impersonate a different user.
|
||||
{% endhint %}
|
||||
|
||||
### Recover/Change Password
|
||||
|
||||
It's possible to recover a password just **knowing the username** (or email or phone is accepted) and having access to it as a code will be sent there:
|
||||
|
||||
```bash
|
||||
aws cognito-idp forgot-password \
|
||||
--client-id <client_id> \
|
||||
--username <username/email/phone> --region <region>
|
||||
```
|
||||
|
||||
{% hint style="info" %}
|
||||
The response of the server is always going to be positive, like if the username existed. You cannot use this method to enumerate users
|
||||
{% endhint %}
|
||||
|
||||
With the code you can change the password with:
|
||||
|
||||
```bash
|
||||
aws cognito-idp confirm-forgot-password \
|
||||
--client-id <client_id> \
|
||||
--username <username> \
|
||||
--confirmation-code <conf_code> \
|
||||
--password <pwd> --region <region>
|
||||
```
|
||||
|
||||
To change the password you need to **know the previous password**:
|
||||
|
||||
```bash
|
||||
aws cognito-idp change-password \
|
||||
--previous-password <value> \
|
||||
--proposed-password <value> \
|
||||
--access-token <value>
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
A user pool supports **different ways to authenticate** to it. If you have a **username and password** there are also **different methods** supported to login.\
|
||||
Moreover, when a user is authenticated in the Pool **3 types of tokens are given**: The **ID Token**, the **Access token** and the **Refresh token**.
|
||||
|
||||
* [**ID Token**](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-id-token.html): It contains claims about the **identity of the authenticated user,** such as `name`, `email`, and `phone_number`. The ID token can also be used to **authenticate users to your resource servers or server applications**. You must **verify** the **signature** of the ID token before you can trust any claims inside the ID token if you use it in external applications.
|
||||
* The ID Token is the token that **contains the attributes values of the user**, even the custom ones.
|
||||
* [**Access Token**](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-access-token.html): It contains claims about the authenticated user, a list of the **user's groups, and a list of scopes**. The purpose of the access token is to **authorize API operations** in the context of the user in the user pool. For example, you can use the access token to **grant your user access** to add, change, or delete user attributes.
|
||||
* [**Refresh Token**](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-refresh-token.html): With refresh tokens you can **get new ID Tokens and Access Tokens** for the user until the **refresh token is invalid**. By **default**, the refresh token **expires 30 days after** your application user signs into your user pool. When you create an application for your user pool, you can set the application's refresh token expiration to **any value between 60 minutes and 10 years**.
|
||||
|
||||
### ADMIN\_NO\_SRP\_AUTH & ADMIN\_USER\_PASSWORD\_AUTH
|
||||
|
||||
This is the server side authentication flow:
|
||||
|
||||
* The server-side app calls the **`AdminInitiateAuth` API operation** (instead of `InitiateAuth`). This operation requires AWS credentials with permissions that include **`cognito-idp:AdminInitiateAuth`** and **`cognito-idp:AdminRespondToAuthChallenge`**. The operation returns the required authentication parameters.
|
||||
* After the server-side app has the **authentication parameters**, it calls the **`AdminRespondToAuthChallenge` API operation**. The `AdminRespondToAuthChallenge` API operation only succeeds when you provide AWS credentials.
|
||||
|
||||
This **method is NOT enabled** by default.
|
||||
|
||||
To **login** you **need** to know:
|
||||
|
||||
* user pool id
|
||||
* client id
|
||||
* username
|
||||
* password
|
||||
* client secret (only if the app is configured to use a secret)
|
||||
|
||||
{% hint style="info" %}
|
||||
In order to be **able to login with this method** that application must allow to login with `ALLOW_ADMIN_USER_PASSWORD_AUTH`.\
|
||||
Moreover, to perform this action you need credentials with the permissions **`cognito-idp:AdminInitiateAuth`** and **`cognito-idp:AdminRespondToAuthChallenge`**
|
||||
{% endhint %}
|
||||
|
||||
```python
|
||||
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
|
||||
```
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Code to Login</summary>
|
||||
|
||||
```python
|
||||
import boto3
|
||||
import botocore
|
||||
import hmac
|
||||
import hashlib
|
||||
import base64
|
||||
|
||||
|
||||
client_id = "<client-id>"
|
||||
user_pool_id = "<user-pool-id>"
|
||||
client_secret = "<client-secret>"
|
||||
username = "<username>"
|
||||
password = "<pwd>"
|
||||
|
||||
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>
|
||||
|
||||
### USER\_PASSWORD\_AUTH
|
||||
|
||||
This method is another simple and **traditional user & password authentication** flow. It's recommended to **migrate a traditional** authentication method **to Cognito** and **recommended** to then **disable** it and **use** then **ALLOW\_USER\_SRP\_AUTH** method instead (as that one never sends the password over the network).\
|
||||
This **method is NOT enabled** by default.
|
||||
|
||||
The main **difference** with the **previous auth method** inside the code is that you **don't need to know the user pool ID** and that you **don't need extra permissions** in the Cognito User Pool.
|
||||
|
||||
To **login** you **need** to know:
|
||||
|
||||
* client id
|
||||
* username
|
||||
* password
|
||||
* client secret (only if the app is configured to use a secret)
|
||||
|
||||
{% hint style="info" %}
|
||||
In order to be **able to login with this method** that application must allow to login with ALLOW\_USER\_PASSWORD\_AUTH.
|
||||
{% endhint %}
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Python code to Login</summary>
|
||||
|
||||
```python
|
||||
import boto3
|
||||
import botocore
|
||||
import hmac
|
||||
import hashlib
|
||||
import base64
|
||||
|
||||
|
||||
client_id = "<client-id>"
|
||||
user_pool_id = "<user-pool-id>"
|
||||
client_secret = "<client-secret>"
|
||||
username = "<username>"
|
||||
password = "<pwd>"
|
||||
|
||||
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.initiate_auth(
|
||||
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>
|
||||
|
||||
### USER\_SRP\_AUTH
|
||||
|
||||
This is scenario is similar to the previous one but **instead of of sending the password** through the network to login a **challenge authentication is performed** (so no password navigating even encrypted through he net).\
|
||||
This **method is enabled** by default.
|
||||
|
||||
To **login** you **need** to know:
|
||||
|
||||
* user pool id
|
||||
* client id
|
||||
* username
|
||||
* password
|
||||
* client secret (only if the app is configured to use a secret)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Code to login</summary>
|
||||
|
||||
```python
|
||||
from warrant.aws_srp import AWSSRP
|
||||
import os
|
||||
|
||||
USERNAME='xxx'
|
||||
PASSWORD='yyy'
|
||||
POOL_ID='us-east-1_zzzzz'
|
||||
CLIENT_ID = '12xxxxxxxxxxxxxxxxxxxxxxx'
|
||||
CLIENT_SECRET = 'secreeeeet'
|
||||
os.environ["AWS_DEFAULT_REGION"] = "<region>"
|
||||
|
||||
aws = AWSSRP(username=USERNAME, password=PASSWORD, pool_id=POOL_ID,
|
||||
client_id=CLIENT_ID, client_secret=CLIENT_SECRET)
|
||||
tokens = aws.authenticate_user()
|
||||
id_token = tokens['AuthenticationResult']['IdToken']
|
||||
refresh_token = tokens['AuthenticationResult']['RefreshToken']
|
||||
access_token = tokens['AuthenticationResult']['AccessToken']
|
||||
token_type = tokens['AuthenticationResult']['TokenType']
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### REFRESH\_TOKEN\_AUTH & REFRESH\_TOKEN
|
||||
|
||||
This **method is always going to be valid** (it cannot be disabled) but you need to have a valid refresh token.
|
||||
|
||||
```bash
|
||||
aws cognito-idp initiate-auth \
|
||||
--client-id 3ig6h5gjm56p1ljls1prq2miut \
|
||||
--auth-flow REFRESH_TOKEN_AUTH \
|
||||
--region us-east-1 \
|
||||
--auth-parameters 'REFRESH_TOKEN=<token>'
|
||||
```
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Code to refresh</summary>
|
||||
|
||||
```python
|
||||
import boto3
|
||||
import botocore
|
||||
import hmac
|
||||
import hashlib
|
||||
import base64
|
||||
|
||||
client_id = "<client-id>"
|
||||
token = '<token>'
|
||||
|
||||
boto_client = boto3.client('cognito-idp', region_name='<region>')
|
||||
|
||||
def refresh(client_id, refresh_token):
|
||||
try:
|
||||
return boto_client.initiate_auth(
|
||||
ClientId=client_id,
|
||||
AuthFlow='REFRESH_TOKEN_AUTH',
|
||||
AuthParameters={
|
||||
'REFRESH_TOKEN': refresh_token
|
||||
}
|
||||
)
|
||||
except botocore.exceptions.ClientError as e:
|
||||
return e.response
|
||||
|
||||
|
||||
print(refresh(client_id, token))
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### CUSTOM\_AUTH
|
||||
|
||||
In this case the **authentication** is going to be performed through the **execution of a lambda function**.
|
||||
|
||||
## Extra Security
|
||||
|
||||
### Advanced Security
|
||||
|
||||
By default it's disabled, but if enabled, Cognito could be able to **find account takeovers**. To minimise the probability you should login from a **network inside the same city, using the same user agent** (and IP is thats possible)**.**
|
||||
|
||||
### **MFA Remember device**
|
||||
|
||||
If the user logins from the same device, the MFA might be bypassed, therefore try to login from the same browser with the same metadata (IP?) to try to bypass the MFA protection.
|
||||
|
||||
## User Pool Groups IAM Roles
|
||||
|
||||
It's possible to add **users to User Pool** groups that are related to one **IAM roles**.\
|
||||
Moreover, **users** can be assigned to **more than 1 group with different IAM roles** attached.
|
||||
|
||||
Note that even if a group is inside a group with an IAM role attached, in order to be able to access IAM credentials of that group it's needed that the **User Pool is trusted by an Identity Pool** (and know the details of that Identity Pool).
|
||||
|
||||
Another requisite to get the **IAM role indicated in the IdToken** when a user is authenticated in the User Pool (`aws cognito-idp initiate-auth...`) is that the **Identity Provider Authentication provider** needs indicate that the **role must be selected from the token.**
|
||||
|
||||
<figure><img src="../../../../.gitbook/assets/image (250).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
The **roles** a user have access to are **inside the `IdToken`**, and a user can **select which role he would like credentials for** with the **`--custom-role-arn`** from `aws cognito-identity get-credentials-for-identity`.\
|
||||
However, if the **default option** is the one **configured** (`use default role`), and you try to access a role from the IdToken, you will get **error** (that's why the previous configuration is needed):
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```
|
||||
An error occurred (InvalidParameterException) when calling the GetCredentialsForIdentity operation: Only SAML providers and providers with RoleMappings support custom role ARN.
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
{% hint style="warning" %}
|
||||
Note that the role assigned to a **User Pool Group** needs to be **accesible by the Identity Provider** that **trust the User Pool** (as the IAM role **session credentials are going to be obtained from it**).
|
||||
{% endhint %}
|
||||
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Federated": "cognito-identity.amazonaws.com"
|
||||
},
|
||||
"Action": "sts:AssumeRoleWithWebIdentity",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"cognito-identity.amazonaws.com:aud": "us-east-1:2361092e-9db6-a876-1027-10387c9de439"
|
||||
},
|
||||
"ForAnyValue:StringLike": {
|
||||
"cognito-identity.amazonaws.com:amr": "authenticated"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}js
|
||||
```
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="../../../../.gitbook/assets/image (1) (1) (1) (1).png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../.gitbook/assets/image (1) (1) (1) (1).png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../../../.gitbook/assets/image (2) (1).png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../../.gitbook/assets/image (2) (1).png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Support HackTricks</summary>
|
||||
|
||||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
Reference in New Issue
Block a user