はじめに
AWSのS3, CloudFront, API-Gateway, Lambdaなどを使って実装したサービスに対して、CICDパイプラインの一部として脆弱性診断を流せるか?という確認作業の中で、診断ツールの1つであるOWASP ZAPを試しています。
2021年8月時点、AWS CDKを使って定義したAPI Gatewayに対して、OWASP ZAP Dockerを使って脆弱性診断をおこなう際、API定義の内容によって診断できない場合がありました。
診断できない2つのケースとその対処法について説明します。
- 診断できないケース1:Status Codeの定義漏れ
- 診断できないケース2:Request Parametersの定義漏れ
※ 以下、動作確認で使用したコンテナイメージは owasp/zap2docker-stable
になります。
診断できないケース1:Status Codeの定義漏れ
診断NGとなるCDKのソースコード
// <中略>
// GETメソッドが返すレスポンスの定義がない
const userId = users.addResource("{userId}")
userId.addMethod("GET")
// <以下省略>
定義がないとどうなるか
- 2021/07月頃はNullPointerExceptionで落ちて終了していました
- 2021/08/19以降は、zap起動後に、以下のwarningが出て診断が実行されずに終了しました。
- 今回の問題解決のヒントとなる
Import warnings
のログはzapのシェルスクリプトを起動してすぐ出力されているのですが、その後Add-onのログが大量に出て流れてしまうので、見落としに注意が必要です。
2021-08-19 07:04:13,560 Import warnings: ['attribute openapi is missing',
"attribute paths.'/users'(post).responses is missing",
"attribute paths.'/users/{userId}'(get).responses is missing",
"attribute paths.'/users/{userId}'(delete).responses is missing"]
2021-08-19 07:04:13,560 Failed to import any URLs
Traceback (most recent call last):
File "/zap/zap-api-scan.py", line 456, in main
raise NoUrlsException()
NoUrlsException
# 中略:Add-onをロードするログが続く
9160 [ZAP-daemon] INFO org.parosproxy.paros.CommandLine - Add-on downloaded to: /home/zap/.ZAP_D/plugin/pscanrulesAlpha-alpha-33.zap
9161 [ZAP-daemon] INFO org.zaproxy.zap.DaemonBootstrap - ZAP is now listening on 0.0.0.0:37715
2021-08-19 07:04:13,562 Trigger hook: pre_exit, args: 3
診断OKなCDKのソースコード
// --- 診断OKなCDKのソースコード ---
const userId = users.addResource("{userId}")
userId.addMethod("GET",
integration,
{ // 最低限これがあれば診断エラーがでない状態。書き方の詳細はAPIドキュメント参照
methodResponses: [{statusCode: '200' }],
}
);
// <以下省略>
補足
API仕様的には以下のようにaddResourceの第二引数の中にdefaultMethodOptionsの値として定義することも可能のようですが、実際やってみると、API GatewayからエクスポートしたOpenAPI定義ファイルでは各メソッドのresponseとしては定義されず、上記と同じエラーになりました。
const userId = users.addResource("{userId}", {
// NG:このようにaddResourceの引数で与えても各メソッドのレスポンス定義には
// 反映されなかった
defaultMethodOptions: {
methodResponses: [{statusCode: '200' }]
}
})
診断できないケース2:Request Parametersの定義漏れ
OWASP ZAP(Docker)で診断する際は、パスやクエリにあるパラメータをCDKのコード上で定義してやる必要がありました。
例えば以下の例では、userIdというパスパラメータを使っています。
診断NGなCDKのソースコード
// path parameter {userId}の定義をしていない
const userId = users.addResource("{userId}")
userId.addMethod("GET", integration,
{
methodResponses: [{statusCode: '200' }],
}
);
定義がないとどうなるか
- api scan実行時に以下のような「parameterの定義がないよ」というwarningが出て、(add onをロードしたログが出た後に)診断されず処理が終わります。
- 2021/08/04ぐらいから発生し始めた現象です
2021-08-19 05:11:32,080 Import warnings: ['attribute openapi is missing',
"attribute paths.'/users/{userId}'. Declared path parameter userId needs
to be defined as a path parameter in path or operation level"]
2021-08-19 05:11:32,080 Failed to import any URLs
Traceback (most recent call last):
File "/zap/zap-api-scan.py", line 456, in main
raise NoUrlsException()
NoUrlsException
<中略: Add-onの読み込みログ>
2021-08-19 05:11:43,562 Trigger hook: pre_exit, args: 3
診断OKなCDKのソースコードの書き方:その1
// addResourceの第二引数にresourceOptionsを定義してその中に
// defaultMethodOptions>requestParametersを定義
const userId = users.addResource("{userId}", {
defaultMethodOptions: {
requestParameters:{'method.request.path.userId':true}
}
})
userId.addMethod("GET", integration,
{
methodResponses: [{statusCode: '200' }]
}
);
addResourceの第二引数がresourceOptionsになります。そのプロパティとして、defaultMethodOptions>requestParametersを追加してuserIdを宣言します。詳細な仕様は以下ドキュメントを参照してください。
診断OKなCDKのソースコードの書き方:その2
// addResourceはそのまま。代わりに”GET"などメソッド毎に
// requestParametersを定義する
// ただしこの場合、(OPTIONS含め)定義する全てのメソッドに
// requestParametersを定義する必要がある
const userId = users.addResource("{userId}")
userId.addMethod("GET", integration,
{
methodResponses: [{statusCode: '200' }],
requestParameters:{'method.request.path.userId':true}
}
);
// 以下省略
こちらの書き方では、addResource
はそのまま。代わりに”GET"などメソッド毎に requestParameters
を定義します。
ただしこの場合、(OPTIONS含め)定義するすべてのメソッドにrequestParameters
を定義する必要があります。
上記サンプルコード中のクエリパラメータを示すキー method.request.path.userId
の書き方は以下のサイトに書き方の例があります。
- 参考: request-response-data-mappings
- たとえばメソッドのクエリ文字列であれば、
method.request.querystring.PARAM_NAME
のようになります - booleanの値部分は必須パラメータかどうかを示しています
おわりに
2021年7~8月にOWASP ZAP Dockerを使って遭遇した問題とその対処(結局は定義をちゃんと書きましょうということ)について共有させていただきました。