2020年9月1日火曜日

OWASP ZAP(脆弱性診断)の検証環境をCloudFormationで構築してみた


下記URLを参考にして、OWASP ZAPの検証環境を作ってみました。

検証環境の構成イメージは下図のとおり。


[MEMO]
  • OWASP ZAP と WebGoat はECS(EC2)で動かします。
  • OWASP ZAPは、NLB経由でアクセスします。なお、NLBは、ACLで、特定IPアドレスのみアクセスできるように制限します。
  • WebGoatは、VPC内部からのアクセスのみ許可します。インターネット経由でWebGoatにアクセスしたい場合は、NATインスタンスを踏み台にしてSSHポート転送を使用します。
  • NATインスタンスとECSインスタンスはセッションマネージャでログインします。
  • NATインスタンスとECSインスタンスは費用節約のためSpotInstanceを使用します。
  • EIPは必須ではありません。

[注意]
  • WebGoatは、わざと脆弱性を含ませたWEBアプリケーションです。インターネットに公開すると危険です。
    https://owasp.org/www-project-webgoat/
  • OWASP ZAP の動的スキャンは、攻撃コードを含んだリクエストを送信します。診断対象のサイトが壊れる危険があります。
    OWAS ZAPで他人のサイトにアクセスしないよう注意してください!!
    https://www.zaproxy.org/

環境構築


## 作業環境(ローカル環境)

構築作業は、WSL2(ubuntu20.04)で実施します。
なお、AWSのリージョンは us-east-1を使用します。
  • Windows10
  • WSL2(ubuntu20.04)
  • docker 19.03.12
  • make 4.2.1
  • aws-cli 1.17.14

1. aws-cli の設定


aws-cli実行時はプロファイルを指定します。プロファイルの設定は下記のとおり。
  • blue21 という名称でプロファイルを作成
  • リージョンは us-east-1 を使用し, Output形式は json
  • 管理者権限のアクセスキーを使用

2. ソース一式のdownload


環境構築に必要なCloudFormationテンプレートなどは、Bitbucketに登録しています。
Bitbucketの下記URLからダウンロードできます。

レポジトリの内容は以下のとおり。
.
├── README.md
├── app
│   ├── README.md
│   └── docker-compose.yml
├── bin
│   ├── Makefile
│   ├── README.md
│   ├── cfn_validate.sh
│   └── cfn_wait.sh
├── cfn
│   ├── Makefile
│   ├── README.md
│   ├── cfn_ec2_nat.yml
│   ├── cfn_ecs_cluster.yml
│   ├── cfn_ecs_service_webgoat.yml
│   ├── cfn_ecs_service_zap.yml
│   ├── cfn_nlb.yml
│   └── cfn_vpc.yml
└── img
    ├── image01.drawio
    └── image01.png

3.CloudFormation実行


構築は、aws-cli と CloudFormationで行います。
aws-cliのコマンドはMakefileに記述しています。
構築時にEC2のキーペア(名称: virginia_key) を使用するので、事前に同じ名称でキーペアを作成するか Makefile を修正してキーペアを変更します
# NAT
cfnnat:
        $(eval STACK_NAME := Blue21Nat00PoC)
        aws cloudformation $(CFNCMD) \
        --profile $(AWSPROFILE) \
        --stack-name $(STACK_NAME) \
        --template-body file://`pwd`/cfn_ec2_nat.yml \
        --parameters \
        "ParameterKey=KeyName,ParameterValue=キーペア名" \
        --capabilities CAPABILITY_NAMED_IAM
        ../bin/cfn_wait.sh $(AWSPROFILE) $(STACK_NAME)

~省略~

# ECS Cluster
cfnecs:
        $(eval STACK_NAME := Blue21Ecs00PoC)
        aws cloudformation $(CFNCMD) \
        --profile $(AWSPROFILE) \
        --stack-name $(STACK_NAME) \
        --template-body file://`pwd`/cfn_ecs_cluster.yml \
        --parameters \
        "ParameterKey=KeyName,ParameterValue=キーペア名" \
        --capabilities CAPABILITY_NAMED_IAM
        ../bin/cfn_wait.sh $(AWSPROFILE) $(STACK_NAME)

