
AI が自動で脆弱性診断! AWS Security Agent のハンズオンをやってみた
はじめに
クラスメソッドオペレーションズの Shimizu です。
AI エージェントがWebアプリケーションに対して自動的にペネトレーションテスト(脆弱性診断)を行うマネージドサービス「AWS Security Agent」が先日 GA となりました。筆者を含めて、以下のような方も多いかと思います。
- 興味があり触ってみたいが、専門知識がないため難しそう
- 課金が気になって気軽に試すことができない
- 診断対象となるWebアプリケーションの用意が難しい
そこで今回は Security Agent の無料枠(2ヶ月間/月400タスク時間まで)を利用して、OWASP 提供のテスト用Webアプリに対するペネトレーションテストをやってみたので、その詳しい手順をご紹介します。
これから利用を検討される方が、所要時間やどの程度の課金が見込まれるかなど、事前にイメージする参考になれば幸いです。
前提条件
今回は以下の条件で実施しました。
- Route 53 パブリックホストゾーンで管理する独自ドメインを所有している
- 独自ドメインの ACM 証明書を発行済み
- AWS アカウントで Administrator 相当の権限を有している
今回の構成図

ペネトレーションテストの設定時に対象アプリケーションのドメイン所有確認が必要なため、Route 53 もしくは他の DNS サービスの操作権限が必要になります。またテスト対象の Web アプリ(ALB、EC2)を CloudFormation でまとめて構築するため、対象 AWS アカウントに各リソースを作成する権限も必要になります。
EC2 でホストするテスト用のWebアプリケーションは「OWASP Juice Shop」を使用しています。下記の記事で詳しく解説されていますので、ここでは説明を省きます。
やってみた
Step 1: CloudFormation でWebアプリケーションを一括デプロイ
まず CloudFormation のスタック作成時に入力する必要があるため、ALB に紐付ける ACM 証明書の ARN を確認しておきます:

次に、下記の 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 テンプレートを選択して進めます。

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

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

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

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

ALB のステータスが Healthy になったら、次に Route 53 へのレコード登録を行います。
Step 2: Route 53 に A レコードを登録してサブドメインと ALB を紐付ける
対象ドメインのホストゾーン設定を開き「レコードを作成」をクリックします。

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

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

これでテスト対象 Web アプリケーションの準備は完了です。
次は AWS Security Agent の初期設定を行なっていきます。
Step 3: Security Agent の初期セットアップ
AWS Security Agent のコンソール画面にアクセスして、まずサービスの起点となる「エージェントスペース」というリソースを作成します。
左側メニューで「エージェントスペース」を開き「最初のエージェントスペースを作成」をクリックします。

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

エージェントスペース作成はこれだけで完了です。
次はぺネトレーションテスト(脆弱性診断)の設定を行なっていきます。
Step 4: ペネトレーションテストの設定
ここが少し難しい設定になりますが、ペネトレーションテストを行うサイトのドメインに対して「そのドメインのオーナーであること」を証明する必要があります。他人のサイトを無断でスキャンすることを防ぐための重要な仕組みです。
コンソール画面から「ぺネトレーションテストを有効化」をクリックします。

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

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

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

再び Security Agent の設定画面に戻り、ターゲットドメインの左側にチェックを入れて「検証」をクリックします。
ステータスが検証済みになれば OK なので、次の画面に進みます。
(失敗してしまう場合は、入力した値に間違いがないか確認して、しばらく時間をおいて試してみましょう)

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

これでペネトレーションテストの準備が完了です。
次は実際のペネトレーションテストを実行していきます。
Step 5: ペネトレーションテストの実行
※ ペネトレーションテストの実行を開始すると、完了まで数時間かかります。無料利用枠を超えると、大きな課金が発生するので注意しましょう。
コンソール画面の「ウェブアプリで開始」をクリックします。

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

