Cloudflare Firewall Event Log で Managed Ruleset か OWASP Core Ruleset かを判別する

# 結論

- Rule ID が `6179ae15870a4bb7b2d480d4843b323c` なら Cloudflare OWASP Core Ruleset
- そうでないなら Cloudflare Managed Ruleset 

```json
{
  "action": "block",
  "description": "949110: Inbound Anomaly Score Exceeded",
  "enabled": true,
  "id": "6179ae15870a4bb7b2d480d4843b323c",
  "last_updated": "2022-06-20T17:07:28.59768Z",
  "ref": "ad0beb2fce9f149e565ee78d6e659d47",
  "score_threshold": 40, # "Low - 60 and higher"、"High - 25 and higher" 設定に応じて上書きされます
  "version": "79"
}
```

# Cloudflare OWASP Core Ruleset の一覧取得

API コール準備

```shell
export EMAIL='YOUR_EMAIL'
export APIKEY='YOUR_APIKEY'
export ACCOUNT_ID='YOUR_ACCOUNT_ID'
export ZONE_ID='YOUR_ZONE_ID'
```

Ruleset ID の取得

```shell
curl -sX GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets" \
     -H "X-Auth-Email: $EMAIL" \
     -H "X-Auth-Key: $APIKEY" \
     -H "Content-Type: application/json" | jq -r '.result[] | select (.name == "Cloudflare OWASP Core Ruleset")'
```

```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": "80",
  "last_updated": "2022-06-20T17:07:28.59768Z",
  "phase": "http_request_firewall_managed"
}
```

ルール一覧の取得

```shell
curl -sX GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/4814384a9e5d4991b9815dcfc25d2f1f" \
     -H "X-Auth-Email: $EMAIL" \
     -H "X-Auth-Key: $APIKEY" \
     -H "Content-Type: application/json" | jq -r '.result.rules[]'
```

```json
{
  "id": "8ac8bc2a661e475d940980f9317f28e1",
  "version": "78",
  "action": "score",
  "categories": [
    "application-multi",
    "attack-generic",
    "capec-1000",
    "capec-210",
    "capec-220",
    "capec-272",
    "capec-274",
    "language-multi",
    "paranoia-level-1",
    "pci-12-1",
    "platform-multi"
  ],
  "description": "911100: Method is not allowed by policy",
  "last_updated": "2022-06-20T17:07:28.59768Z",
  "ref": "c5f1c0931bfbf37339d4c6e292caec43",
  "enabled": true,
  "action_parameters": {
    "increment": 5
  }
}
...
{
  "id": "c2e1451cfff1400db51a760a852d81eb",
  "version": "76",
  "action": "score",
  "categories": [
    "application-multi",
    "attack-sqli",
    "capec-1000",
    "capec-152",
    "capec-248",
    "capec-66",
    "language-multi",
    "paranoia-level-3",
    "pci-6-5-2",
    "platform-multi",
    "beta"
  ],
  "description": "942101: SQL Injection Attack Detected via libinjection - beta",
  "last_updated": "2022-06-20T17:07:28.59768Z",
  "ref": "7238f2be8107287fa0990a2e413e24c82",
  "enabled": true,
  "action_parameters": {
    "increment": 0
  }
}
{
  "id": "6179ae15870a4bb7b2d480d4843b323c",
  "version": "79",
  "action": "block",
  "score_threshold": 40,
  "description": "949110: Inbound Anomaly Score Exceeded",
  "last_updated": "2022-06-20T17:07:28.59768Z",
  "ref": "ad0beb2fce9f149e565ee78d6e659d47",
  "enabled": true
}
```

# Cloudflare OWASP Core Ruleset のアクション

OWASP Core Ruleset にある Rule のアクションを見てみると、`score` が 178 個で `block` が 1 個であることがわかります。

```shell
curl -sX GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/4814384a9e5d4991b9815dcfc25d2f1f" \
     -H "X-Auth-Email: $EMAIL" \
     -H "X-Auth-Key: $APIKEY" \
     -H "Content-Type: application/json" | jq -r '.result.rules[].action' | uniq -c  
```

```shell
178 score
   1 block
```

`score` となっているルールは、最終評価のためのスコアを加算するだけでトラフィックをブロックしたりするものではありません。

![image-20220906151114474](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/image-20220906151114474.png)

