🔐 API Security – Découverte, protection, schémas, REST, GraphQL & WebSockets
Guide technique orienté production : inventaire d'API, protection REST/GraphQL/WebSockets, contrôle OpenAPI/JSON Schema, rate limiting, OAuth2/OIDC/JWT/mTLS, prévention BOLA/IDOR, intégration WAAP/API Gateway, observabilité SOC et DevSecOps.
API Security Foundations
Cartographie des surfaces REST, GraphQL, WebSockets, gRPC, identités et flux métiers.
Threat ModelZero TrustRuntimeDiscovery & Inventory
Découverte d'API exposées, shadow APIs, versions oubliées, endpoints non documentés.
DiscoveryShadow APICatalogOWASP API Top 10
Couverture structurée des risques API1 à API10 : BOLA, auth, BOPLA, SSRF, consommation.
OWASP APIBOLABOPLAREST Security
Protection REST/JSON : méthodes, verbes HTTP, pagination, idempotence, erreurs, cache.
RESTJSONHTTPSchema Enforcement
Contrôle OpenAPI/JSON Schema : types, champs inattendus, enum, réponse et drift de contrat.
OpenAPIJSON SchemaContractAuthentication & Authorization
OAuth2/OIDC, JWT, API keys, mTLS, RBAC/ABAC et autorisation objet par objet.
OAuth2JWTmTLSRate Limiting & Quotas
Limites par IP, token, route, tenant, coût GraphQL, burst, throttling et anti-abus.
QuotaBurstDoSGraphQL Security
Protection GraphQL : introspection, profondeur, complexité, batching, authZ champ par champ.
GraphQLDepthComplexityWebSocket Security
Protection WebSockets : handshake, Origin, auth, quotas messages, framing, WSS et backpressure.
WebSocketWSSRealtimeBOLA / IDOR Defense
Défense contre accès horizontal : object IDs, tenant isolation, ownership checks, tests multi-comptes.
BOLAIDORTenantData Protection & BOPLA
Protection des propriétés sensibles : excessive data exposure, mass assignment, PII, secrets.
BOPLAPIIDTOGateway / WAAP Runtime
Protection runtime : API Gateway, WAF/WAAP, règles positives, blocage d'injections et policy enforcement.
GatewayWAAPRuntimeObservability & SOC
Logs structurés, détection comportementale, traces, métriques, SIEM, playbooks d'incident API.
SIEMLogsForensicsDevSecOps API
Shift-left API : lint OpenAPI, SAST, DAST, fuzzing, contract tests et gates CI/CD.
CI/CDDASTFuzzingGovernance & Maturity
Modèle de maturité API Security : ownership, standards, runbooks, KPI, dépréciation et conformité.
GovernanceKPIRunbookComprendre la surface API moderne
Une API n'est pas seulement une URL exposée : c'est un contrat applicatif, un flux métier, un modèle d'autorisation et un canal d'échange machine-to-machine. La sécurité API consiste à contrôler ce contrat avant, pendant et après l'exécution.
- North-South : clients web/mobile, partenaires, SaaS et appels publics.
- East-West : microservices internes, service mesh, jobs batch, workers et pipelines.
- Protocoles : REST/JSON, GraphQL, WebSockets, gRPC, SOAP legacy, webhooks.
- Contrats : OpenAPI, GraphQL SDL, AsyncAPI, Protobuf, JSON Schema.
Objectif opérationnel
Les risques typiques d'une API exposée
| Risque | Symptôme | Contrôle attendu |
|---|---|---|
| BOLA / IDOR | Changement d'un ID dans l'URL pour lire l'objet d'un autre utilisateur. | Autorisation objet par objet côté backend. |
| Broken Authentication | JWT long-lived, refresh token non rotatif, absence de MFA pour opérations sensibles. | OIDC robuste, rotation, validation stricte des claims. |
| Mass Assignment | Champ admin ou role accepté dans le body JSON. | Allowlist de champs, DTO séparés, validation schema. |
| Resource Exhaustion | Pagination absente, GraphQL trop profond, WebSocket bavard. | Quotas, depth limit, coût requête, backpressure. |
Stack défensive cible
- API Gateway : routage, auth, quotas, transformations, versioning.
- WAAP : règles OWASP, détection d'injections, bot defense, L7 DDoS.
- API Security : discovery, schema enforcement, BOLA detection, posture.
- Service Mesh : mTLS east-west, policies workload-to-workload, telemetry.
- SIEM/SOAR : corrélation, alerting, playbooks de réponse.
Politique minimale
API runtime minimum baseline - HTTPS only / HSTS / TLS 1.2+ - Authentication required by default - Explicit method allowlist - OpenAPI schema validation for request and response - Per-token and per-IP rate limits - Object-level authorization in backend - Structured logs with user_id, client_id, route_id, decision - Secrets never logged
Checklist d'audit rapide
| Question | Pourquoi | Signal d'alerte |
|---|---|---|
| Dispose-t-on d'un inventaire complet ? | On ne protège pas ce qu'on ne voit pas. | Endpoints détectés dans les logs mais absents du catalogue. |
| Chaque endpoint a-t-il un owner ? | La remédiation nécessite une responsabilité claire. | API legacy sans équipe responsable. |
| Les schémas sont-ils appliqués au runtime ? | Le contrat doit bloquer champs inattendus et types invalides. | Body JSON libre sans validation. |
| Les décisions AuthZ sont-elles tracées ? | Indispensable pour enquêter sur BOLA/IDOR. | Logs sans subject, object_id ni policy decision. |
Sources de découverte
- Logs edge : CDN, WAF, reverse proxy, Nginx, API Gateway.
- CI/CD : specs OpenAPI, routes backend, tests d'intégration.
- Cloud : load balancers, ingress Kubernetes, serverless functions.
- Runtime : traces APM, service mesh, eBPF, telemetry gateway.
- Code : annotations controllers, routers Django/FastAPI/Spring/Express.
Normalisation d'un endpoint
Raw paths:
GET /api/users/123/orders/456
GET /api/users/789/orders/111
Normalized route:
GET /api/users/{user_id}/orders/{order_id}
Inventory fields:
owner, service, auth_required, data_classification,
method, route, schema_ref, last_seen, traffic_volumeDétection des Shadow / Zombie APIs
Une Shadow API est une API active mais non inventoriée. Une Zombie API est une ancienne version encore accessible. Les deux augmentent le risque car elles échappent souvent aux contrôles de sécurité et au patch management.
| Type | Exemple | Risque | Action |
|---|---|---|---|
| Shadow | /internal/export visible sur Internet | Exposition de données non prévue. | Bloquer, documenter, rattacher à un owner. |
| Zombie | /v1/payments encore utilisée | AuthZ ou validation moins stricte. | Sunset plan, redirection, version policy. |
| Debug | /api/debug/config | Fuite de secrets et metadata. | Suppression immédiate, règle edge. |
Score de criticité API
Public Internet, partner-only, internal, service mesh.
PII, secrets, paiement, santé, données internes.
Read-only, write, delete, paiement, admin.
risk_score = exposure_weight + data_sensitivity + action_impact + auth_weakness + traffic_anomaly Example: Public + PII + write + weak auth + unknown spec = Critical
Catalogue exploitable
Le résultat attendu n'est pas seulement une liste d'URLs, mais un inventaire exploitable par la sécurité, les équipes produit et l'exploitation.
| Champ | Usage |
|---|---|
| route_id | Identifiant stable pour logs, alertes et politiques. |
| owner | Équipe responsable de la correction. |
| schema_status | Spec présente, obsolète, absente, drift détecté. |
| auth_model | Public, API key, OAuth2, mTLS, session cookie, service token. |
| last_seen | Permet de détecter zombie APIs et usage résiduel. |
Référentiel OWASP API Security Top 10
| Risque | Lecture opérationnelle | Contrôle |
|---|---|---|
| API1 BOLA | Accès non autorisé à l'objet d'un autre utilisateur. | AuthZ objet par objet, tests horizontaux. |
| API2 Broken Authentication | Tokens faibles, sessions mal gérées, credentials exposés. | OIDC, rotation, validation stricte. |
| API3 BOPLA | Propriétés trop exposées ou modifiables. | DTO, allowlist, response filtering. |
| API4 Unrestricted Resource Consumption | Abus CPU, mémoire, pagination, GraphQL depth. | Rate limits, quotas, timeout, cost model. |
| API5 Broken Function Level Authorization | Fonctions admin accessibles par role user. | RBAC/ABAC côté serveur, route policy. |
Mapping vers contrôles runtime
| Risque | Gateway / WAAP | Backend obligatoire |
|---|---|---|
| BOLA | Détection d'enumeration d'ID, anomalies par token. | Vérification propriétaire/tenant de l'objet. |
| Auth | Validation JWT, mTLS, API key hygiene. | Gestion session, revocation, claims fiables. |
| BOPLA | Schema deny unknown fields. | DTO input/output, field-level authorization. |
| SSRF | Filtrage URL, DNS policy, egress restrictions. | Allowlist destinations, blocage metadata IPs. |
Tests sécurité API par risque
BOLA test pattern
1. Créer deux comptes A et B
2. Récupérer un object_id valide depuis A
3. Réutiliser cet object_id avec le token de B
4. Attendu: 403 ou 404, jamais 200
Mass assignment test
PATCH /api/users/me
{
"displayName": "test",
"role": "admin",
"isVerified": true
}
Attendu: champs role/isVerified ignorés ou rejetésPriorisation réaliste
Baseline REST sécurisée
- HTTPS only : jamais d'API sensible en HTTP clair.
- Verbes maîtrisés : GET, POST, PUT, PATCH, DELETE explicitement autorisés par route.
- Content-Type : refuser les types inattendus ; parser JSON strict.
- Pagination : limite maximale serveur, curseur plutôt qu'offset massif.
- Erreurs : messages utiles mais non bavards, correlation_id pour debug.
Contrôle de méthodes
Allowed:
GET /api/products
POST /api/orders
PATCH /api/users/me
Blocked:
TRACE /api/*
OPTIONS unrestricted
DELETE /api/users/{id} without admin policy
GET with body on sensitive endpointsHeaders importants pour API
| Header | Usage | Remarque |
|---|---|---|
| Authorization | Bearer token, signature, API key. | Ne jamais logger la valeur brute. |
| Content-Type | Type réel du payload. | Refuser application/xml si non supporté. |
| Accept | Version ou format attendu. | Peut piloter versioning propre. |
| X-Request-ID | Corrélation end-to-end. | Générer côté edge si absent. |
| Idempotency-Key | Protection contre double paiement. | Critique pour POST transactionnels. |
Gestion des erreurs
Une API doit être diagnostiquable sans exposer stacktrace, SQL, chemins fichiers, détails de librairie ou secrets.
Bad response:
500 Internal Error: psycopg2.errors.SyntaxError at /var/app/db.py line 88
Good response:
{
"error": "invalid_request",
"message": "The request cannot be processed.",
"correlation_id": "req_7f52a1",
"status": 400
}Cache et données sensibles
| Cas | Contrôle |
|---|---|
| Réponse utilisateur privée | Cache-Control: no-store |
| Token dans query string | Interdit : fuite via logs, referer, cache. |
| GET transactionnel | À éviter : risque de replay/cache involontaire. |
| CDN devant API | Vary contrôlé, pas de cache sur Authorization. |
Le contrat comme contrôle de sécurité
Une spécification OpenAPI permet de décrire les endpoints, méthodes, paramètres, auth schemes, payloads et réponses. Appliquée au runtime, elle devient une barrière contre entrées inattendues, champs toxiques et drift applicatif.
- Refuser routes non déclarées.
- Refuser méthodes non déclarées.
- Valider types, tailles, regex, enum.
- Optionnel : valider la réponse pour éviter fuite de champs internes.
Exemple de contrainte
components:
schemas:
CreateUserRequest:
type: object
additionalProperties: false
required: [email, displayName]
properties:
email:
type: string
format: email
maxLength: 254
displayName:
type: string
minLength: 2
maxLength: 80Contrôle strict du body
| Contrôle | Bloque | Impact |
|---|---|---|
| additionalProperties=false | Mass assignment, champs admin cachés. | Très fort, nécessite specs propres. |
| maxLength | Payload abuse, stockage excessif. | Faible friction si défini par métier. |
| enum | Valeurs inattendues, bypass de workflow. | Bon contrôle fonctionnel. |
| pattern | IDs non conformes, injections simples. | Attention aux regex trop coûteuses. |
Détection de drift contrat/runtime
Le drift apparaît quand le trafic réel ne correspond plus au contrat documenté : nouveaux champs, routes inconnues, types différents, versions parallèles.
PATCH /api/users/me avec champ isAdmin.displayName et phone.Déploiement progressif
| Phase | Mode | Objectif |
|---|---|---|
| 1 | Discovery | Observer sans bloquer, construire inventaire et schémas. |
| 2 | Alerting | Alerter sur drift et payloads suspects. |
| 3 | Block high-confidence | Bloquer méthodes/routes inconnues, content-type invalide. |
| 4 | Strict schema | Appliquer validation complète sur endpoints critiques. |
Authentification API
- OAuth2/OIDC : standard pour clients web/mobile et délégation.
- JWT : vérifier signature, algorithme, audience, issuer, expiration.
- API Keys : acceptable pour partenaires simples, jamais comme seule preuve forte pour actions sensibles.
- mTLS : excellent pour service-to-service et partenaires hautement sensibles.
JWT validation checklist
Validate every request: - signature using trusted JWKS - alg is expected, never none - iss == trusted issuer - aud contains this API - exp, nbf, iat within policy - scope/role is sufficient - token not revoked if high-risk
Autorisation : route, fonction, objet, champ
| Niveau | Exemple | Contrôle |
|---|---|---|
| Route | GET /admin/users | Role admin requis. |
| Fonction | POST /refund | Scope payment:refund. |
| Objet | GET /orders/{id} | Order tenant_id == token tenant_id. |
| Champ | salary, internalNotes | Field-level policy. |
Hygiène des tokens
- Access token court, refresh token rotatif.
- Scopes minimaux et lisibles.
- Pas de données sensibles inutiles dans les claims.
- Revocation ou introspection pour opérations critiques.
- Binding possible : mTLS-bound token ou DPoP selon architecture.
Example scopes: orders:read orders:write orders:refund users:read:self users:read:any
Défaillances fréquentes
| Erreur | Conséquence | Correction |
|---|---|---|
| Décoder JWT sans vérifier signature | Token forgé accepté. | Validation cryptographique stricte. |
| Se fier à user_id du body | Impersonation simple. | Subject depuis token uniquement. |
| Role global trop large | Escalade fonctionnelle. | Scopes par action + ABAC. |
| Absence tenant_id dans requêtes DB | Cross-tenant data leak. | Filtre tenant systématique. |
Modèles de limitation
| Modèle | Usage | Limite |
|---|---|---|
| Fixed Window | Simple : 1000 req/min. | Effet bord de fenêtre. |
| Sliding Window | Plus équitable. | Coût mémoire supérieur. |
| Token Bucket | Autorise burst contrôlé. | Très adapté APIs publiques. |
| Leaky Bucket | Lissage du débit. | Peut frustrer clients bursty. |
Limiter au bon niveau
Utile anti-bruteforce, mais fragile derrière NAT/proxy.
Très utile pour abus d'un client authentifié.
Protège la plateforme contre un client bruyant.
Rate limit policy example: - login: 5/min/IP + 20/h/account - search: 60/min/token + max page_size 100 - export: 3/h/tenant + async job only - payment: 10/min/token + idempotency key required
Rate limiting par coût
Pour GraphQL, compter les requêtes ne suffit pas : une seule query peut demander des milliers d'objets via profondeur, aliases et fragments.
Cost model idea: base_cost = 1 field_cost = number_of_fields list_cost = first/limit argument nested_cost = depth_multiplier Reject when: depth > 8 OR complexity > 1000 OR aliases > 20
Réponses client propres
HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1720000000
{
"error": "rate_limit_exceeded",
"message": "Too many requests. Retry later.",
"correlation_id": "req_19ab"
}Un bon rate limit protège la plateforme sans casser inutilement les intégrations légitimes.
Spécificités GraphQL
GraphQL donne beaucoup de pouvoir au client : il choisit la forme de la réponse. Cette flexibilité augmente les risques d'exfiltration, d'énumération, de DoS logique et de contournement d'autorisation.
- Introspection exposée en production.
- Queries profondes ou coûteuses.
- Aliases et fragments pour multiplier le travail serveur.
- Field-level authorization oubliée.
- Batching utilisé pour brute force ou enumeration.
Query coûteuse
query Evil {
users(first: 1000) {
orders(first: 1000) {
items(first: 1000) {
product { reviews(first: 1000) { text } }
}
}
}
}Contrôles GraphQL essentiels
| Contrôle | But |
|---|---|
| Depth limit | Empêcher queries récursives ou trop imbriquées. |
| Complexity limit | Limiter le coût estimé par champ/liste. |
| Persisted queries | Autoriser uniquement queries connues en production. |
| Disable GraphiQL | Éviter console d'exploration publique. |
| Field AuthZ | Contrôler chaque champ sensible. |
Autorisation au niveau champ
type User {
id: ID!
displayName: String!
email: String! # owner or admin only
internalNotes: String # support_admin only
billingStatus: String # billing scope only
}
Resolver rule:
if field == "email" and viewer.id != user.id and !viewer.hasRole("admin"):
deny()Observabilité GraphQL
| Métrique | Signal |
|---|---|
| query_depth | Détection de DoS logique. |
| query_complexity | Corrélation avec CPU/latence. |
| operation_name | Plus exploitable qu'une URL unique /graphql. |
| field_denied_count | Détection de probing de champs sensibles. |
| introspection_attempts | Reconnaissance ou outil automatisé. |
Contrôler l'ouverture de connexion
- WSS obligatoire : chiffrement et intégrité du canal.
- Origin allowlist : empêcher cross-site WebSocket hijacking.
- Auth au handshake : token court, cookie SameSite, session vérifiée.
- Subprotocol : refuser sous-protocoles inattendus.
Contrôle Origin
Allowed origins: https://app.example.com https://admin.example.com Reject: Origin: null Origin: https://evil.example Missing Origin for browser clients
Valider chaque message
Après l'upgrade HTTP, les messages WebSocket doivent être traités comme des entrées non fiables : type, taille, fréquence, schéma et autorisation doivent être contrôlés.
Message schema:
{
"type": "subscribe_order",
"request_id": "uuid",
"payload": {
"order_id": "ord_123"
}
}
Controls:
- allowed message type
- max payload size
- JSON schema validation
- object-level authorization on order_idAbus temps réel
| Abus | Symptôme | Protection |
|---|---|---|
| Connection flood | Ouvertures massives. | Limit par IP/token, proof/challenge si besoin. |
| Message flood | CPU/event-loop saturé. | Quota messages/sec, backpressure. |
| Subscription abuse | Trop de canaux par client. | Max subscriptions, scopes par channel. |
| Broadcast abuse | Amplification vers nombreux clients. | Contrôle du fan-out, quotas par tenant. |
Logs WebSocket utiles
On connect: connection_id, user_id, tenant_id, origin, ip, user_agent On message decision: connection_id, message_type, object_id, decision, reason, latency_ms On close: connection_id, close_code, duration_sec, messages_in, messages_out
Pourquoi BOLA est critique
BOLA apparaît quand l'API vérifie que l'utilisateur est authentifié, mais ne vérifie pas qu'il a le droit d'accéder à l'objet demandé. C'est très fréquent dans les routes contenant des identifiants.
Victim: GET /api/invoices/inv_1001 Authorization: Bearer token_A Attack: GET /api/invoices/inv_1001 Authorization: Bearer token_B Expected: 403 Forbidden or 404 Not Found Vulnerable: 200 OK with invoice data
Contrôle backend obligatoire
def get_invoice(invoice_id, viewer):
invoice = db.invoice.find_one({
"id": invoice_id,
"tenant_id": viewer.tenant_id
})
if not invoice:
raise NotFound()
if invoice.owner_id != viewer.user_id and not viewer.has_scope("invoice:read:any"):
raise Forbidden()
return invoicefind_one({"id": invoice_id}) puis vérifier seulement le rôle global.Détection runtime BOLA
| Signal | Interprétation |
|---|---|
| Nombreux 403/404 sur IDs proches | Enumeration d'objets. |
| Un token accède à IDs de plusieurs tenants | Possible fuite cross-tenant. |
| Variation rapide d'ID dans la même route | Script de probing. |
| User-Agent rare + taux d'erreur élevé | Automatisation offensive probable. |
Réduire l'exposition
- Utiliser IDs non prédictibles, sans considérer cela comme une autorisation.
- Scoper les requêtes DB par tenant et owner dès le départ.
- Créer des ressources via collections de l'utilisateur :
/me/orders/{id}. - Éviter endpoints admin génériques exposés aux clients.
- Tester systématiquement avec deux comptes et deux tenants.
Excessive Data Exposure
Le backend ne doit jamais renvoyer un objet complet en supposant que le frontend filtrera les champs sensibles. Le filtrage doit être côté serveur.
Bad response:
{
"id": "usr_1",
"email": "client@example.com",
"passwordHash": "...",
"mfaSecret": "...",
"internalRiskScore": 87
}
Good response:
{
"id": "usr_1",
"displayName": "Client",
"email": "client@example.com"
}Mass assignment
| Anti-pattern | Risque | Solution |
|---|---|---|
| Mapper body JSON directement vers modèle ORM | Modification de champs internes. | DTO d'entrée allowlist. |
| Réutiliser UserModel pour create/update | role, isAdmin, credit exposés. | Models séparés input/output. |
| Accepter additionalProperties | Champs non prévus persistés. | Schema strict. |
Données sensibles
- Classer les champs : public, interne, personnel, secret, paiement.
- Masquer dans les logs : Authorization, cookies, tokens, secrets, cartes.
- Chiffrer ou tokeniser les données sensibles au repos.
- Appliquer minimisation : ne jamais renvoyer un champ inutile.
- Mettre en place data retention et purge.
Validation des réponses
La validation des réponses est souvent négligée, mais elle permet de détecter des fuites de champs internes après refactoring.
Response schema guard: - additionalProperties: false - deny fields matching: *password*, *secret*, *token*, *hash* - max array size for list endpoints - no stacktrace fields - no internal service metadata
Où placer la protection API ?
- CDN/Edge : L7 DDoS, bot defense, règles globales.
- API Gateway : auth, routing, quotas, transformation.
- Ingress Kubernetes : exposition cluster, policies par service.
- Service Mesh : mTLS east-west, policies internes.
- Backend : autorisation métier et validation finale.
Chaîne idéale
Positive security model
Au lieu de bloquer seulement ce qui ressemble à une attaque, on autorise uniquement ce qui correspond au contrat attendu.
| Élément | Autorisé | Bloqué |
|---|---|---|
| Route | Déclarée dans OpenAPI | Endpoint inconnu |
| Méthode | GET/POST prévu | TRACE, DELETE inattendu |
| Paramètre | Type, taille, enum valides | Paramètre inconnu ou payload trop grand |
| Auth | Scope attendu | Token absent, audience invalide |
Détection d'attaques applicatives
Examples of high-confidence blocks: - SQLi patterns in string fields not expected to contain code - XSS payloads in displayName/comment fields - Command injection metacharacters in filename/host parameters - SSRF attempts to 169.254.169.254 or internal ranges - Path traversal in file download parameters - JSON/XML bombs and oversized nested payloads
Anti-bypass
- Normaliser avant analyse : encoding, unicode, case, path normalization.
- Limiter content-types : JSON strict si API JSON.
- Refuser duplicate headers critiques ou paramètres ambigus.
- Traiter gzip/deflate avec limites de décompression.
- Bloquer HTTP request smuggling patterns côté edge.
Log API minimal
api_log = {
"timestamp": "...",
"route_id": "GET /api/orders/{id}",
"method": "GET",
"status": 403,
"decision": "deny",
"reason": "object_owner_mismatch",
"user_id": "usr_123",
"tenant_id": "ten_001",
"client_id": "mobile_app",
"object_id_hash": "...",
"correlation_id": "req_abc",
"latency_ms": 42
}Use-cases SOC API
| Use-case | Signal | Action |
|---|---|---|
| BOLA probing | 403/404 élevés sur route objet. | Throttle token, alerte AppSec. |
| Credential stuffing API | Login failures par IP/device. | Challenge, lockout progressif. |
| Data scraping | Pagination exhaustive, volume anormal. | Réduction quota, review client. |
| Schema drift | Champs inconnus fréquents. | Ticket owner, mode block si critique. |
Métriques de pilotage
% endpoints inventoriés avec spec et owner.
Blocages par route, raison et niveau de confiance.
Routes/champs observés mais non documentés.
Playbook incident API
Gates CI/CD API Security
| Étape | Contrôle |
|---|---|
| Design | Threat modeling, revue OpenAPI, classification données. |
| Build | SAST, secrets scan, dependency scan. |
| Test | DAST API, fuzzing, tests BOLA multi-comptes. |
| Deploy | Publication spec vers gateway/WAAP, policy as code. |
| Runtime | Discovery drift, alerting, blocking progressif. |
Règles de lint OpenAPI
Fail build if: - endpoint has no security requirement - requestBody has no schema - schema allows additionalProperties by default on sensitive endpoints - string fields have no maxLength - arrays have no maxItems - 5xx response exposes stacktrace schema - route has no owner or data classification
Fuzzing orienté API
- Types invalides : string au lieu de integer, null inattendu.
- Tailles extrêmes : champs trop longs, arrays massifs.
- Encodages : unicode, double encoding, path traversal.
- Business fuzzing : IDs d'autres utilisateurs, états workflow impossibles.
- GraphQL fuzzing : depth, aliases, fragments, introspection.
Policy as Code
api_policy:
route: "POST /api/payments"
auth:
required: true
scopes: ["payments:write"]
limits:
per_token: "10/min"
per_tenant: "1000/day"
schema:
request: "#/components/schemas/CreatePayment"
strict: true
controls:
require_idempotency_key: true
log_decision: trueModèle de maturité
| Niveau | État | Objectif |
|---|---|---|
| 0 | APIs inconnues, sécurité réactive. | Découverte passive. |
| 1 | Inventaire partiel, WAF générique. | Catalogue + owners. |
| 2 | Specs OpenAPI présentes. | Schema enforcement progressif. |
| 3 | Tests CI/CD et runtime alerts. | Policy as code + DAST. |
| 4 | Protection adaptative, KPIs, SOAR. | Amélioration continue. |
Ownership clair
- Chaque API a une équipe propriétaire.
- Chaque route critique a une classification de données.
- Chaque version a une date de fin de vie.
- Chaque exception WAAP a un ticket, une justification et une expiration.
- Les changements de spec passent par revue sécurité si endpoint sensible.
Indicateurs utiles
% endpoints connus / endpoints observés.
% routes avec schéma strict et security requirement.
Temps moyen de correction drift ou endpoint critique.
Pitch expertise API Security
Positionnement professionnel : capacité à sécuriser des APIs modernes de bout en bout, depuis l'inventaire et la modélisation des risques jusqu'à la protection runtime et l'intégration DevSecOps.
Je sais mettre en place une démarche API Security complète : découverte des APIs exposées, détection de shadow APIs, validation OpenAPI/JSON Schema, protection REST/GraphQL/WebSockets, contrôles OAuth2/OIDC/JWT/mTLS, rate limiting par token/tenant, détection BOLA/IDOR, intégration WAAP/API Gateway et observabilité SOC avec logs exploitables.
