AI が自動で脆弱性診断! AWS Security Agent のハンズオンをやってみた

AI が自動で脆弱性診断! AWS Security Agent のハンズオンをやってみた

専用ツールなどの知識がなくてもWebアプリケーションの脆弱性を自動検出できるサービス AWS Security Agent を体験してみた手順、感想をレポートしています
2026.05.25

はじめに

クラスメソッドオペレーションズの Shimizu です。

AI エージェントがWebアプリケーションに対して自動的にペネトレーションテスト(脆弱性診断)を行うマネージドサービス「AWS Security Agent」が先日 GA となりました。筆者を含めて、以下のような方も多いかと思います。

  • 興味があり触ってみたいが、専門知識がないため難しそう
  • 課金が気になって気軽に試すことができない
  • 診断対象となるWebアプリケーションの用意が難しい

そこで今回は Security Agent の無料枠(2ヶ月間/月400タスク時間まで)を利用して、OWASP 提供のテスト用Webアプリに対するペネトレーションテストをやってみたので、その詳しい手順をご紹介します。
これから利用を検討される方が、所要時間やどの程度の課金が見込まれるかなど、事前にイメージする参考になれば幸いです。

前提条件

今回は以下の条件で実施しました。

  • Route 53 パブリックホストゾーンで管理する独自ドメインを所有している
  • 独自ドメインの ACM 証明書を発行済み
  • AWS アカウントで Administrator 相当の権限を有している

今回の構成図

img-000

ペネトレーションテストの設定時に対象アプリケーションのドメイン所有確認が必要なため、Route 53 もしくは他の DNS サービスの操作権限が必要になります。またテスト対象の Web アプリ(ALB、EC2)を CloudFormation でまとめて構築するため、対象 AWS アカウントに各リソースを作成する権限も必要になります。

EC2 でホストするテスト用のWebアプリケーションは「OWASP Juice Shop」を使用しています。下記の記事で詳しく解説されていますので、ここでは説明を省きます。

https://dev.classmethod.jp/articles/security-agent-owasp-juice-shop/

やってみた

Step 1: CloudFormation でWebアプリケーションを一括デプロイ

まず CloudFormation のスタック作成時に入力する必要があるため、ALB に紐付ける ACM 証明書の ARN を確認しておきます:

img-001

次に、下記の CloudFormation テンプレート内容をコピーして、テキストファイルでPC上に保存します。ここではファイル名「security-agent-handson.yaml」とします。

テンプレートはこちら
AWSTemplateFormatVersion: '2010-09-09'
Description: >
  AWS Security Agent Hands-on: EC2 with ALB Deploys a vulnerable web application for penetration testing with AWS Security Agent.Requires a existing ACM certificate.

# ============================================================
# Architecture Overview
# ============================================================
#
# 前提条件:
#   - 独自ドメインを所有していること
#   - ACM で対象ドメインの証明書が発行済み(検証完了)であること
#
# このテンプレートで作成するもの:
#   - VPC / サブネット / IGW / ルートテーブル
#   - ALB(HTTPS リスナー + ACM 証明書適用)
#   - EC2(OWASP Juice Shop を Docker で起動)
#   - セキュリティグループ / IAM ロール
#
# このテンプレートで作成しないもの(手動作業):
#   - Route 53 への ALB エイリアスレコード登録
#   - Security Agent のエージェントスペース作成
#   - Security Agent のペネトレーションテスト設定・実行
# ============================================================

Parameters:
  CertificateArn:
    Type: String
    Description: >
      ACM ARN *example: arn:aws:acm:ap-northeast-1:123456789012:certificate/xxxxx

