Pourquoi 48h (et pas 2 semaines) ?
J’ai mené plus de 20 audits de sécurité pour des PME suisses ces 3 dernières années. La réalité : personne n’a le temps ni le budget pour un pentest complet de 2 semaines avant chaque mise en production.
Ce dont vous avez besoin, c’est d’un audit ciblé qui identifie les vulnérabilités critiques — celles qui permettent à un attaquant de voler vos données ou de prendre le contrôle de votre app — en 48h maximum.
Voici ma méthodologie éprouvée et la checklist exacte que j’utilise.
Méthodologie : focus sur l’impact réel
Phase 1 : Reconnaissance (3h)
Cartographie de l’application
- Architecture (frontend/backend/DB/cloud)
- Points d’entrée (APIs, formulaires, uploads)
- Technologies (frameworks, versions, dépendances)
- Stack d’authentification
Outils
# Fingerprinting rapide
whatweb https://votreapp.ch
nmap -sV -p 80,443 votreapp.ch
# Analyse des headers
curl -I https://votreapp.ch | grep -E "(Server|X-Powered|X-Frame)"
Phase 2 : Top 10 OWASP (12h)
Je ne teste que les vecteurs qui apparaissent dans 90% des incidents réels en Suisse.
Phase 3 : Remédiation prioritaire (3h)
Rapport avec 3 catégories :
- Critique : exploitable en < 1h, impact métier immédiat
- Élevé : nécessite compétence technique, impact significatif
- Moyen : défense en profondeur
Les 10 vecteurs d’attaque les plus courants
1. Broken Access Control (A01)
Ce que je teste
# IDOR (Insecure Direct Object Reference)
GET /api/users/123/invoices # Mon accès
GET /api/users/124/invoices # Accès à un autre user ?
Vulnérabilité réelle trouvée (Mars 2024) Une PME lausannoise : j’ai pu accéder à 12,000 factures clients en incrémentant simplement l’ID dans l’URL.
Fix rapide
// AVANT (vulnérable)
app.get('/api/invoices/:id', (req, res) => {
const invoice = db.getInvoice(req.params.id);
res.json(invoice);
});
// APRÈS (sécurisé)
app.get('/api/invoices/:id', authenticate, (req, res) => {
const invoice = db.getInvoice(req.params.id);
if (invoice.userId !== req.user.id) {
return res.status(403).json({ error: 'Forbidden' });
}
res.json(invoice);
});
2. Cryptographic Failures (A02)
Checklist
- ✓ HTTPS partout (y compris fonts, CDN, images)
- ✓ Certificat valide et à jour
- ✓ HSTS header (Strict-Transport-Security)
- ✓ Mots de passe hashés avec bcrypt/argon2 (jamais MD5/SHA1)
- ✓ Secrets jamais en clair dans le code
Test
# Vérifier HSTS
curl -I https://votreapp.ch | grep Strict-Transport-Security
# Scan SSL/TLS
sslscan votreapp.ch
Erreur fréquente
Cookies de session sans flag Secure et HttpOnly.
// Mauvais
res.cookie('session', token);
// Bon
res.cookie('session', token, {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 3600000
});
3. Injection (A03)
SQL Injection reste #1
Test manuel :
' OR '1'='1
'; DROP TABLE users; --
1' UNION SELECT password FROM users--
Fix : parameterized queries
// Vulnérable
db.query(`SELECT * FROM users WHERE email = '${"$"}{email}'`);
// Sécurisé
db.query('SELECT * FROM users WHERE email = ?', [email]);
NoSQL Injection (souvent oublié)
// Vulnérable (MongoDB)
db.users.find({ username: req.body.username });
// Attaque
POST /login
{ "username": { "$ne": null }, "password": { "$ne": null } }
// Fix : validation stricte
const username = String(req.body.username);
db.users.find({ username });
4. Insecure Design (A04)
Pattern dangereux : récupération de mot de passe
❌ Mauvais : envoyer le mot de passe actuel par email
✅ Bon : lien de réinitialisation avec token unique, expiration 1h
❌ Mauvais : question secrète stockée en clair
✅ Bon : TOTP (Google Authenticator) ou email de confirmation
5. Security Misconfiguration (A05)
Checklist rapide
# Stack traces exposées ?
curl https://votreapp.ch/api/nonexistent
# Directory listing ?
curl https://votreapp.ch/.git/
# Fichiers sensibles accessibles ?
curl https://votreapp.ch/.env
curl https://votreapp.ch/package.json
curl https://votreapp.ch/composer.json
Headers de sécurité obligatoires
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self'" always;
6. Vulnerable Components (A06)
Automatisable en 5 minutes
# Node.js
npm audit
# Python
pip-audit
# PHP
composer audit
# Containers
docker scan myimage:latest
Règle d’or : si une dépendance a une CVE critique, patcher dans les 72h.
7. Identification & Authentication Failures (A07)
Tests
- Brute force possible ? (rate limiting ?)
- Session timeout configuré ?
- Logout invalide la session côté serveur ?
- Pas de token/session dans l’URL ?
Rate limiting express
const rateLimit = require('express-rate-limit');
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 min
max: 5, // 5 tentatives max
message: 'Trop de tentatives, réessayez dans 15min'
});
app.post('/login', loginLimiter, loginController);
8. Software and Data Integrity Failures (A08)
CI/CD compromise
Vérifier :
- Secrets dans les variables d’env (pas hardcodés)
- Signature des artefacts de build
- Scan de containers avant déploiement
npm/yarn integrity
// package.json
{
"dependencies": {
"express": "4.18.2" // Version fixe, pas "^4.18.0"
}
}
9. Security Logging Failures (A09)
Ce qu’il FAUT logger
- Tentatives de login (succès et échecs)
- Changements de mots de passe
- Accès à données sensibles
- Erreurs serveur (500, 403, etc.)
Ce qu’il NE FAUT PAS logger
- Mots de passe (même hashés)
- Tokens d’auth
- Numéros de carte de crédit
// Bon exemple
logger.info('Login attempt', {
email: email, // OK
ip: req.ip,
userAgent: req.headers['user-agent'],
success: false,
reason: 'invalid_password'
// password: password ← JAMAIS
});
10. Server-Side Request Forgery (SSRF) (A10)
Vulnérabilité sous-estimée
// Vulnérable
app.post('/fetch-url', (req, res) => {
const url = req.body.url;
fetch(url).then(data => res.json(data));
});
// Attaque possible
POST /fetch-url
{ "url": "http://169.254.169.254/latest/meta-data/" }
// → accès aux métadonnées AWS/Azure
Fix : whitelist stricte
const allowedDomains = ['api.partner.com', 'cdn.trusted.com'];
if (!allowedDomains.includes(new URL(url).hostname)) {
return res.status(400).json({ error: 'Domain not allowed' });
}
Outils gratuits pour automatiser 60% de l’audit
- OWASP ZAP : scanner automatique
- Burp Suite Community : proxy d’interception
- npm audit / Snyk : scan dépendances
- Mozilla Observatory : test headers HTTP
- SSL Labs : test configuration SSL
Checklist 30 minutes
Version imprimable pour check rapide :
[ ] HTTPS obligatoire partout
[ ] Headers de sécurité configurés
[ ] Cookies Secure + HttpOnly
[ ] Rate limiting sur login/API
[ ] Validation inputs côté serveur
[ ] Requêtes SQL paramétrées
[ ] Secrets en variables d'env
[ ] npm audit clean
[ ] Logs d'audit actifs
[ ] Backups testés régulièrement
Quand faire un audit complet ?
Audit 48h ne remplace pas un pentest complet dans ces cas :
- Application manipulant données bancaires/santé
- > 100k utilisateurs actifs
- Conformité réglementaire (PCI-DSS, HIPAA, etc.)
Mais pour 80% des PME suisses : cet audit ciblé est largement suffisant et peut être répété tous les 3-6 mois sans exploser le budget.
Coût vs Impact
Audit OWASP 48h : 3,000-5,000 CHF
Coût moyen d’une brèche : 380,000 CHF (IBM Cost of Data Breach 2024)
ROI : ~7,500%
Besoin d’un audit de sécurité pour votre application ? Contactez-moi pour un devis et un planning adapté à vos contraintes de production.