🔒 Sécurité

security-api-security-hardener

Durcissement de la sécurité des APIs — rate limiting, validation d'entrée, headers de sécurité, CORS, protection contre les attaques courantes.

⚡ Installation & lancement en 1 commande

Copiez-collez dans votre terminal : le skill s'installe dans ~/.claude/skills et Claude Code se lance directement dessus.

macOS / Linux
curl -fsSL https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.sh | sh -s -- security-api-security-hardener --launch
Windows (PowerShell)
iex "& { $(iwr -useb https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.ps1) } security-api-security-hardener -Launch"

🚀 Déjà installé ?

claude "/security-api-security-hardener"

Ou tapez /security-api-security-hardener dans une session Claude Code, ou décrivez simplement votre besoin — le skill se déclenche automatiquement via le skill-router.

🔑 Déclencheurs automatiques

Le skill s'active automatiquement quand votre demande contient :

sécurité APIrate limitingheaders sécuritéCORSAPI hardeningprotection APIOWASP API

📦 Installation manuelle

git clone https://github.com/khalilbenaz/claude-skills-collection.git cp -r claude-skills-collection/skills/security-api-security-hardener ~/.claude/skills/

Payload du plugin : skills/security-api-security-hardener · source éditable : security-skills/api-security-hardener

📖 Manuel

Durcissement de la Sécurité des APIs

Workflow en 5 étapes

1. Auditer — cartographier la surface d'attaque

curl -sI https://api.example.com/health | grep -iE "server|x-powered|access-control|x-content"

Critère de décision : si un endpoint peut être appelé sans jeton ou sans vérification d'ownership sur la ressource → priorité 1.


2. Configurer les headers de sécurité (ASP.NET Core)