Resources:
  # ============================================================
  # VPC & Networking
  # - EC2 と ALB を配置するネットワーク基盤。
  # - IGW 経由でインターネットアクセスを提供(Docker イメージ pull、ALB 公開)。
  # ============================================================
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: security-agent-handson-vpc

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: security-agent-handson-igw

  InternetGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  PublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.1.0/24
      AvailabilityZone: !Select [0, !GetAZs '']
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: security-agent-handson-public-1a

  PublicSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.2.0/24
      AvailabilityZone: !Select [1, !GetAZs '']
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: security-agent-handson-public-1c

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: security-agent-handson-public-rt

  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: InternetGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet1
      RouteTableId: !Ref PublicRouteTable

  PublicSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet2
      RouteTableId: !Ref PublicRouteTable

  # ============================================================
  # Security Groups
  # - ALB SG: インターネットからの HTTPS (443) を許可
  # - EC2 SG: ALB からのポート 3000 のみ許可
  # ============================================================
  ALBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security Agent Handson - ALB SG (HTTPS)
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0
          Description: Allow HTTPS from internet
      Tags:
        - Key: Name
          Value: security-agent-handson-alb-sg

  EC2SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security Agent Handson - EC2 SG
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 3000
          ToPort: 3000
          SourceSecurityGroupId: !Ref ALBSecurityGroup
          Description: Allow traffic from ALB
      Tags:
        - Key: Name
          Value: security-agent-handson-ec2-sg

  # ============================================================
  # IAM Role for EC2
  # - SSM Session Manager 経由で EC2 に接続するためのロール。
  # - SSH キーペア不要でセキュアにインスタンスへアクセスできる。
  # ============================================================
  EC2Role:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub '${AWS::StackName}-ec2-role'
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
      Tags:
        - Key: Name
          Value: !Sub '${AWS::StackName}-ec2-role'

  EC2InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      InstanceProfileName: !Sub '${AWS::StackName}-ec2-profile'
      Roles:
        - !Ref EC2Role

  # ============================================================
  # EC2 Instance (OWASP Juice Shop)
  # - Docker で OWASP Juice Shop を起動し、ポート 3000 で待ち受ける。
  # ============================================================
  JuiceShopInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Sub '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64}}'
      InstanceType: t3.medium
      IamInstanceProfile: !Ref EC2InstanceProfile
      SubnetId: !Ref PublicSubnet2
      SecurityGroupIds:
        - !Ref EC2SecurityGroup
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -xe
          exec > /var/log/userdata.log 2>&1

          # Install Docker
          dnf update -y
          dnf install -y docker

          # Add ec2-user to docker group
          usermod -aG docker ec2-user

          # Start Docker service
          systemctl enable docker
          systemctl start docker

          # Wait for Docker daemon to be ready
          for i in $(seq 1 30); do
            docker info > /dev/null 2>&1 && break
            echo "Waiting for Docker daemon... ($i/30)"
            sleep 2
          done

          # Pull and run OWASP Juice Shop container
          docker pull bkimminich/juice-shop:latest
          docker run -d --name juice-shop \
            --restart always \
            -p 3000:3000 \
            bkimminich/juice-shop:latest

          # Wait for Juice Shop to be ready (healthcheck)
          for i in $(seq 1 60); do
            curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/ | grep -q "200" && break
            echo "Waiting for Juice Shop to start... ($i/60)"
            sleep 5
          done
          echo "Juice Shop is ready"

      Tags:
        - Key: Name
          Value: security-agent-handson-juiceshop

  # ============================================================
  # Application Load Balancer
  # - HTTPS でアプリケーションを公開する。
  # - ACM 証明書を適用し、Security Agent が HTTPS 経由でテスト可能にする。
  # ============================================================
  ALB:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: security-agent-handson-alb
      Scheme: internet-facing
      Type: application
      SecurityGroups:
        - !Ref ALBSecurityGroup
      Subnets:
        - !Ref PublicSubnet1
        - !Ref PublicSubnet2
      Tags:
        - Key: Name
          Value: security-agent-handson-alb

  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: security-agent-handson-tg
      Protocol: HTTP
      Port: 3000
      VpcId: !Ref VPC
      TargetType: instance
      Targets:
        - Id: !Ref JuiceShopInstance
          Port: 3000
      HealthCheckPath: /
      HealthCheckProtocol: HTTP
      HealthCheckPort: '3000'
      HealthyThresholdCount: 2
      UnhealthyThresholdCount: 3
      HealthCheckIntervalSeconds: 30
      HealthCheckTimeoutSeconds: 5
      Tags:
        - Key: Name
          Value: security-agent-handson-tg

  # HTTPS リスナー(ACM 証明書を適用)
  ALBListenerHTTPS:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      LoadBalancerArn: !Ref ALB
      Protocol: HTTPS
      Port: 443
      SslPolicy: ELBSecurityPolicy-TLS13-1-2-2021-06
      Certificates:
        - CertificateArn: !Ref CertificateArn
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref TargetGroup

# ============================================================
# Outputs
# ============================================================
Outputs:
  ALBDNSName:
    Description: >
      ALB の DNS 名。Route 53 で A レコード(エイリアス)を作成する際のターゲット。
    Value: !GetAtt ALB.DNSName

  ALBHostedZoneId:
    Description: >
      ALB の Hosted Zone ID。Route 53 エイリアスレコード作成時に必要。
    Value: !GetAtt ALB.CanonicalHostedZoneID

  EC2InstanceId:
    Description: EC2 Instance ID — SSM Session Manager で接続する際に使用
    Value: !Ref JuiceShopInstance

  VpcId:
    Description: VPC ID
    Value: !Ref VPC