`block` となっているルールは、OWASP Core Ruleset 全体でアノマリスコア閾値に対するアクションとして設定できます。

![image-20220906154411210](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/image-20220906154411210.png)

デフォルトでは、アノマリスコア閾値 `Medium - 40 and higher` の設定が反映され、`"score_threshold": 40` となっています。

```shell
curl -sX GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/4814384a9e5d4991b9815dcfc25d2f1f" \
     -H "X-Auth-Email: $EMAIL" \
     -H "X-Auth-Key: $APIKEY" \
     -H "Content-Type: application/json" | jq -r '.result.rules[] | select (.action == "block")'         
```

```json
{
  "id": "6179ae15870a4bb7b2d480d4843b323c",
  "version": "79",
  "action": "block",
  "score_threshold": 40,
  "description": "949110: Inbound Anomaly Score Exceeded",
  "last_updated": "2022-06-20T17:07:28.59768Z",
  "ref": "ad0beb2fce9f149e565ee78d6e659d47",
  "enabled": true
}
```

アノマリスコア閾値 `High - 25 and higher` や `Paranoia Level 1` の設定にカスタマイズしている場合は、

![image-20220906154442160](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/image-20220906154442160.png)

以下のように `"phase": "http_request_firewall_managed"` の `entrypoint` に対して `override` が設定されます。

```shell
curl -sX GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/phases/http_request_firewall_managed/entrypoint" \
     -H "X-Auth-Email: $EMAIL" \
     -H "X-Auth-Key: $APIKEY" \
     -H "Content-Type: application/json" | jq -r '.result.rules[] | select (.action_parameters.id == "4814384a9e5d4991b9815dcfc25d2f1f")'
```

```json
{
  "id": "12cab42c142b4f4f8fcfa299d67bb562",
  "version": "1",
  "action": "execute",
  "expression": "true",
  "description": "zone",
  "last_updated": "2022-09-06T06:43:03.500308Z",
  "ref": "12cab42c142b4f4f8fcfa299d67bb562",
  "enabled": true,
  "action_parameters": {
    "id": "4814384a9e5d4991b9815dcfc25d2f1f",
    "version": "latest",
    "overrides": {
      "categories": [
        {
          "category": "paranoia-level-2",
          "enabled": false
        },
        {
          "category": "paranoia-level-3",
          "enabled": false
        },
        {
          "category": "paranoia-level-4",
          "enabled": false
        }
      ],
      "rules": [
        {
          "id": "6179ae15870a4bb7b2d480d4843b323c",
          "score_threshold": 25
        }
      ]
    }
  }
}
```

# Cloudflare ダッシュボードでの Firewall Events フィルタ

「Service equals Managed rules」で Cloudflare Managed Ruleset か OWASP Core Ruleset であることを絞れます。

![image-20220906155110243](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/image-20220906155110243.png)

Ruleset ID `4814384a9e5d4991b9815dcfc25d2f1f` で OWASP Core Ruleset のみに絞れます。
（does not equal で Cloudflare Managed Ruleset のみに絞れます。）

![image-20220906155150431](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/image-20220906155150431.png)

Rule ID `6179ae15870a4bb7b2d480d4843b323c` で OWASP Core Ruleset のみに絞れます。

（does not equal で Cloudflare Managed Ruleset のみに絞れます。）

![image-20220906155210416](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/image-20220906155210416.png)

# 参考：Cloudflare Logs での Firewall Events フィルタ（Google Cloud Storage）

API コール準備

```shell
export BUCKET='kyouhei'
export FOLDER='firewall_event'
```

Cloudflare Managed Ruleset のみ

```shell
gsutil list gs://$BUCKET/$FOLDER/$(date +"%Y%m%d") | grep .log.gz | tail -n 10 | while read line
do
  gsutil cat $line | gunzip | jq '.|select (.Source == "firewallmanaged") | select (.RuleID != "6179ae15870a4bb7b2d480d4843b323c") | select (.Action != "skip")'
done
```

