Cloudflare OWASP Core Ruleset の詳細を確認する

# 目的
以下の記事も参考にしながら、Cloudflare OWASP Core Ruleset の詳細を確認します。

- [Cloudflare Firewall Event Log で Managed Ruleset か OWASP Core Ruleset かを判別する - Qiita](https://qiita.com/khayama/items/146d127802b0c52676a1)

# Ruleset の取得
以下のコマンドで Ruleset が取得できます。

```shell:
export ZONE_ID='YOUR_ZONE_ID'

http -A creds "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets" \
| jq -r '.result[] | select (.name == "Cloudflare OWASP Core Ruleset")'
```

```json:rulesets.json
{
  "id": "4814384a9e5d4991b9815dcfc25d2f1f",
  "name": "Cloudflare OWASP Core Ruleset",
  "description": "Cloudflare's implementation of the Open Web Application Security Project (OWASP) ModSecurity Core Rule Set. We routinely monitor for updates from OWASP based on the latest version available from the official code repository",
  "source": "firewall_managed",
  "kind": "managed",
  "version": "85",
  "last_updated": "2023-07-10T11:41:55.46098Z",
  "phase": "http_request_firewall_managed"
}
```

# Rules の取得
以下のコマンドで Rulesets 内の Rules が取得できます。

```shell:
export ZONE_ID='YOUR_ZONE_ID'

http -A creds "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/4814384a9e5d4991b9815dcfc25d2f1f" \
| jq -r '.result.rules[].action' | uniq -c
```

```text:result
 178 score
   1 block
```

最後のルール以外は `"action": "score"` でスコアが加算されるだけでブロックはしません。

最後の `"949110: Inbound Anomaly Score Exceeded"` ルールにより、`score_threshold` 以上のスコアに対してブロックアクションをとります。

```shell:
http -A creds "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/4814384a9e5d4991b9815dcfc25d2f1f" \
| jq -r '.result.rules[] | del(.ref,.version,.categories,.last_updated)'
```

https://gist.github.com/kyouheicf/b54fad669724890ea530b4e40717453a

# Paranoia Level

チューニングパラメータの一つで
要は適用されるルールの数を Paranoia Level と呼んでいるだけです。

- [Paranoia Levels :: Core Rule Set Documentation](https://coreruleset.org/docs/configuring/paranoia_levels/)
- [Working with Paranoia Levels – OWASP ModSecurity Core Rule Set](https://coreruleset.org/20211028/working-with-paranoia-levels/)

Paranoia Level = 3 だと、107+44+18 のルールが有効化され、
Paranoia Level = 4 の 7 つのルールは無効される形です。


|      | `paranoia-level-1` rules (107) | `paranoia-level-2` rules (44) | `paranoia-level-3` rules (18) | `paranoia-level-4` rules (7)|
| ---- | ------------------------ | ------------------------ | ------------------------ | ------------------------ |
| PL4  | Enabled                  | Enabled                  | Enabled                  | Enabled                  |
| PL3  | Enabled                  | Enabled                  | Enabled                  | Disabled                 |
| PL2  | Enabled                  | Enabled                  | Disabled                 | Disabled                 |
| PL1  | Enabled                  | Disabled                 | Disabled                 | Disabled                 |


```shell:
% http -A creds "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/4814384a9e5d4991b9815dcfc25d2f1f" \
| jq -r '[.result.rules[] | select (.categories[]? | contains("paranoia-level-1"))] | length'
107

% http -A creds "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/4814384a9e5d4991b9815dcfc25d2f1f" \
| jq -r '[.result.rules[] | select (.categories[]? | contains("paranoia-level-2"))] | length'
44

% http -A creds "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/4814384a9e5d4991b9815dcfc25d2f1f" \
| jq -r '[.result.rules[] | select (.categories[]? | contains("paranoia-level-3"))] | length'
18

% http -A creds "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/4814384a9e5d4991b9815dcfc25d2f1f" \
| jq -r '[.result.rules[] | select (.categories[]? | contains("paranoia-level-4"))] | length'
7
```

## Paranoia Level タグがないルール
以下のルールは Paranoia Level タグがないため、Paranoia Level で有効・無効の設定はされません。

```shell:
http -A creds "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/4814384a9e5d4991b9815dcfc25d2f1f" \
| jq -r '.result.rules[] | select(any(.categories[]?; contains("paranoia-level-1"))|not) | select(any(.categories[]?; contains("paranoia-level-2"))|not) | select(any(.categories[]?; contains("paranoia-level-3"))|not) | select(any(.categories[]?; contains("paranoia-level-4"))|not)'
```

```json:pl-independent-rules.json
{
  "id": "7e22a50933244f18a3695e4e1fe97a48",
  "version": "83",
  "action": "score",
  "categories": [
    "application-multi",
    "attack-protocol",
    "capec-1000",
    "capec-210",
    "capec-272",
    "language-multi",
    "platform-multi"
  ],
  "description": "920181: Content-Length and Transfer-Encoding headers present.",
  "last_updated": "2023-07-10T11:41:55.46098Z",
  "ref": "475aa82e71ee8d83d9077349eb60c82b",
  "enabled": true,
  "action_parameters": {
    "increment": 3
  }
}
{
  "id": "c966380737654b0abec157f24974ad9a",
  "version": "83",
  "action": "score",
  "categories": [
    "application-multi",
    "capec-1000",
    "capec-136",
    "capec-152",
    "capec-248",
    "language-ldap",
    "platform-multi"
  ],
  "description": "921200: LDAP Injection Attack",
  "last_updated": "2023-07-10T11:41:55.46098Z",
  "ref": "1647369b168998d06b23538c12a80281",
  "enabled": true,
  "action_parameters": {
    "increment": 5
  }
}
{
  "id": "6179ae15870a4bb7b2d480d4843b323c",
  "version": "84",
  "action": "block",
  "score_threshold": 40,
  "description": "949110: Inbound Anomaly Score Exceeded",
  "last_updated": "2023-07-10T11:41:55.46098Z",
  "ref": "ad0beb2fce9f149e565ee78d6e659d47",
  "enabled": true
}
```

# OWASP Anomaly Score Threshold
スコア加算の結果を判定する閾値を以下の3段階に変更可能です。

Paranoia Level と合わせて調整を検討するのが良いでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/5b89969b-c6eb-ebea-8208-af299d72ae3c.png)


# OWASP Action
閾値トリガーを受けて実施されるアクションを以下のものに変更可能です。

基本はブロックで良いと思いますが、導入初期フェーズでは Log アクションで様子を見ることもできるでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/766a5e5a-79b5-a9fa-db7e-669c27804101.png)


# まとめ

Cloudflare OWASP Core Ruleset のチューニングは、以下のパターンに分けられます。

- Score Threshold を変更する
- Paranoia Level を変更する
- 個別のルールを有効化・無効化する
- 全体のアクションを変更する

アプリケーションで検知したパターンによって、検討してみると良いでしょう。