上記の用意ができたら、ACM 証明書が存在するリージョンの AWS コンソールを開いて CloudFormation スタックを新規作成します。PC上に保存した .yaml テンプレートを選択して進めます。

img-002

スタック名は任意ですが、今回は「security-agent-handson」とします。
パラメータには先ほど確認した ACM 証明書の ARN を入力します。

img-003

あとは特に何も入力せず、スタックの作成へ進みます。一連のリソース作成が完了するまでしばらく待ちます。

img-004

スタック作成が完了したら、ALB の HTTPS リスナーに指定した ACM 証明書が設定されていることを確認します。

img-005

併せてターゲットグループのヘルスチェック状態も確認します。Unhealthy の場合は EC2 の起動に時間がかかっている可能性があるので、Healthy になるまでしばらく待ちます。

img-006

ALB のステータスが Healthy になったら、次に Route 53 へのレコード登録を行います。

Step 2: Route 53 に A レコードを登録してサブドメインと ALB を紐付ける

対象ドメインのホストゾーン設定を開き「レコードを作成」をクリックします。

img-007

サブドメイン名は任意ですが、ここでは「juiceshop」とします。レコードタイプは A(エイリアス)で、先ほど作成した ALB を選択してレコードを登録します。

img-008

レコードを登録したら、ブラウザからhttps://juiceshop.独自ドメイン名でアクセスしてみます。下記のような架空のジュースショップのサイトが表示されます。

img-009

これでテスト対象 Web アプリケーションの準備は完了です。

次は AWS Security Agent の初期設定を行なっていきます。

Step 3: Security Agent の初期セットアップ

AWS Security Agent のコンソール画面にアクセスして、まずサービスの起点となる「エージェントスペース」というリソースを作成します。

左側メニューで「エージェントスペース」を開き「最初のエージェントスペースを作成」をクリックします。

img-010

エージェントスペース名は任意ですが、ここでは「security-agent-handson」とします。
あとは特に何も変更せず「作成」をクリックします。

img-011

エージェントスペース作成はこれだけで完了です。

次はぺネトレーションテスト(脆弱性診断)の設定を行なっていきます。

Step 4: ペネトレーションテストの設定

ここが少し難しい設定になりますが、ペネトレーションテストを行うサイトのドメインに対して「そのドメインのオーナーであること」を証明する必要があります。他人のサイトを無断でスキャンすることを防ぐための重要な仕組みです。

コンソール画面から「ぺネトレーションテストを有効化」をクリックします。

img-012

「ターゲットドメイン」に先ほど登録したjuiceshop.独自ドメイン名 を入力します。
検証方法は「DNSテキストレコード」を選択して次に進みます。

img-013

入力したドメインの検証が行われます。この時点ではステータスが「保留中」になっているため「検証トークン」と「DNS レコード名/ルートパス」をコピーします。

img-014

再び Route 53 のホストゾーン画面に行き、ドメイン検証用の TXT レコードを作成します。レコード名には先ほどの画面でコピーした「DNSレコード名」を、値には「検証トークン」を貼り付けて、レコードを登録します。

img-015

再び Security Agent の設定画面に戻り、ターゲットドメインの左側にチェックを入れて「検証」をクリックします。

ステータスが検証済みになれば OK なので、次の画面に進みます。
(失敗してしまう場合は、入力した値に間違いがないか確認して、しばらく時間をおいて試してみましょう)

img-016

次のオプション画面ではペネトレーションテスト対象の VPC スコープやロギング設定、使用する IAM ロールの設定等が行えますが、今回は特に変更せず「保存」をクリックします。

img-017

これでペネトレーションテストの準備が完了です。
次は実際のペネトレーションテストを実行していきます。

Step 5: ペネトレーションテストの実行

※ ペネトレーションテストの実行を開始すると、完了まで数時間かかります。無料利用枠を超えると、大きな課金が発生するので注意しましょう。

コンソール画面の「ウェブアプリで開始」をクリックします。

img-018

専用のウェブアプリ画面が開くので、左側ペインの「ペネトレーションテスト」から「初めてのペネトレーションテストを作成」をクリックします。

img-019

各設定画面で、今回は以下のように入力しました。