```json
{
  "Action": "block",
  "ClientIP": "209.145.56.163",
  "ClientRequestHost": "example.com",
  "ClientRequestMethod": "GET",
  "ClientRequestPath": "/.env",
  "ClientRequestQuery": "",
  "Datetime": "2022-09-05T23:08:48Z",
  "EdgeResponseStatus": 403,
  "RayID": "7462a104bdc14941",
  "ClientASN": 40021,
  "ClientASNDescription": "CONTABO",
  "ClientCountry": "us",
  "ClientIPClass": "noRecord",
  "ClientRefererHost": "",
  "ClientRefererPath": "",
  "ClientRefererQuery": "",
  "ClientRefererScheme": "",
  "ClientRequestProtocol": "HTTP/1.1",
  "ClientRequestScheme": "http",
  "ClientRequestUserAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36",
  "EdgeColoCode": "STL",
  "Kind": "firewall",
  "MatchIndex": 0,
  "Metadata": {
    "ruleset_version": "102",
    "version": "102",
    "type": "customer"
  },
  "OriginResponseStatus": 0,
  "OriginatorRayID": "00",
  "RuleID": "23548ee2b36547a1be09bb2c0550c529",
  "Source": "firewallmanaged"
}
```

OWASP Core Ruleset のみ

```shell
gsutil list gs://$BUCKET/$FOLDER/$(date +"%Y%m%d") | grep .log.gz | tail -n 10 | while read line
do
  gsutil cat $line | gunzip | jq '.|select (.Source == "firewallmanaged") | select (.RuleID == "6179ae15870a4bb7b2d480d4843b323c")'
done
```

```json
{
  "Action": "block",
  "ClientIP": "240d:1a:a55:9d00:b806:2139:ec88:6c77",
  "ClientRequestHost": "example.com",
  "ClientRequestMethod": "POST",
  "ClientRequestPath": "/",
  "ClientRequestQuery": "",
  "Datetime": "2022-09-08T05:03:30Z",
  "EdgeResponseStatus": 403,
  "RayID": "7475235539a0e354",
  "ClientASN": 2527,
  "ClientASNDescription": "SO-NET Sony Network Communications Inc.",
  "ClientCountry": "jp",
  "ClientIPClass": "noRecord",
  "ClientRefererHost": "",
  "ClientRefererPath": "",
  "ClientRefererQuery": "",
  "ClientRefererScheme": "",
  "ClientRequestProtocol": "HTTP/2",
  "ClientRequestScheme": "https",
  "ClientRequestUserAgent": "curl/7.82.0-DEV",
  "EdgeColoCode": "NRT",
  "Kind": "firewall",
  "MatchIndex": 0,
  "Metadata": {
    "ruleset_version": "77",
    "version": "76",
    "type": "customer",
    "score_total": "117",
    "score_rules": "[\"6fac9ca10e764e06a0e242791813a269\",\"a6be45d4905042b9964ff81dc12e41d2\",\"8798ef68f5144daa86219e082563548f\",\"61fe42e94df24ce3b22bed0539838bb3\",\"753c98e3a15f4a389ea0b196c91b7247\",\"89783961975749f0a1694572d4ebd4cf\",\"83ab9971710a4444959dad71776b0bec\",\"807e8b69772c4d8897552ad3a078d4ef\",\"91bdd244810c4b2fb7868436973c7a5c\",\"68996db700bc4aaca4c22befaf661a66\",\"1fd9e041e6944a5c9c080d19346650ed\",\"efc7b690312c4488bb10d6bc565cd049\",\"be337f9e5266487a8e67c008d732161b\",\"79239a25d12f4ced90b9beade71d0764\",\"6afe6795ee6a48d6a1dfe59255395a78\",\"f394c2277cba4406b408c9d1feb8fadb\",\"5a6f5a57cde8428ab0668ce17cdec0c8\",\"a1e6edf90e6541948dc86318d90595f6\",\"5e4903d6afa841c9b88b96203297003f\",\"d12ad6d1bc0c42b3affe0cee682bb405\",\"052dcdf764834ffa997afbf2276a6986\",\"2380cd409b604c2a9273042f3eb29c4e\",\"f5aebedc99a14c8d9e8cfa2ce5f94216\",\"edf8c37cc81747d382690b3c77e82ce4\",\"1129dfb383bb42e48466488cf3b37cb1\"]"
  },
  "OriginResponseStatus": 0,
  "OriginatorRayID": "00",
  "RuleID": "6179ae15870a4bb7b2d480d4843b323c",
  "Source": "firewallmanaged"
}
```