INTEGRITY Dokumentace

Konfigurace ochrany proti škodlivým GraphQL dotazům přes API

Použijte Cloudflare GraphQL API , abyste shromáždili data o aktuálním využití vašeho GraphQL API a nakonfigurovali ochranu Cloudflare proti škodlivým dotazům GraphQL tak, aby škodlivé dotazy zaznamenávala nebo blokovala.

Úvod

Velikost dotazu je definována jako počet koncových polí (listů) v dotazu, zatímco hloubka dotazu je nejhlubší úroveň, ve které se list vyskytuje. Velikost následujícího dotazu bude například hlášena jako 4 (terminalField[1-4] all contribute to this counter), a hloubka se uvede jako 3 (terminalField3 and terminalField4 are at depth level 3).

Dotaz GraphQL
{
	terminalField1
	nonTerminalField1(filter: 123) {
		terminalField2
		nonTerminalField2 {
			terminalField3
			terminalField4
		}
	}
}

Shromážděte statistiky GraphQL

Pomocí nového apiGatewayGraphqlQueryAnalyticsGroups uzel v Cloudflare GraphQL API a můžete získat apiGatewayGraphqlQuerySize a apiGatewayGraphqlQueryDepth dimenze.

Dotaz GraphQL
query ApiGatewayGraphqlQueryAnalytics(
	$zoneTag: string
	$start: Time
	$end: Time
) {
	viewer {
		zones(filter: { zoneTag: $zoneTag }) {
			apiGatewayGraphqlQueryAnalyticsGroups(
				limit: 100
				orderBy: [
					apiGatewayGraphqlQuerySize_DESC
					apiGatewayGraphqlQueryDepth_DESC
				]
				filter: { datetime_geq: $start, datetime_leq: $end }
			) {
				count
				dimensions {
					apiGatewayGraphqlQuerySize
					apiGatewayGraphqlQueryDepth
				}
			}
		}
	}
}

S výše uvedeným dotazem získáte následující odpověď:

Odpověď
{
	"data": {
		"viewer": {
			"zones": [
				{
					"apiGatewayGraphqlQueryAnalyticsGroups": [
						{
							"count": 10,
							"dimensions": {
								"apiGatewayGraphqlQueryDepth": 1,
								"apiGatewayGraphqlQuerySize": 11
							}
						},
						{
							"count": 10,
							"dimensions": {
								"apiGatewayGraphqlQueryDepth": 1,
								"apiGatewayGraphqlQuerySize": 2
							}
						}
					]
				}
			]
		}
	},
	"errors": null
}

V ukázkové odpovědi Cloudflare ve zvoleném časovém rozmezí zaznamenal 10 požadavků s hloubkou 1 a velikostí 11 a 10 požadavků s hloubkou 1 a velikostí 2.

Analyzujte statistiky GraphQL

Odpověď můžete použít k výpočtu percentilů napříč atributy a nastavit práh toho, co je povoleno. Můžete například použít jednoduchou heuristiku, jako je 1.5 * p99 pro velikost nebo hloubku dotazu.

Zde je jednoduchý skript v Pythonu, který na základě výše uvedeného výstupu odpovědi API GraphQL (ve formátu JSON souboru) vypíše percentily velikosti a hloubky dotazu:

Skript v Pythonu
#!/usr/bin/env python3

import json
import numpy as np
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--response", help="Path to the API JSON response file with the apiGatewayGraphqlQueryAnalyticsGroups node", required=True)
args = parser.parse_args()
with open(args.response) as f:
    query_sizes = np.array([], dtype=np.uint16)
    query_depths = np.array([], dtype=np.uint8)
    data = json.load(f)['data']['viewer']['zones'][0]['apiGatewayGraphqlQueryAnalyticsGroups']
    for datapoint in data:
        query_sizes = np.append(query_sizes, [datapoint['dimensions']['apiGatewayGraphqlQuerySize']] * datapoint['count'])
        query_depths = np.append(query_depths, [datapoint['dimensions']['apiGatewayGraphqlQueryDepth']] * datapoint['count'])

    quantiles = [0.99, 0.95, 0.75, 0.5]
    print('\n'.join([f"Query size {int(q * 100)}th percentile is {v}" for q, v in zip(quantiles, np.quantile(query_sizes, quantiles))]))
    print('\n'.join([f"Query depth {int(q * 100)}th percentile is {v}" for q, v in zip(quantiles, np.quantile(query_depths, quantiles))]))

S výše uvedeným dotazem získáte následující výstup:

Příklad výstupu
./calculator.py --response=response.json
Query size 99th percentile is 11.0
Query size 95th percentile is 11.0
Query size 75th percentile is 11.0
Query size 50th percentile is 6.5
Query depth 99th percentile is 1.0
Query depth 95th percentile is 1.0
Query depth 75th percentile is 1.0
Query depth 50th percentile is 1.0

Nastavit limity pro příchozí dotazy GraphQL

Zákazníci API Shield mají nyní ve vlastních pravidlech k dispozici tři nová pole:

Pomocí API nebo dashboardu můžete například nasadit následující pravidlo, které zablokuje dotazy s hlubokým zanořením a požadavkem na více než 30 polí.

(cf.api_gateway.graphql.query_size > 30 and cf.api_gateway.graphql.query_depth > 7 and cf.api_gateway.graphql.parsed_successfully)