ペネトレーションテストの詳細

  • ペネトレーションテスト名
    任意ですが「first-penatration-test」と入力

  • ターゲット URL
    作成したテストサイトのURL https://juiceshop.独自ドメイン名 を入力

  • リスクタイプを除外する - オプション

  • 範囲外の URL - オプション

  • アクセス可能な URL - オプション

  • カスタム HTTP ヘッダー - オプション
    特に設定せず(もしテストから除外したいリスクやURLがあればここで入力)

  • サービスロール
    先ほどのペネトレーション設定操作で自動作成された IAM ロールを指定

  • 自動コード修正
    チェックなし

VPC リソース - オプション
特に入力せず

認証リソース - オプション
今回は OWASP Juice Shop にあらかじめ用意された、以下のログイン情報を入力して進めます。

ユーザー名 admin@juice-sh.op
パスワード admin123

📌 認証情報を渡すと、ログイン後の画面(マイページ・管理画面など)もスキャン対象になり、検出される脆弱性の数が大幅に増えます。実運用での診断時は認証設定を活用することをおすすめします。

その他の学習リソース - オプション
今回は特に設定なし。
もし脆弱性診断のために用意しているドキュメント資料などがあればアップロードします。

以上の項目を入力したら「ペネトレーションテストを作成」をクリックします。

img-020
img-021
img-022

ペネトレーションテストを作成できたら「実行を開始する」をクリックします。

確認画面が出るので、課金などについて了承済みで問題がなければ、実行を開始します。

img-023

開始したら、あとは診断が完了するまで待つだけです。開始時間の部分をクリックすると、進行中のテストの詳細を確認できます。

img-024

もし停止したくなったら「実行を停止」ボタンで停止できます。
再開はできないようですが、もし誤って開始してしまった場合はここから停止しましょう。

img-025

あとはテストが完了するまで待ちます。今回の検証では4時間半ほどかかりました。
(対象サイトの規模や診断項目によって異なると思いますが、目安になれば幸いです)

Step 6: 結果の確認

ペネトレーションテストの実行ステータスが「Completed」になれば完了です。
完了後、コンソールでログや検出結果を確認できます。PDF レポートのダウンロードも可能です。

※ 今回、完了までにかかった所要時間は約4時間19分ですが、タスク時間は17.14時間でした。
料金ドキュメント *4 によると記事執筆時点での料金は「$50.00 per task-hour」なので、もし無料枠なしで利用した場合、今回のテストで $50 x 17.14h = $857(約13.6万円)の課金が予想されます。

img-026

検出結果では脆弱性の優先度や内容、再現手順までもが詳細に確認できます。

img-027

PDF のレポートは英語ですが、見た目も美しくこのまま提出できそうな内容です。これをさらに AI に分析させれば、Web アプリの改修計画も立てられそうです。

img-028

これでペネトレーションテストのハンズオンは完了なので、今回作成したリソースのクリーンアップを行います。

Step 7: クリーンアップ

まずは Route 53 ホストゾーンから、今回登録した 2 レコードを削除します。
(juiceshop のサブドメイン、Security Agent のドメイン検証)

img-029

続いて Security Agent のコンソール画面から、エージェントスペースの削除を行います。

img-030

最後に、今回作成した CloudFormation スタックを削除します。

img-031

これで今回のハンズオンは完了です。

さいごに

いかがでしたでしょうか。
これまで脆弱性診断ツールなどの専門知識がなかった筆者でも、思っていたよりずっと簡単にペネトレーションテストを実施できたことに驚きました。

もちろん診断結果の深い読み込みや修正対応には専門家の知識が必要であり、無料枠がなければ利用料も一概に安価とはいえません。
しかしながら AWS Security Agent によってペネトレーションテストの実施ハードルは大幅に下がるため「まず自分のアプリにどんなリスクがあるか把握したい」という第一歩としては有効な選択肢だと思います。

AWS Securit Agent を導入するかご検討されている方に、この記事が判断の材料となれば幸いです!

参考資料

クラスメソッドオペレーションズ株式会社について

クラスメソッドグループのオペレーション企業です。
運用・保守開発・サポート・情シス・バックオフィスの専門チームが、IT・AIをフル活用した「しくみ」を通じて、お客様の業務代行から課題解決や高付加価値サービスまでを提供するエキスパート集団です。
当社は様々な職種でメンバーを募集しています。
「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、クラスメソッドオペレーションズ株式会社 コーポレートサイト をぜひご覧ください。
※2026年1月 アノテーション㈱から社名変更しました

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事