Cloudflare Vulnerability Scanner を使うと、Broken Object Level Authorization(BOLA)などの脆弱性について API エンドポイントを検査できます。このガイドでは、Cloudflare API で最初の脆弱性スキャンを実行する手順を説明します。
次のものが必要です。
- アカウント内に、少なくとも 1 つのゾーンがあること。
- スキャン対象 API を記述した OpenAPI スキーマ。
- 対象向けの API 認証情報。スキャナーは、BOLA 脆弱性を検査するために、異なるユーザーとして認証する必要があります。
API リクエストは、ベース URL https://api.cloudflare.com/client/v4/ を使い、Authorization ヘッダーの Bearer トークンで認証します。
対象アカウントに次の 権限 を持つ API トークンを、Cloudflare ダッシュボードで 作成 します。Account > API Gateway > Edit
以降のコマンドで使えるよう、API トークンと、Cloudflare ダッシュボードのアカウント Overview ページにある Account Tag を環境変数として保存します。
export CLOUDFLARE_API_TOKEN="<YOUR_API_TOKEN>"
export ACCOUNT_ID="<YOUR_ACCOUNT_ID>"ターゲット環境は、スキャナーが何をスキャンするかを定義します。現在サポートしているターゲットタイプは zone だけです。
Cloudflare ダッシュボードのゾーン Overview ページで Zone Tag を確認し、エクスポートします。
export ZONE_TAG="<YOUR_ZONE_TAG>"次の POST リクエストで、ターゲット環境を作成します。
curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/target_environments" \
--header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
--header "Content-Type: application/json" \
--data '{
"name": "Production API",
"description": "Main production zone for API scanning",
"target": {
"type": "zone",
"zone_tag": "'"${ZONE_TAG}"'"
}
}'レスポンスのターゲット環境 ID を、変数 TARGET_ENV_ID に保存します。
(任意)次の URL へ GET リクエストを送ると、ターゲット環境を確認できます。
https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/target_environments/${TARGET_ENV_ID}現在、スキャナーは BOLA スキャンをサポートしています。次の 2 組の認証情報が必要です。
- Owner:検査対象のリソースを所有する正当なユーザー。
- Attacker:所有者のリソースへアクセスできないはずの、別の正当なユーザー。
スキャナーは両方のユーザーとして認証し、Attacker が Owner のリソースへアクセスできるかを確認します。各認証情報は、1 つ以上の credential を含む credential set にまとめます。
次の POST リクエストで、Owner の credential set と Attacker の credential set を作成します。
curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/credential_sets" \
--header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
--header "Content-Type: application/json" \
--data '{ "name": "Owner Credentials" }'
# Export the ID from the response
export OWNER_CRED_SET_ID="<OWNER_CRED_SET_ID>"curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/credential_sets" \
--header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
--header "Content-Type: application/json" \
--data '{ "name": "Attacker Credentials" }'
# Export the ID from the response
export ATTACKER_CRED_SET_ID="<ATTACKER_CRED_SET_ID>"credential は、スキャナーがリクエストに付与する、1 つの認証トークンまたはセッション値を表します。
次の POST リクエストで、Owner と Attacker の credential をそれぞれのセットへ追加します。
curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/credential_sets/${OWNER_CRED_SET_ID}/credentials" \
--header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
--header "Content-Type: application/json" \
--data '{
"name": "Owner Bearer Token",
"location": "header",
"location_name": "authorization",
"value": "Bearer eyJhbGciOiJSUzI1NiIs...owner-token"
}'curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/credential_sets/${ATTACKER_CRED_SET_ID}/credentials" \
--header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
--header "Content-Type: application/json" \
--data '{
"name": "Attacker Session Cookie",
"location": "cookie",
"location_name": "session_id",
"value": "attacker-session-token-value"
}'(任意)次の URL へ GET リクエストを送ると、セット内の credential を一覧表示できます。
https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/credential_sets/<CRED_SET_ID>/credentialsターゲット環境と 2 つの credential set が用意できたら、BOLA スキャンを開始できます。
OpenAPI スキーマは文字列形式にします。たとえば jq を使います。
OPEN_API_SCHEMA=$(jq -c . < openapi.json)次の POST リクエストでスキャンを開始します。
curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans" \
--header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
--header "Content-Type: application/json" \
--data "$(jq -n \
--arg te_id "$TARGET_ENV_ID" \
--arg schema "$OPEN_API_SCHEMA" \
--arg owner "$OWNER_CRED_SET_ID" \
--arg attacker "$ATTACKER_CRED_SET_ID" \
'{
target_environment_id: $te_id,
scan_type: "bola",
open_api: $schema,
credential_sets: { owner: $owner, attacker: $attacker }
}')"レスポンスのスキャン ID を保存します。
export SCAN_ID="<SCAN_ID>"スキャンの状態は、GET リクエストで確認できます。
curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans/${SCAN_ID}" \
--header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}"スキャンの状態が completed になると、検査した脆弱性の詳細な検出結果を含むレポートを取得できます。
curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans/${SCAN_ID}" \
--header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}"jq を使うと、レポート結果を要約しやすくなります。
curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans/${SCAN_ID}" \
--header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" | jq '.result.report.report.tests[] | {test_verdict: .verdict, steps: [.steps | to_entries[] | {step: (.key + 1), method: .value.request.method, url: .value.request.url, role: .value.request.credential_set.role, status: (if .value.errors | length > 0 then "error" else "ok" end)}]}'jq コマンドを付けると、出力が要約されます。次の例では、ステップ 3 で Attacker が DELETE エンドポイントへアクセスできています。
{
"test_verdict": "warning",
"steps": [
{
"step": 1,
"method": "POST",
"url": "https://api.example.com/v1/orders",
"role": "owner",
"status": "ok"
},
{
"step": 2,
"method": "GET",
"url": "https://api.example.com/v1/orders",
"role": "attacker",
"status": "ok"
},
{
"step": 3,
"method": "DELETE",
"url": "https://api.example.com/v1/orders/bdc64e8a-deec-4374-92c0-4fe91d1650bb",
"role": "attacker",
"status": "error"
}
]
}よくあるパターンは、スキャンが完了するまで状態をポーリングし、その後レポートを取得することです。
while true; do
STATUS=$(curl --silent \
"https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans/${SCAN_ID}" \
--header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" | jq -r '.result.status // empty')
echo "Scan status: ${STATUS:-unknown}"
case "$STATUS" in
completed) echo "Scan finished. Fetching report..."; break ;;
failed) echo "Scan failed." >&2; exit 1 ;;
*) sleep 10 ;;
esac
done
curl --silent \
"https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans/${SCAN_ID}/report" \
--header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" | jq .オープンベータ中は、大きな OpenAPI スペックがある場合、スキャナー向けにスペックを最適化した方がよいことがあります。
API のスキャン計画を作る AI モデルには、128k トークンのコンテキスト制限があります。ディスク上のファイルサイズでは、おおよそ 40〜60kB に相当します。スキーマがこのサイズを超える場合は、より小さいファイルへ分割する必要があります。
同様に、意味のあるユースケースごとに個別の OpenAPI ファイルを作ると、スキャン結果がより詳しくなることがあります。たとえば、アプリケーションがアカウント変更、ソーシャル共有、お気に入り登録をサポートしている場合、ベータ期間中はユースケースごとにスペックを分割すると、テストカバレッジが上がることがあります。
Vulnerability Scanner は現在、Enterprise の API Shield お客様だけが利用できます。今後、Cloudflare はスキャンタイプを追加し、その時点でスキャナーの提供範囲を広げます。
credential を作成するとき、location フィールドは、スキャナーがリクエスト中に credential をどこへ付けるかを決めます。
| Location | location_name |
使用例 |
|---|---|---|
| header | HTTP ヘッダー名 | Bearer トークンを付けた Authorization ヘッダー。 |
| cookie | Cookie 名 | セッショントークンを持つ session_id Cookie。 |
credential set には、複数の credential を含められます。たとえば、Authorization ヘッダーの Bearer トークンと、X-CSRF-Token ヘッダーの CSRF トークンの両方が必要な API では、セット内に 2 つの credential を設定します。