// Program.cs — avant app.UseRouting()
app.Use(async (context, next) =>
{
    var headers = context.Response.Headers;
    headers.Append("X-Content-Type-Options", "nosniff");
    headers.Append("X-Frame-Options", "DENY");
    headers.Append("X-XSS-Protection", "0");            // désactivé volontairement (géré par CSP)
    headers.Append("Referrer-Policy", "strict-origin-when-cross-origin");
    headers.Append("Content-Security-Policy", "default-src 'self'");
    headers.Append("Permissions-Policy", "camera=(), microphone=(), geolocation=()");
    headers.Append("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
    headers.Remove("Server");
    headers.Remove("X-Powered-By");
    headers.Remove("X-AspNet-Version");
    await next();
});
Vérifier après déploiement avec securityheaders.com ou curl -sI.

3. Configurer le Rate Limiting

Critères de choix :

// .NET 7+ — Microsoft.AspNetCore.RateLimiting
builder.Services.AddRateLimiter(options =>
{
    // Global : 100 req/min par IP
    options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(ctx =>
        RateLimitPartition.GetFixedWindowLimiter(
            partitionKey: ctx.Connection.RemoteIpAddress?.ToString() ?? "unknown",
            factory: _ => new FixedWindowRateLimiterOptions
            {
                PermitLimit = 100,
                Window = TimeSpan.FromMinutes(1)
            }));

    // Politique "strict" pour endpoints sensibles
    options.AddPolicy("strict", ctx =>
        RateLimitPartition.GetSlidingWindowLimiter(
            partitionKey: ctx.User.Identity?.Name     // par utilisateur si authentifié
                          ?? ctx.Connection.RemoteIpAddress?.ToString()
                          ?? "anon",
            factory: _ => new SlidingWindowRateLimiterOptions
            {
                PermitLimit = 5,
                Window = TimeSpan.FromMinutes(1),
                SegmentsPerWindow = 6
            }));

    options.OnRejected = async (ctx, token) =>
    {
        ctx.HttpContext.Response.StatusCode = 429;
        ctx.HttpContext.Response.Headers.Append("Retry-After", "60");
        await ctx.HttpContext.Response.WriteAsync("Too Many Requests", token);
    };
});

app.UseRateLimiter();

// Sur l'endpoint
app.MapPost("/api/payments", handler).RequireRateLimiting("strict");

4. Valider les entrées et sécuriser les sorties

Validation d'entrée (DTO) :

public class CreatePaymentRequest
{
    [Required]
    [Range(1, 9_999_999)]
    public int AmountCents { get; set; }

    [Required, RegularExpression("^(EUR|USD|MAD|TND)$")]
    public string Currency { get; set; } = default!;

    [Required, StringLength(50, MinimumLength = 1)]
    [RegularExpression("^[a-zA-Z0-9_-]+$")]   // pas d'injection possible
    public string RecipientId { get; set; } = default!;

    [MaxLength(10)]
    public Dictionary<string, string>? Metadata { get; set; }
}

BOLA — vérification d'ownership :

// Toujours filtrer par UserId de la session, pas par paramètre URL seul
var order = await db.Orders
    .Where(o => o.Id == orderId && o.UserId == currentUserId)  // double filtre obligatoire
    .FirstOrDefaultAsync();

if (order is null) return Results.NotFound();   // ne pas révéler l'existence

Réponses d'erreur génériques :

// Anti-pattern : retourner le message d'exception
return Results.Problem(ex.Message);   // ❌ fuite d'info

// Correct
return Results.Problem("Une erreur est survenue.", statusCode: 500);  // ✅
// Logger ex en interne avec correlation ID

5. Configurer CORS et monitorer

CORS strict :

builder.Services.AddCors(options =>
{
    options.AddPolicy("Production", policy =>
        policy.WithOrigins("https://app.company.com", "https://admin.company.com")
              .WithMethods("GET", "POST", "PUT", "DELETE")
              .WithHeaders("Authorization", "Content-Type", "X-Correlation-Id")
              .SetMaxAge(TimeSpan.FromHours(1)));   // cache preflight 1h
});

// Jamais AllowAnyOrigin() + AllowCredentials() ensemble → erreur runtime + faille critique

Logging sécurité (Serilog / ILogger) :

// Événements à logger systématiquement
logger.LogWarning("Auth failed: user={User} ip={Ip} endpoint={Ep}", user, ip, path);
logger.LogWarning("Rate limit hit: ip={Ip} policy={Policy}", ip, policy);
logger.LogWarning("BOLA attempt: requestedId={Id} ownerId={Owner}", id, owner);

Envoyer ces logs vers un SIEM ou au moins un fichier séparé consultable en cas d'incident.


OWASP API Top 10 — Checklist 2023

#RisqueContrôle minimal
API1Broken Object Level AuthorizationFiltre UserId sur chaque requête DB
API2Broken AuthenticationJWT exp court (15 min), refresh rotation, révocation
API3Broken Object Property Level AuthorizationDTO explicites, jamais d'entités directes
API4Unrestricted Resource ConsumptionRate limit + pagination obligatoire (maxPageSize)
API5Broken Function Level Authorization[Authorize(Roles="Admin")] sur chaque endpoint admin
API6Unrestricted Sensitive Business FlowsLimites métier (ex. max 3 OTP/24h), CAPTCHA
API7Server Side Request ForgeryWhitelist d'URLs, interdire les IPs privées dans les webhooks
API8Security MisconfigurationHeaders corrects, swagger désactivé en prod, erreurs génériques
API9Improper Inventory ManagementInventaire d'endpoints versionné, décommissionner /v1 obsolètes
API10Unsafe Consumption of APIsValider le schéma des réponses tierces, timeout agressif

Anti-patterns / Pièges


Commandes de vérification rapide

# Tester les headers en prod
curl -sI https://api.example.com/ | grep -iE "strict-transport|content-security|x-content|server"

# Tester CORS
curl -sI -X OPTIONS https://api.example.com/api/payments \
  -H "Origin: https://evil.com" \
  -H "Access-Control-Request-Method: POST" | grep -i "access-control"

# Tester le rate limit (10 appels rapides)
for i in {1..12}; do curl -sw "%{http_code}\n" -o /dev/null https://api.example.com/api/auth/login; done