Azure DevOpsのPipelineでOWASP ZAPを実行してみる
はじめに
2020年12月時点の情報で記事を作成しています。
参照される時期によっては、記事内で使用されているコマンド、画面キャプチャが使用できなくなっている可能性がありますのでご留意ください。
Azure PipelineでOWASP ZAPを実行したい
だいぶ前にGitHubActionsでOWASP ZAPのScanができるようになりました。
例のごとくAzurePipelineでは使用できません。
Azure Pipeline上でOWASP ZAPのスキャンを使用してみましょう。
ZAP Dockerを使用する
Pipeline上でDockerコマンドが実行できるのでそれを使用してPipeline上で脆弱性チェックを行います。
と、いってもZAP Dockerのコマンド等の類の説明は山程あると思いますので省きます。
今回はDocker内で提供されているFullScanを使用しますが
細かい機能を使用したい場合はPowerShell経由でZAP APIを叩いて
Context作成→ContextにURL追加→Spider実行ないつもの流れを行えばいいと思います。
OWASP ZAP2.7でzap-API を使ってSpiderの実行 - 備忘録/にわかエンジニアが好きなように書く
WebAPIをPowerShellからテストする - Qiita
Azure Pipeline上で実行する
すでにPipeline上で実行する記事を書かれている方がいるのでそれを参考にしてみます。
How to run OWASP ZAP Security Tests Part of Azure DevOps CI/CD Pipeline
この記事ではReleaseパイプライン上で実行されているので、MultiStagePipeline上で実行できるようにいじってみます。
また、結果レポートはAzure Artifactsに格納されていますが、すこしアクセスしづらいのでBLOB上に格納してみます。
Pipeline構成
下記な構成のymlとなります
- SPAのWebApplicationをビルド
- Angularアプリケーションをビルドします
- WebAppsにデプロイ 1, デプロイ先のWebAppsの脆弱性調査+Report出力
trigger: branches: include: - master stages: - stage: build jobs: - job: build_job displayName: Build Angular pool: vmImage: ubuntu-latest steps: - task: npm@1 displayName: npm ci inputs: command: custom customCommand: 'ci' - task: npm@1 displayName: npm build inputs: command: custom customCommand: 'run build:ci' - task: ArchiveFiles@2 displayName: 'Archive dist/pipeline-learn-front' inputs: rootFolderOrFile: 'dist/pipeline-learn-front' includeRootFolder: false archiveFile: '$(Build.ArtifactStagingDirectory)/drop.zip' - task: PublishBuildArtifacts@1 displayName: 'Publish Artifact: drop' - stage: deploy dependsOn: build jobs: - deployment: deploy_webapp displayName: Deploy WebApp environment: deploy strategy: runOnce: preDeploy: steps: - download: current artifact: drop deploy: steps: - task: AzureRmWebAppDeployment@4 inputs: ConnectionType: 'AzureRM' azureSubscription: '***' appType: 'webApp' WebAppName: '***' packageForLinux: '$(Pipeline.Workspace)/**/*.zip' - stage: security_test dependsOn: deploy jobs: - job: security_test displayName: SecurityTest pool: vmImage: ubuntu-latest steps: - task: DockerInstaller@0 inputs: dockerVersion: '17.09.0-ce' - task: Bash@3 inputs: targetType: 'inline' script: | chmod -R 777 ./ docker run --rm -v $(pwd):/zap/wrk/:rw -t owasp/zap2docker-stable zap-full-scan.py -t https://okawa-test-webapp.azurewebsites.net/ -j -g gen.conf -x OWASP-ZAP-Report.xml -r scan-report.html true - task: PowerShell@2 inputs: targetType: 'inline' script: | $XslPath = "$($Env:SYSTEM_DEFAULTWORKINGDIRECTORY)/OWASPToNUnit3.xslt" $XslPath $XmlInputPath = "$($Env:SYSTEM_DEFAULTWORKINGDIRECTORY)/OWASP-ZAP-Report.xml" $XmlInputPath $XmlOutputPath = "$($Env:SYSTEM_DEFAULTWORKINGDIRECTORY)/Converted-OWASP-ZAP-Report.xml" $XmlOutputPath $XslTransform = New-Object System.Xml.Xsl.XslCompiledTransform $XslTransform.Load($XslPath) $XslTransform.Transform($XmlInputPath, $XmlOutputPath) - task: PublishTestResults@2 inputs: testResultsFormat: 'NUnit' testResultsFiles: 'Converted-OWASP-ZAP-Report.xml' searchFolder: '$(System.DefaultWorkingDirectory)' - task: AzurePowerShell@5 inputs: azureSubscription: '***' ScriptType: 'InlineScript' azurePowerShellVersion: latestVersion Inline: | $storage = Get-AzStorageAccount -ResourceGroupName "vse-sandbox" -Name "***" $ctx = $storage.Context $containerName = "zap-result" Set-AzStorageBlobContent -File "$($Env:SYSTEM_DEFAULTWORKINGDIRECTORY)/scan-report.html" -Container $containerName -Blob "scan-report.html" -Context $ctx
結果
AzureのCIレポートでテスト結果を確認できるように、レポート出力されたXMLファイルをNUnit形式に変換しています。
結果、下図のようにCIのレポートで発見された脆弱性のレポートを確認できるようになっている感じです。
HTMLで出力されたレポートを見たい場合はBLOBからですね。
Azure Artifactsに上げる場合のハマりどころ
今回はBLOBにあげてみましたが、参考サイトにある通りAzure Artifactsにあげようとした場合にハマったポイントがありました。
準備段階で、AzureArtifactsにaz artifacts universal
を使用してArtifactsを作っているのですが
azコマンドからは403が出てしまいPublishできないといった現象がおきました。
vsts CLIを使用した場合にはエラーは発生しなかったので、azコマンドでエラーが発生した場合はvsts CLIを使用してみるといいかもしれません。
まとめ
今回は雑にCIに組み込めるか程度のレベルで試してみました。
AngularアプリのようなSPA構成のアプリの場合は単純なSpiderではなくAjaxスパイダーを使用したり
試行時間を決定しないと永遠に終わらなかったり…と考慮することは多そうなので
実際にしっかり運用するとなったら直接APIを叩いてガリガリ組んでいくしかないかなと思います。
と言っても、知らん間にガチ脆弱性チェックを行ってデータが壊れるのも色々嫌な感じですし
サーバーの設定レベルだけチェックするような現在の構成のほうが、自動実行するレベルとしては扱いやすいのかもしれないですね。