cfnディレクトリで、下記のmakeコマンドを実行すると、CloudFormationのスタックを作成します。
ALLOW_CIDRには、アクセスを許可するIPアドレスを指定します。
$ make cfnall ALLOW_CIDR=1.2.3.4/32

cfnディレクトリで下記コマンドを実行すると、作成したスタック一覧を参照できます。
このコマンドはスタック名に "Blue21" を含むものをリストします。
$ make stackls
aws cloudformation describe-stacks \
--profile blue21 \
--query 'Stacks[?contains(StackName,`Blue21`)].{StackName:StackName,StackStatus:StackStatus,Desc:Description}' \
--output table
------------------------------------------------------------------
|                         DescribeStacks                         |
+-------------------------+------------------+-------------------+
|          Desc           |    StackName     |    StackStatus    |
+-------------------------+------------------+-------------------+
|  Ecs service (WebGoat)  |  Blue21Svc01PoC  |  CREATE_COMPLETE  |
|  Ecs service (OWASP ZAP)|  Blue21Svc00PoC  |  CREATE_COMPLETE  |
|  Ecs cluster (SpotFleet)|  Blue21Ecs00PoC  |  CREATE_COMPLETE  |
|  NLB                    |  Blue21Nlb00PoC  |  CREATE_COMPLETE  |
|  EC2 NatInstance        |  Blue21Nat00PoC  |  CREATE_COMPLETE  |
|  VPC & subnet           |  Blue21Vpc00PoC  |  CREATE_COMPLETE  |
+-------------------------+------------------+-------------------+

動作確認


環境確認


ネットワークACLは下図のとおり。
Indoundは、特定のIPアドレスと、VPC内のIPアドレス以外は遮断します。


NLBは下図のとおり。
OWASP ZAP用に 8080, 8090ポートのリスナーがあります。


NLBのURLはスタック(Blue21Nlb00PoC)の「出力」で確認できます。


ECSは下図のとおり。
「Blue21Svc00PoC」がOWASP ZAP用ECSサービスです。
「Blue21Svc01PoC」がWebGoat用ECSサービスです。
CloudFormation実行直後は、OWASP ZAP と WebGoat のタスクは起動していません。


SSMのマネージドインスタンスは下図のとおり。
ECSインスタンス(Blue21Ecs00PoC)とNATインスタンス(Blue21Nat00PoC)です。


セッションマネージャでSSH


セッションマネージャを使用して、ローカルからECSインスタンスとNATインスタンスにSSHします。
ローカルのSSH設定方法は、下記URLを参照
下図はNATインスタンスの例です。


OWASP ZAP用の日本語フォント設定


ECSインスタンスに日本語フォントを格納します。
まず、下記URLからIPAフォント(TTCファイル)をダウンロードします。

ローカルにダウンロードして解凍したら、下記のようにTTCファイルをECSインスタンスに scp します。
$ curl -OL https://ipafont.ipa.go.jp/IPAfont/IPAGTTC00303.zip
$ unzip IPAGTTC00303.zip
$ ssh -i ~/.ssh/virginia_key.pem ec2-user@i-0e1ad6bf3b649043f 'sudo mkdir -p /data/japanese-font'
$ ssh -i ~/.ssh/virginia_key.pem ec2-user@i-0e1ad6bf3b649043f 'sudo chmod 777 /data/japanese-font'
$ scp -i ~/.ssh/virginia_key.pem ./IPAGTTC00303/ipag.ttc ec2-user@i-0e1ad6bf3b649043f:/data/japanese-font/.
$ ssh -i ~/.ssh/virginia_key.pem ec2-user@i-0e1ad6bf3b649043f 'sudo ls -l /data/japanese-font'
total 6328
-rw-r--r-- 1 ec2-user ec2-user 6476356 Aug 31 00:21 ipag.ttc