各設定画面で、今回は以下のように入力しました。
ペネトレーションテストの詳細
-
ペネトレーションテスト名
任意ですが「first-penatration-test」と入力 -
ターゲット URL
作成したテストサイトのURLhttps://juiceshop.独自ドメイン名を入力 -
リスクタイプを除外する - オプション
-
範囲外の URL - オプション
-
アクセス可能な URL - オプション
-
カスタム HTTP ヘッダー - オプション
特に設定せず(もしテストから除外したいリスクやURLがあればここで入力) -
サービスロール
先ほどのペネトレーション設定操作で自動作成された IAM ロールを指定 -
自動コード修正
チェックなし
VPC リソース - オプション
特に入力せず
認証リソース - オプション
今回は OWASP Juice Shop にあらかじめ用意された、以下のログイン情報を入力して進めます。
ユーザー名 admin@juice-sh.op
パスワード admin123
📌 認証情報を渡すと、ログイン後の画面(マイページ・管理画面など)もスキャン対象になり、検出される脆弱性の数が大幅に増えます。実運用での診断時は認証設定を活用することをおすすめします。
その他の学習リソース - オプション
今回は特に設定なし。
もし脆弱性診断のために用意しているドキュメント資料などがあればアップロードします。
以上の項目を入力したら「ペネトレーションテストを作成」をクリックします。



ペネトレーションテストを作成できたら「実行を開始する」をクリックします。
確認画面が出るので、課金などについて了承済みで問題がなければ、実行を開始します。

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

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

あとはテストが完了するまで待ちます。今回の検証では4時間半ほどかかりました。
(対象サイトの規模や診断項目によって異なると思いますが、目安になれば幸いです)
Step 6: 結果の確認
ペネトレーションテストの実行ステータスが「Completed」になれば完了です。
完了後、コンソールでログや検出結果を確認できます。PDF レポートのダウンロードも可能です。
※ 今回、完了までにかかった所要時間は約4時間19分ですが、タスク時間は17.14時間でした。
料金ドキュメント *4 によると記事執筆時点での料金は「$50.00 per task-hour」なので、もし無料枠なしで利用した場合、今回のテストで $50 x 17.14h = $857(約13.6万円)の課金が予想されます。

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

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

これでペネトレーションテストのハンズオンは完了なので、今回作成したリソースのクリーンアップを行います。
Step 7: クリーンアップ
まずは Route 53 ホストゾーンから、今回登録した 2 レコードを削除します。
(juiceshop のサブドメイン、Security Agent のドメイン検証)

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

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

これで今回のハンズオンは完了です。
さいごに
いかがでしたでしょうか。
これまで脆弱性診断ツールなどの専門知識がなかった筆者でも、思っていたよりずっと簡単にペネトレーションテストを実施できたことに驚きました。
もちろん診断結果の深い読み込みや修正対応には専門家の知識が必要であり、無料枠がなければ利用料も一概に安価とはいえません。
しかしながら AWS Security Agent によってペネトレーションテストの実施ハードルは大幅に下がるため「まず自分のアプリにどんなリスクがあるか把握したい」という第一歩としては有効な選択肢だと思います。
AWS Securit Agent を導入するかご検討されている方に、この記事が判断の材料となれば幸いです!
参考資料
- *1 AWS Security Agent ユーザーガイド
- *2 クイックスタート: ペネトレーションテストの実行
- *3 ドメイン検証の設定
- *4 AWS Security Agent 料金
- *5 OWASP Juice Shop
クラスメソッドオペレーションズ株式会社について
クラスメソッドグループのオペレーション企業です。
運用・保守開発・サポート・情シス・バックオフィスの専門チームが、IT・AIをフル活用した「しくみ」を通じて、お客様の業務代行から課題解決や高付加価値サービスまでを提供するエキスパート集団です。
当社は様々な職種でメンバーを募集しています。
「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、クラスメソッドオペレーションズ株式会社 コーポレートサイト をぜひご覧ください。
※2026年1月 アノテーション㈱から社名変更しました










