6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

OWASP ZAPで診断するためにAWS CDKで実装が必須となる箇所

Posted at

はじめに

AWSのS3, CloudFront, API-Gateway, Lambdaなどを使って実装したサービスに対して、CICDパイプラインの一部として脆弱性診断を流せるか?という確認作業の中で、診断ツールの1つであるOWASP ZAPを試しています。

2021年8月時点、AWS CDKを使って定義したAPI Gatewayに対して、OWASP ZAP Dockerを使って脆弱性診断をおこなう際、API定義の内容によって診断できない場合がありました。
診断できない2つのケースとその対処法について説明します。

  1. 診断できないケース1:Status Codeの定義漏れ
  2. 診断できないケース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を使って遭遇した問題とその対処(結局は定義をちゃんと書きましょうということ)について共有させていただきました。

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?