OWASP ZAP と WebGoatのタスク起動


OWASP ZAP用ECSサービスの「必要数」を 1 にして、タスクを起動します。
cfnディレクトリで下記コマンドを実行するとCloudFormationで「必要数」を変更します。
$ make cfnsvc00 CFNCMD=update-stack ECS_COUNT=1

次に、WebGoat用ECSサービスの「必要数」を 1 にして、タスクを起動します。
cfnディレクトリで下記コマンドを実行します。
make cfnsvc01 CFNCMD=update-stack ECS_COUNT=1

OWASP ZAPのタスクが下図のように表示されたらOKです。


WebGoatのタスクが下図のように表示されたらOKです。
このIPアドレスは、WebGoatにアクセスするときに使用します。


NLBが下図のように表示されたらNLB経由でアクセスできます。
「healthy」になるまで、少し、時間がかかります。


[MEMO]
  • OWASP ZAPの 8090ポートは、GUIを起動するまで開きません。
    なので 8090ポートのヘルスチェックは 8080ポートで実施しています。

OWASP ZAP のGUIを使う


下記URLでOWASP ZAPのGUIを開きます。
  • http://<NLBのDNS名>:8080/zap/

[Tools]>[Options]を選択し、[Display] で日本語フォント(IPAPGothic)を選択します。


[Language]で日本語を選択し、[OK]ボタンをクリックします。


[File]>[Exit]で、いったん、GUIを終了し
再度、画面を開くと、日本語で表示されます。


スキャンの画面でWebGoatのURL(http://10.0.11.109:8080/WebGoat)を設定してスキャンします


スキャン結果は下図のとおり。


OWASP ZAP のプロキシを使う


OWASP ZAPのプロキシを準備します。
OWASP ZAPのプロキシポート(8090)は、GUIを表示するとOPENします。
ローカルのChromeでOWASP ZAPのGUIを表示します。


下図は、Firefoxブラウザのプロキシ設定です。
プロキシをNLBの8090ポートにします。


Firefox でWEBサイトにアクセスすると、OWASP ZAPがスキャンします。
他人のサイトにアクセスしないように注意!!

WebGoatの画面を使う


まず、ローカルからWebGoatにアクセスする準備をします。
ローカルのブラウザでWebGoatにアクセスするには、NATインスタンスを踏み台にします。
ローカルで下記のようにSSHコマンドを実行すると、ローカルの18080ポートがWebGoatの8080に転送されます。
$ ssh -i ~/.ssh/virginia_key.pem -l ec2-user i-0be7e1fa17895df00 -L 18080:10.0.11.109:8080

ブラウザで "http://localhost:18080/WebGoat" にアクセスするとWebGoatの画面が表示されます。


環境破棄


AWSコンソールで下記のスタックを上から順番に削除します。
ELBを削除するときに、EIPが削除できずにエラーになりますが、少しまってから、再度、削除すると成功します。
------------------------------------------------------------------
|                         DescribeStacks                         |
+-------------------------+------------------+-------------------+
|          Desc           |    StackName     |    StackStatus    |
+-------------------------+------------------+-------------------+
|  Ecs service (WebGoat)  |  Blue21Svc01PoC  |  CREATE_COMPLETE  |
|  Ecs service (OWASP ZAP)|  Blue21Svc00PoC  |  CREATE_COMPLETE  |
|  Ecs cluster (SpotFleet)|  Blue21Ecs00PoC  |  CREATE_COMPLETE  |
|  NLB                    |  Blue21Nlb00PoC  |  CREATE_COMPLETE  |
|  EC2 NatInstance        |  Blue21Nat00PoC  |  CREATE_COMPLETE  |
|  VPC & subnet           |  Blue21Vpc00PoC  |  CREATE_COMPLETE  |
+-------------------------+------------------+-------------------+