← Cloudflare API Shield / api-shield / security / graphql-protection
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).
{
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.
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ěď:
{
"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:
#!/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:
./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.0Nastavit limity pro příchozí dotazy GraphQL
Zákazníci API Shield mají nyní ve vlastních pravidlech k dispozici tři nová pole:
cf.api_gateway.graphql.query_sizepopisuje velikost dotazu GraphQL.cf.api_gateway.graphql.query_depthpopisuje hloubku dotazu GraphQL.cf.api_gateway.graphql.parsed_successfullypopisuje, zda Cloudflare dokázal dotaz zpracovat. V současnosti provádíme parsování s nejlepším úsilím, což znamená, že se nám nemusí podařit zpracovat všechny platné dotazy. To znamená, že musíte použítand cf.api_gateway.graphql.parsed_successfullyfiltr ve vlastních pravidlech při nasazování bezpečnostních pravidel GraphQL.
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)