# AWS - API Gateway Enum

{{#include ../../../banners/hacktricks-training.md}}

## API Gateway

### 基本情報

AWS API Gatewayは、開発者が**大規模にAPIを作成、公開、管理**するために設計された、Amazon Web Services（AWS）が提供する包括的なサービスです。これはアプリケーションへの入り口として機能し、開発者がルールと手順のフレームワークを確立することを許可します。このフレームワークは、外部ユーザーがアプリケーション内の特定のデータや機能にアクセスする方法を管理します。

API Gatewayは、**APIへのリクエストがどのように処理されるべきかを定義**することを可能にし、特定のメソッド（例：GET、POST、PUT、DELETE）とリソースを持つカスタムAPIエンドポイントを作成できます。また、開発者がアプリケーションからAPIを呼び出しやすくするためのクライアントSDK（ソフトウェア開発キット）を生成することもできます。

### API Gatewayの種類

- **HTTP API**: OIDCやOAuth2などの組み込み機能とネイティブCORSサポートを備えた低遅延でコスト効果の高いREST APIを構築します。以下と連携します：Lambda、HTTPバックエンド。
- **WebSocket API**: チャットアプリケーションやダッシュボードなどのリアルタイムユースケースのために、持続的な接続を使用してWebSocket APIを構築します。以下と連携します：Lambda、HTTP、AWSサービス。
- **REST API**: リクエストとレスポンスを完全に制御できるREST APIを開発し、API管理機能を持ちます。以下と連携します：Lambda、HTTP、AWSサービス。
- **REST API Private**: VPC内からのみアクセス可能なREST APIを作成します。

### API Gatewayの主なコンポーネント

1. **リソース**: API Gatewayにおけるリソースは、**APIの構造を構成するコンポーネント**です。これらは**APIの異なるパスやエンドポイント**を表し、APIがサポートするさまざまなアクションに対応します。リソースは、各パス（/, または /users、または /user/{id}）内の各メソッド（例：GET、POST、PUT、DELETE）です。
2. **ステージ**: API Gatewayのステージは、開発、ステージング、または本番など、APIの**異なるバージョンや環境**を表します。ステージを使用して、**APIの複数のバージョンを同時に管理および展開**でき、新機能やバグ修正を本番環境に影響を与えずにテストできます。ステージはまた、現在のステージに基づいてAPIの動作を構成するために使用できるキーと値のペアである**ステージ変数**を**サポート**します。たとえば、ステージ変数を使用して、ステージに応じてAPIリクエストを異なるLambda関数や他のバックエンドサービスに向けることができます。
- ステージはAPI GatewayエンドポイントのURLの最初に示されます。
3. **オーソライザー**: API Gatewayのオーソライザーは、リクエストが進行する前に呼び出し元のアイデンティティを確認することによって、**APIへのアクセスを制御**する役割を担います。**AWS Lambda関数**をカスタムオーソライザーとして使用でき、独自の認証および認可ロジックを実装できます。リクエストが到着すると、API Gatewayはリクエストの認証トークンをLambdaオーソライザーに渡し、トークンを処理して呼び出し元が実行できるアクションを決定するIAMポリシーを返します。API Gatewayは、**AWS Identity and Access Management (IAM)**や**Amazon Cognito**などの**組み込みオーソライザー**もサポートしています。
4. **リソースポリシー**: API Gatewayのリソースポリシーは、**APIへのアクセス権限を定義するJSONドキュメント**です。これはIAMポリシーに似ていますが、API Gateway専用に調整されています。リソースポリシーを使用して、誰がAPIにアクセスできるか、どのメソッドを呼び出せるか、どのIPアドレスやVPCから接続できるかを制御できます。**リソースポリシーはオーソライザーと組み合わせて使用することができ、APIに対する詳細なアクセス制御を提供します。**
- リソースポリシーが変更された後、APIを**再デプロイする必要があります**。

### ロギング

デフォルトでは、**CloudWatch Logs**は**オフ**、**アクセスロギング**は**オフ**、**X-Rayトレース**も**オフ**です。

### 列挙

> [!TIP]
> AWS APIを使用してリソースを列挙するには（**`apigateway`**および**`apigatewayv2`**）、必要な権限は**`apigateway:GET`**のみであり、それを使用することで**すべてを列挙できます。**

{{#tabs }}
{{#tab name="apigateway" }}
```bash
# Generic info
aws apigateway get-account
aws apigateway get-domain-names
aws apigateway get-usage-plans
aws apigateway get-vpc-links
aws apigateway get-client-certificates

# Enumerate APIs
aws apigateway get-rest-apis # This will also show the resource policy (if any)
## Get stages
aws apigateway get-stages --rest-api-id <id>
## Get resources
aws apigateway get-resources --rest-api-id <id>
## Get API resource action per HTTP verb (check authorizers and api key required)
aws apigateway get-method --http-method GET --rest-api-id <api-id> --resource-id <resource-id>

## Call API
https://<api-id>.execute-api.<region>.amazonaws.com/<stage>/<resource>
## API authorizers
aws apigateway get-authorizers --rest-api-id <id>
## Models
aws apigateway get-models --rest-api-id <id>
## More info
aws apigateway get-gateway-responses --rest-api-id <id>
aws apigateway get-request-validators --rest-api-id <id>
aws apigateway get-deployments --rest-api-id <id>

# Get api keys generated
aws apigateway get-api-keys --include-value
aws apigateway get-api-key --api-key <id> --include-value # Get just 1
## Example use API key
curl -X GET -H "x-api-key: AJE&Ygenu4[..]" https://e83uuftdi8.execute-api.us-east-1.amazonaws.com/dev/test
## Usage plans
aws apigateway get-usage-plans #Get limit use info
aws apigateway get-usage-plan-keys --usage-plan-id <plan_id> #Get clear text values of api keys
aws apigateway get-usage-plan-key --usage-plan-id <plan_id> --key-id <key_id>
###Already consumed
aws apigateway get-usage --usage-plan-id <plan_id> --start-date 2023-07-01 --end-date 2023-07-12
```
{{#endtab }}

{{#tab name="apigatewayv2" }}
```bash
# Generic info
aws apigatewayv2 get-domain-names
aws apigatewayv2 get-domain-name --domain-name <name>
aws apigatewayv2 get-vpc-links

# Enumerate APIs
aws apigatewayv2 get-apis # This will also show the resource policy (if any)
aws apigatewayv2 get-api --api-id <id>

## Get all the info from an api at once
aws apigatewayv2 export-api --api-id <id> --output-type YAML --specification OAS30 /tmp/api.yaml

## Get stages
aws apigatewayv2 get-stages --api-id <id>

## Get routes
aws apigatewayv2 get-routes --api-id <id>
aws apigatewayv2 get-route --api-id <id> --route-id <route-id>

## Get deployments
aws apigatewayv2 get-deployments --api-id <id>
aws apigatewayv2 get-deployment --api-id <id> --deployment-id <dep-id>

## Get integrations
aws apigatewayv2 get-integrations --api-id <id>

## Get authorizers
aws apigatewayv2 get-authorizers --api-id <id>
aws apigatewayv2 get-authorizer --api-id <id> --authorizer-id <uth-id>

## Get domain mappings
aws apigatewayv2 get-api-mappings --api-id <id> --domain-name <dom-name>
aws apigatewayv2 get-api-mapping --api-id <id> --api-mapping-id <map-id> --domain-name <dom-name>

## Get models
aws apigatewayv2 get-models --api-id <id>

## Call API
https://<api-id>.execute-api.<region>.amazonaws.com/<stage>/<resource>
```
{{#endtab }}
{{#endtabs }}

## API Gateway エンドポイントにアクセスするための異なる認証

### リソースポリシー

リソースポリシーを使用して、誰が API エンドポイントを呼び出すことができるかを定義することが可能です。\
以下の例では、**指定された IP は** GET を介してエンドポイント `/resource_policy` を呼び出すことができません。

<figure><img src="../../../images/image (256).png" alt=""><figcaption></figcaption></figure>

### IAM 認証

パス内のメソッド（リソース）が呼び出すために IAM 認証を必要とするように設定することが可能です。

<figure><img src="https://lh3.googleusercontent.com/GGx-kfqNXu6zMqGidnO8_eR88fYPpJG-wNuBBnedAJntiRUEPTEScl7OvWthGYRiI_msYCdC6oBFvJc827Tb4-4UogxpOyrEXyst-8IDzP9DC2NOtXSY7w58L0baCAcBQjSyvBhJREvWWCtiboNYPSKuEw=s2048" alt=""><figcaption></figcaption></figure>

これが設定されると、認証なしでエンドポイントにアクセスしようとすると、エラー `{"message":"Missing Authentication Token"}` が返されます。

アプリケーションが期待するトークンを生成する簡単な方法は、**curl** を使用することです。
```bash
$ curl -X <method> https://<api-id>.execute-api.<region>.amazonaws.com/<stage>/<resource> --user <AWS_ACCESS_KEY>:<AWS_SECRET_KEY> --aws-sigv4 "aws:amz:<region>:execute-api"
```
別の方法は、**Postman**内で**`Authorization`**タイプの**`AWS Signature`**を使用することです。

<figure><img src="../../../images/image (168).png" alt=""><figcaption></figcaption></figure>

使用したいアカウントのaccessKeyとSecretKeyを設定すると、APIエンドポイントに対して認証できます。

どちらの方法も、次のような**Authorization** **header**を生成します：
```
AWS4-HMAC-SHA256 Credential=AKIAYY7XU6ECUDOTWB7W/20220726/us-east-1/execute-api/aws4_request, SignedHeaders=host;x-amz-date, Signature=9f35579fa85c0d089c5a939e3d711362e92641e8c14cc571df8c71b4bc62a5c2
```
他のケースでは、**Authorizer**が**不適切にコーディング**されている可能性があり、**Authorization header**内に**何でも**送信することで**隠されたコンテンツを見ることができる**ことに注意してください。

### Pythonを使用したリクエスト署名
```python

pip install requests
pip install requests-aws4auth
pip install boto3

import boto3
import requests
from requests_aws4auth import AWS4Auth

region = 'us-east-1'  # Region
service = 'execute-api'
access_key = 'YOUR_ACCESS_KEY'
secret_key = 'YOUR_SECRET_KEY'

url = 'https://<apiid>.execute-api.us-east-1.amazonaws.com/<stage>/<resource>'

session = boto3.Session(aws_access_key_id=access_key, aws_secret_access_key=secret_key)
credentials = session.get_credentials()
awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token)

response = requests.get(url, auth=awsauth)

print(response.text)

```
### カスタム Lambda 認証者

特定のトークンに基づいて、**IAM ポリシー**を**返す** Lambda を使用することが可能であり、これによりユーザーが**API エンドポイントを呼び出す権限があるかどうか**を示します。\
認証者を使用する各リソースメソッドを設定できます。

<details>

<summary>Lambda 認証者コード例</summary>
```python
import json

def lambda_handler(event, context):
token = event['authorizationToken']
method_arn = event['methodArn']

if not token:
return {
'statusCode': 401,
'body': 'Unauthorized'
}

try:
# Replace this with your own token validation logic
if token == "your-secret-token":
return generate_policy('user', 'Allow', method_arn)
else:
return generate_policy('user', 'Deny', method_arn)
except Exception as e:
print(e)
return {
'statusCode': 500,
'body': 'Internal Server Error'
}

def generate_policy(principal_id, effect, resource):
policy = {
'principalId': principal_id,
'policyDocument': {
'Version': '2012-10-17',
'Statement': [
{
'Action': 'execute-api:Invoke',
'Effect': effect,
'Resource': resource
}
]
}
}
return policy
```
</details>

次のように呼び出します：

<pre class="language-bash" data-overflow="wrap"><code class="lang-bash"><strong>curl "https://jhhqafgh6f.execute-api.eu-west-1.amazonaws.com/prod/custom_auth" -H 'Authorization: your-secret-token'
</strong></code></pre>

> [!WARNING]
> Lambdaコードによっては、この認証が脆弱である可能性があります

**拒否ポリシーが生成されて返される**場合、API Gatewayから返されるエラーは次のとおりです：`{"Message":"User is not authorized to access this resource with an explicit deny"}`

この方法で、**この認証**が存在することを**特定**できます。

### 必要なAPIキー

**有効なAPIキー**が必要なAPIエンドポイントを設定することが可能です。

<figure><img src="../../../images/image (88).png" alt=""><figcaption></figcaption></figure>

API GatewayポータルでAPIキーを生成し、使用量（リクエスト毎秒および月間リクエスト数）を設定することも可能です。

APIキーを機能させるには、**使用プラン**に追加する必要があります。この使用プランは**APIステージ**に追加され、関連するAPIステージにはAPIキーを必要とする**エンドポイント**に対して**メソッドスロットリング**が設定されている必要があります：

<figure><img src="../../../images/image (198).png" alt=""><figcaption></figcaption></figure>

## 認証されていないアクセス

{{#ref}}
../aws-unauthenticated-enum-access/aws-api-gateway-unauthenticated-enum/README.md
{{#endref}}

## プライバシー昇格

{{#ref}}
../aws-privilege-escalation/aws-apigateway-privesc/README.md
{{#endref}}

## ポストエクスプロイテーション

{{#ref}}
../aws-post-exploitation/aws-api-gateway-post-exploitation/README.md
{{#endref}}

## 永続性

{{#ref}}
../aws-persistence/aws-api-gateway-persistence/README.md
{{#endref}}

{{#include ../../../banners/hacktricks-training.md}}
