ALB のパブリックIPアドレスに直接アクセスできる状態は危険です。リスナールールを使ってセキュリティを強化しましょう。

記事タイトルとURLをコピーする

こんにちは😸
カスタマーサクセス部の山本です。

Application Load Balancer (ALB) のパブリック IP アドレスに https 接続できるような状態において、潜む危険があったりします。 その部分を解説してみようと思います。

ALB のパブリック IP アドレスに https 接続できるような状態

パブリックな Application Load Balancer (ALB) を作成し、*.karukozaka46.click という証明書を紐づけています。

この ALB には youkoso.karukozaka46.click という A レコードを Route 53 に作成して関連付けています。

ALB のパブリック IP アドレスはインターネットから名前解決可能になっています。

ブラウザで youkoso.karukozaka46.click にアクセスすると、正常に ALB の先の WEB サーバーが正常に応答します。

ブラウザでパブリック IP アドレスにアクセスした場合も、警告が出るものの、正常に応答します。

パブリック IP アドレスからのリクエストを許容することにより生じる危険

正規のドメイン名を知らないボットや攻撃者も、IPアドレスをスキャンしてアクセスを試みます。IPアドレスで直接アクセスできる状態は、以下のような危険を生みます。

  • ドメインフロンティングへの悪用。攻撃の踏み台として ALB やバックエンドのサーバーが悪用される可能性があります。
  • 設定情報の推測。レスポンスの内容やエラーメッセージから、サーバーの構成に関するヒントを攻撃者に与えてしまうことがあります。
  • コストの増加。大量の不正アクセスを ALB が処理することで、無駄なデータ転送料金が発生する可能性があります。

取りうる対策

ターゲットグループに転送するリスナールールには、「正規のドメインをホストヘッダに含むリクエストを転送する」条件を入れましょう。
以下の例では、youkoso.karukozaka46.click というドメイン宛のリクエストのみをバックエンドの ECS コンテナ / EC2 に転送しています。

また最も重要なのが、どのルールにも一致しなかった場合に適用されるデフォルトアクションです。これをターゲットグループに転送する設定にせず、固定レスポンス(例: 403 Forbidden)を返すように設定しましょう。

これにより、ALB の パブリック IP アドレスへのリクエストは、403 を返却するようになりました。

正規のリクエストは正常に動作します。

不正なリクエストが来ているかを調査する方法

ALB でアクセスログを有効にしましょう。これにより、 ALB にどういったリクエストが来ているのが確認できます。
そして、 Athena でテーブルを作成しクエリを書いて分析しましょう。
初期設定方法は本記事では触れません。以下のサーバーワークスブログと公式ドキュメントを参考にしましょう。

テーブル作成

CREATE EXTERNAL TABLE IF NOT EXISTS alb_access_logs (
            type string,
            time string,
            elb string,
            client_ip string,
            client_port int,
            target_ip string,
            target_port int,
            request_processing_time double,
            target_processing_time double,
            response_processing_time double,
            elb_status_code int,
            target_status_code string,
            received_bytes bigint,
            sent_bytes bigint,
            request_verb string,
            request_url string,
            request_proto string,
            user_agent string,
            ssl_cipher string,
            ssl_protocol string,
            target_group_arn string,
            trace_id string,
            domain_name string,
            chosen_cert_arn string,
            matched_rule_priority string,
            request_creation_time string,
            actions_executed string,
            redirect_url string,
            lambda_error_reason string,
            target_port_list string,
            target_status_code_list string,
            classification string,
            classification_reason string,
            conn_trace_id string
            )
            ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
            WITH SERDEPROPERTIES (
            'serialization.format' = '1',
            'input.regex' = 
        '([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \"([^ ]*) (.*) (- |[^ ]*)\" \"([^\"]*)\" ([A-Z0-9-_]+) ([A-Za-z0-9.-]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" ([-.0-9]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^ ]*)\" \"([^\\s]+?)\" \"([^\\s]+)\" \"([^ ]*)\" \"([^ ]*)\" ?([^ ]*)?'
            )
            LOCATION 's3://yamamoto-alb-accesslog/AWSLogs/'

クエリ

SELECT
  *
FROM
  alb_access_logs
WHERE
  -- JSTでの時刻指定をUTCに変換して検索します (JST = UTC+9h)
  time >= '2025-08-04T05:00:00Z' AND 
  time < '2025-08-04T07:30:00Z'

さて、クエリ結果の列名 request_url では、どういった URL へのリクエストがあったかを確認できます。
これらの URL が正規のドメインでない場合は基本的に攻撃とみていいでしょう。
また、それらのリクエストのうち、elb_status_codetarget_status_code が両方 200 になったものは要注意です。
なぜなら、「作成者の意図しない URL にアクセスがあり、リクエストが成功し、サーバーがなんらかのデータを閲覧者に返している」ためです。
言い換えるなら「攻撃者からの情報採取が成功したかもしれないリクエスト」になります。

ALB のリスナーで IP アドレスでのアクセスを許可している場合には、ドメインフロンティング攻撃のように見えるリクエストも見受けられました。

「攻撃者からの情報採取が成功したかもしれないリクエスト」を抽出するクエリになります。
もし攻撃を受けた場合、このクエリ結果にある request_url を一つずつ当たってみると、問題解決の鍵が得られるかもしれません。

SELECT
  *
FROM
  alb_access_logs
WHERE
  -- JSTでの時刻指定をUTCに変換して検索します (JST = UTC+9h)
  time >= '2025-08-04T05:00:00Z' AND 
  time < '2025-08-04T07:30:00Z' AND
  -- データ型に合わせて比較
  elb_status_code = 200 AND
  target_status_code = '200' AND
  -- 指定したドメイン名(ホストヘッダ)ではないものを抽出
  domain_name != 'youkoso.karukozaka46.click'

アクセスログにある各列の説明は以下のドキュメントもご参照ください。

まとめ

ALBのIPアドレスへ直接アクセスできることの危険性と、その対策を解説しました。意図しないアクセスは、コストの増加だけでなく、攻撃の踏み台にされるといったセキュリティリスクにも直結します。正規ドメイン以外からのアクセスはリスナールールで明確に拒否し、ALBのアクセスログをAthenaで分析することで、より安全なサービス運用を目指しましょう。

山本 哲也 (記事一覧)

カスタマーサクセス部のインフラエンジニア。

山を走るのが趣味です。