Score: 93% (was 72%) — 4 thesis techniques now implemented, browser classification, ASN PeeringDB, SOC feedback loop. Identifies 9 bot-detector bugs (2 critical: campaign_id/raw_anomaly_score never inserted, worst_score inverted) and 11 dashboard bugs (4 critical: XSS, no auth, no CSRF, CORS misconfiguration). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
18 KiB
Audit de conformité : Code vs Thèse — Mise à jour 8 avril 2026
Date : 8 avril 2026
Référence : docs/THESIS_HTTP_Traffic_Detection.md
Périmètre : services/bot-detector/, services/dashboard/, schéma SQL
Légende
| Statut | Signification |
|---|---|
| ✅ CONFORME | Implémenté conformément à la thèse |
| ⚠️ PARTIEL | Implémenté mais incomplet ou dégradé |
| ❌ ABSENT | Décrit dans la thèse, non implémenté |
| 🔄 DIVERGENT | Implémenté différemment de ce que décrit la thèse |
| 🐛 BUG | Implémenté mais avec un bug qui empêche le fonctionnement correct |
Partie A — Conformité bot-detector vs Thèse
A1. Architecture multi-couches (Thèse §3)
| Composant thèse | Statut | Détail |
|---|---|---|
| Pipeline L3-L5 (ja4sentinel) | ✅ | TTL, IP-ID, DF, TCP win/mss/scale, JA4/JA3, ALPN, SNI |
| Pipeline L7 (mod_reqin_log) | ✅ | Headers, méthode, path, query, timestamps ns |
| Corrélation (logcorrelator) | ✅ | Clé src_ip:src_port, Keep-Alive, orphelins |
| Enrichissement ASN | ✅ | dict_iplocate_asn (714K CIDRs, 4 colonnes) |
| Enrichissement Anubis | ✅ | 5 niveaux priorité (UA+IP > UA > IP > ASN > Country) |
| Agrégation 1h | ✅ | agg_host_ip_ja4_1h + agg_header_fingerprint_1h |
| Vue features | ✅ | view_ai_features_1h (72+ colonnes) |
| Bifurcation Complet/Applicatif | ✅ | Complet (63 features L3→L7, correlated=1) + Applicatif (51 features L7, correlated=0) |
A2. Features L3 IP (Thèse §3.2)
| Feature thèse | Statut | Colonne SQL / Python |
|---|---|---|
| avg_ttl | ✅ | avg_ttl dans view_ai_features_1h |
| ttl_std | ✅ | ttl_std |
| ip_id_zero_ratio | ✅ | ip_id_zero_ratio |
| ip_df_variance | ✅ | ip_df_variance |
| request_size_variance | ✅ | request_size_variance |
| anomalous_payload_ratio | ✅ | anomalous_payload_ratio |
A3. Features L4 TCP (Thèse §3.3)
| Feature thèse | Statut | Détail |
|---|---|---|
| true_window_size | ⚠️ PARTIEL | Calculé dans SQL mais non inclus dans feats_complet — pas utilisé par l'EIF |
| window_mss_ratio | ⚠️ PARTIEL | Calculé dans SQL, absent de feats_complet |
| mss_mobile_mismatch | ✅ | Dans feats_complet |
| no_window_scale_ratio | ✅ | Dans feats_complet |
| tcp_shared_count | ✅ | Dans feats |
| tcp_jitter_variance | ✅ | Dans feats_complet |
| src_port_density | ✅ | Dans feats |
| port_exhaustion_ratio | ✅ | Dans feats |
| max_keepalives | ✅ | Dans feats |
A4. Features L5 TLS (Thèse §3.4)
| Feature thèse | Statut | Détail |
|---|---|---|
| JA4 fingerprint | ✅ | Clé de corrélation + feature |
| is_rare_ja4 | ✅ | Dans feats_complet |
| ja3_diversity_ratio | ✅ | Dans feats_complet |
| is_alpn_missing | ✅ | Dans feats_complet |
| sni_host_mismatch | ✅ | Dans feats_complet |
| tls12_ratio | ✅ | Dans feats_complet |
| alpn_http_mismatch | ✅ | Dans feats_complet |
A5. Features L7 HTTP (Thèse §3.5 + §2.3)
| Feature thèse | Statut | Détail |
|---|---|---|
| hits, hit_velocity | ✅ | |
| fuzzing_index | ✅ | |
| post_ratio, head_ratio | ✅ | |
| asset_ratio, direct_access_ratio | ✅ | |
| modern_browser_score | ✅ | 0/50/100 |
| ua_ch_mismatch | ✅ | |
| has_accept_language, has_cookie, has_referer | ✅ | |
| sec_fetch_absence_rate | ✅ | |
| generic_accept_ratio | ✅ | |
| missing_accept_enc_ratio | ✅ | |
| header_count, header_order_confidence | ✅ | |
| temporal_entropy | ✅ | Shannon entropie |
| path_diversity_ratio, url_depth_variance | ✅ | |
| http10_ratio, http_scheme_ratio | ✅ | |
| orphan_ratio | ✅ | |
| is_ua_rotating | ✅ |
A6. ML Pipeline (Thèse §2.4 + §3.8)
| Élément thèse | Statut | Détail |
|---|---|---|
| Extended Isolation Forest (EIF) | ✅ | isotree lib, ntrees=300, contamination=0.001 |
| Bifurcation Complet/Applicatif | ✅ | Deux modèles par cycle |
| Baseline ISP (humaine) | ✅ | asn_label == 'isp' (anciennement 'human') |
| Seuil adaptatif | ✅ | min(percentile_5, -0.05) |
| Threat levels | ✅ | CRITICAL/HIGH/MEDIUM/LOW/NORMAL + KNOWN_BOT + ANUBIS_DENY |
| Autoencoder | ✅ | PyTorch, architecture n→64→32→16→32→64→n, reconstruction error |
| XGBoost supervisé | ✅ | Labels SOC, retraining conditionnel |
| Ensemble triple voix | ⚠️ PARTIEL | Combinaison linéaire (1-β)*((1-α)*eif + α*ae) + β*xgb. Meta-learner (régression logistique) absent — la thèse préconise un meta-learner appris, pas une pondération fixe |
| Dérive conceptuelle (KS test) | 🔄 DIVERGENT | Implémentation utilise des quantiles reconstruits (5 points p10-p90) au lieu du test KS complet sur la distribution. Approximation grossière pour distributions multimodales |
| Validation gate | ✅ | Taux anomalie >20% → rejet modèle |
| Feature pruning (variance) | ✅ | Seuil 1e-6 |
| SHAP explainability | ✅ | Top-5 features par anomalie |
| HDBSCAN clustering | ✅ | Campagnes coordonnées |
| Feedback loop SOC | ✅ | FP→baseline, TP→exclusion |
| Déduplication TTL | ✅ | Inter-cycles, configurable |
| Récurrence penalty | ✅ | log1p(recurrence) × weight |
| Browser légitime (LEGITIMATE_BROWSER) | ✅ | JA4 + consistency score ≥ 4/5 |
A7. Techniques originales (Thèse §5)
| Technique | Statut | Détail |
|---|---|---|
| §5.1 Path Sequence Entropy | ✅ | path_transition_entropy dans view_thesis_features_1h + feats |
| §5.2 Bipartite JA4×ASN Graph | ❌ ABSENT | Non implémenté |
| §5.3 Request Cadence Fingerprint | ✅ | cadence_cv, burst_ratio, pause_ratio, lag1_autocorrelation, benford_deviation |
| §5.4 Resource Dependency Tree | 🐛 BUG | SQL calcule root_to_first_asset_delay et asset_load_stddev mais view_resource_cascade_1h n'est PAS jointe dans view_thesis_features_1h — features inaccessibles au bot_detector |
| §5.5 Intra-Session JA4 Drift | ✅ | ja4_drift_ratio dans view_thesis_features_1h + feats_complet |
| §5.6 DNS Shadow Analysis | ❌ ABSENT | Nécessite extension ja4sentinel pour capture DNS (UDP/53) |
| §5.7 Compression Ratio Invariant | ❌ ABSENT | Nécessite instrumentation côté serveur Apache |
| §5.8 Cross-Domain Session Linking | ✅ | host_diversity, host_sweep_speed, host_coverage_uniformity dans view_thesis_features_1h + feats |
A8. Taxonomie 7 familles (Thèse §4)
| Famille | Features attendues | Statut |
|---|---|---|
| 1. Volume & Vitesse | hits, hit_velocity, max_keepalives | ✅ 3/3 |
| 2. Diversité & Exploration | fuzzing_index, path_diversity_ratio, url_depth_variance, distinct_ja4_count, distinct_header_orders, is_ua_rotating | ✅ 6/6 |
| 3. Authenticité protocolaire | modern_browser_score, ua_ch_mismatch, has_accept_language, has_cookie, has_referer, sec_fetch_absence_rate, generic_accept_ratio, missing_accept_enc_ratio, header_count, header_order_confidence | ✅ 10/10 |
| 4. Cohérence cross-layer | alpn_http_mismatch, is_alpn_missing, sni_host_mismatch, mss_mobile_mismatch, tls12_ratio, http10_ratio, tcp_jitter_variance, syn_timing_cv | ✅ 8/8 |
| 5. Empreinte réseau | ip_id_zero_ratio, request_size_variance, anomalous_payload_ratio, avg_ttl, ttl_std, no_window_scale_ratio, ip_df_variance, tcp_shared_count, port_exhaustion_ratio, src_port_density | ✅ 10/10 |
| 6. Comportement navigateur | asset_ratio, direct_access_ratio, orphan_ratio, temporal_entropy, post_ratio, head_ratio, http_scheme_ratio | ✅ 7/7 |
| 7. Intelligence contextuelle | ja4_asn_concentration, ja4_country_concentration, is_rare_ja4, header_order_shared_count, ja3_diversity_ratio, anubis_is_flagged, multiplexing_efficiency | ✅ 7/7 |
Total taxonomie : 51/51 features (100%)
Partie B — Bugs identifiés dans bot-detector
B1. Bugs critiques (impact fonctionnel)
| # | Sévérité | Description | Localisation |
|---|---|---|---|
| B1.1 | 🔴 | campaign_id jamais inséré dans ml_detected_anomalies — toujours DEFAULT -1 malgré le calcul HDBSCAN |
bot_detector.py cols ligne ~1624 |
| B1.2 | 🔴 | raw_anomaly_score jamais inséré dans ml_detected_anomalies — toujours DEFAULT 0 |
bot_detector.py cols ligne ~1624 |
| B1.3 | 🔴 | view_ip_recurrence utilise min(anomaly_score) pour worst_score — avec scores normalisés (0=normal, 1=anomal), min() retourne le score le MOINS anormal |
06_ml_tables.sql |
| B1.4 | 🟠 | log_decision('FEATURE_PRUNED', name, '', ...) — name passé en cycle_id au lieu de model (argument order swap) |
bot_detector.py:596 |
| B1.5 | 🟠 | log_decision('MODEL_REJECTED', name, '', ...) — même inversion d'arguments |
bot_detector.py:623 |
| B1.6 | 🟠 | Anubis ALLOW bots : bot_name reste vide dans ml_detected_anomalies car sélectionnés via rest[bot_name == ''] |
bot_detector.py:970-1140 |
| B1.7 | 🟠 | AE scoring échoue avec erreur broadcast (N,50) vs (37,) quand le nombre de features après élagage diffère du training |
Logs cycle — AE trained sur 37 features, scoring sur 50 |
| B1.8 | 🟡 | rec_df peut être None → TypeError sur dict(zip(rec_df['src_ip']...)) |
bot_detector.py:~1489 |
| B1.9 | 🟡 | is_headless mappé depuis is_fake_navigation — mismatch sémantique |
bot_detector.py:1622 |
B2. Bugs qualité code
| # | Sévérité | Description | Localisation |
|---|---|---|---|
| B2.1 | 🟡 | warnings.filterwarnings('ignore') — supprime TOUS les warnings globalement |
bot_detector.py:71 |
| B2.2 | 🟡 | pyyaml dans requirements.txt mais jamais importé |
requirements.txt |
| B2.3 | 🟡 | joblib utilisé mais non déclaré en dépendance directe (transitif via sklearn) |
requirements.txt |
| B2.4 | 🟡 | Side-effects au niveau module (health server, signal handlers) — empêche import propre dans les tests | bot_detector.py:232,252-259 |
| B2.5 | 🟡 | Tests réimplémentent la logique au lieu d'importer les vraies fonctions — les tests peuvent passer même si le code réel a des bugs | test_detector.py |
| B2.6 | 🟡 | Section header dupliquée "A5 — DÉDUPLICATION" | bot_detector.py:1242,1280 |
| B2.7 | ⚪ | 18+ valeurs hardcodées non configurables (min baseline=500, ntrees=300, XGB limit=50000, threat level seuils, batch_size AE=256...) | Dispersé |
B3. Feature SQL non jointe (Thèse §5.4)
view_resource_cascade_1h est définie dans 12_thesis_features.sql mais absente du JOIN final dans view_thesis_features_1h. Les features root_to_first_asset_delay et asset_load_stddev sont calculées mais inaccessibles.
B4. Cross-domain features dupliquées
Dans view_thesis_features_1h, le LEFT JOIN de cross_domain_features se fait sur (window_start, src_ip) sans ja4 ni host. Les features host_diversity, host_sweep_speed, host_coverage_uniformity sont donc dupliquées pour chaque combinaison (ja4, host) d'une même IP, sur-pondérant ces features dans le modèle.
Partie C — Bugs identifiés dans dashboard
C1. Bugs critiques (sécurité)
| # | Sévérité | Description | Localisation |
|---|---|---|---|
| C1.1 | 🔴 | XSS : const IP = "{{ ip }}"; — injection JS via URL /ip/";alert(1);// |
ip_detail.html:72, pages.py:37 |
| C1.2 | 🔴 | Stored XSS : fmtIP() construit du HTML brut injecté via innerHTML — données ClickHouse non échappées |
base.html:123, tous les templates |
| C1.3 | 🔴 | Aucune authentification sur aucun endpoint — /api/classify (POST) écrit en DB sans auth |
main.py, api.py:770 |
| C1.4 | 🔴 | Pas de CSRF sur le POST /api/classify + CORS allow_origins=["*"] |
main.py:19-25 |
C2. Bugs fonctionnels
| # | Sévérité | Description | Localisation |
|---|---|---|---|
| C2.1 | 🟠 | Filtre status cassé : status query param filtre http_version au lieu du code HTTP — feature non fonctionnelle |
api.py:335 |
| C2.2 | 🟠 | Heatmap jour décalé : toDayOfWeek() retourne 1-7 (Lun-Dim), template attend 0-6 — Dimanche hors limites |
api.py:654, features.html:63 |
| C2.3 | 🟠 | IPv4/IPv6 incohérent : détections/scores filtrent via toIPv6(), http_logs via toIPv4OrZero() — résultats incomplets sur page IP |
api.py:378-399 |
| C2.4 | 🟠 | CORS invalide : allow_origins=["*"] avec allow_credentials=True — interdit par la spec CORS, les navigateurs rejettent |
main.py:19-25 |
| C2.5 | 🟡 | Bouton filtre MEDIUM manquant sur la page scores | scores.html:22 |
| C2.6 | 🟡 | models.html — null safety manquante : m.validation.val_anomaly_rate*100 crash si null |
models.html:51 |
| C2.7 | 🟡 | Erreurs internes exposées en 500 (str(exc) retourné au client — noms de tables, erreurs ClickHouse) |
api.py:144,226,303,364,433,787 |
| C2.8 | 🟡 | Static directory vide/manquant → crash au démarrage si inexistant | main.py:28 |
| C2.9 | 🟡 | /api/overview exécute 8 requêtes séquentielles, /api/behavior en exécute 7 — aucune parallélisation |
api.py |
| C2.10 | ⚪ | Aucun test unitaire ou d'intégration pour le dashboard | — |
| C2.11 | ⚪ | Dockerfile : pas de HEALTHCHECK, exécution root, pas de .dockerignore |
Dockerfile |
Partie D — Synthèse quantitative
D1. Conformité thèse
| Section thèse | Éléments | Conformes | Partiels | Absents | Bugs | Score |
|---|---|---|---|---|---|---|
| §3 Architecture | 8 | 8 | 0 | 0 | 0 | 100% |
| §3.2 L3 IP | 6 | 6 | 0 | 0 | 0 | 100% |
| §3.3 L4 TCP | 9 | 7 | 2 | 0 | 0 | 89% |
| §3.4 L5 TLS | 7 | 7 | 0 | 0 | 0 | 100% |
| §3.5 L7 HTTP | 17 | 17 | 0 | 0 | 0 | 100% |
| §4 Taxonomie 7 familles | 51 | 51 | 0 | 0 | 0 | 100% |
| §2.4+§3.8 ML Pipeline | 16 | 13 | 2 | 0 | 1 | 84% |
| §5 Techniques originales | 8 | 4 | 0 | 3 | 1 | 50% |
| TOTAL | 122 | 113 | 4 | 3 | 2 | 93% |
D2. Évolution depuis le dernier audit (7 avril)
| Métrique | 7 avril | 8 avril | Delta |
|---|---|---|---|
| §5 Techniques originales | 6% (0/8 + 1 partiel) | 50% (4/8) | +44% |
| Feedback loop SOC | ❌ ABSENT | ✅ CONFORME | ✅ Résolu |
| Browser classification | ❌ ABSENT | ✅ CONFORME | ✅ Résolu |
| ASN classification PeeringDB | ⚠️ 86% unknown | ✅ 7 catégories | ✅ Résolu |
| Score global pondéré | ~72% | ~93% | +21% |
D3. Gaps restants (par priorité)
| Priorité | Gap | Impact | Effort |
|---|---|---|---|
| P0 🔴 | campaign_id + raw_anomaly_score jamais insérés |
Clustering HDBSCAN inutile, score brut perdu | 5 min — ajouter aux cols |
| P0 🔴 | worst_score inversé dans view_ip_recurrence |
Récurrence penalty basée sur mauvais score | 5 min — max() au lieu de min() |
| P0 🔴 | XSS dans ip_detail.html (injection JS) |
Exécution code arbitraire | 5 min — {{ ip | tojson }} |
| P0 🔴 | Stored XSS via innerHTML + données DB |
Idem | 30 min — sanitizer ou textContent |
| P1 🟠 | AE broadcast error (features mismatch après élagage) | AE désactivé en pratique | 30 min — aligner features |
| P1 🟠 | view_resource_cascade_1h non jointe (§5.4) |
Features thèse §5.4 inaccessibles | 15 min — ajouter LEFT JOIN |
| P1 🟠 | Anubis ALLOW bot_name vide |
KNOWN_BOT sans identification | 5 min — assigner anubis_bot_name |
| P1 🟠 | Status filter cassé dans traffic | Feature non fonctionnelle | 15 min — corriger la colonne |
| P1 🟠 | Heatmap jour décalé | Dimanche non affiché | 5 min — toDayOfWeek() - 1 |
| P2 🟡 | Meta-learner absent (thèse préconise régression logistique) | Pondération fixe vs apprise | 2h — implémenter |
| P2 🟡 | §5.2 Bipartite JA4×ASN Graph | Technique originale manquante | 4h |
| P2 🟡 | §5.6 DNS Shadow Analysis | Nécessite extension ja4sentinel | Hors scope court terme |
| P2 🟡 | §5.7 Compression Ratio Invariant | Nécessite instrumentation Apache | Hors scope court terme |
| P3 ⚪ | Authentification dashboard | Sécurité production | 4h |
| P3 ⚪ | Tests dashboard (0% coverage) | Qualité | 8h |
| P3 ⚪ | Tests bot-detector importent le vrai code | Qualité | 4h |
Partie E — Conformité dashboard vs architecture thèse (§3.1)
La thèse décrit le dashboard comme composant de "21 modules + clustering + outils SOC". État actuel :
| Module thèse | Statut | Pages/Endpoints |
|---|---|---|
| Vue d'ensemble (overview) | ✅ | /overview — stats agrégées, top IPs, top JA4 |
| Détections (anomalies) | ✅ | /detections — tri, filtres, pagination |
| Scores ML (all_scores) | ✅ | /scores — toutes les sessions scorées |
| Trafic brut | ⚠️ PARTIEL | /traffic — filtre status cassé (C2.1) |
| Détail IP | ⚠️ PARTIEL | /ip/<ip> — XSS (C1.1), pas de pagination |
| Géolocalisation | ✅ | /api/geo — carte pays |
| Fingerprints JA4 | ✅ | /api/fingerprints — top JA4 avec stats |
| Features avancées | ⚠️ PARTIEL | /features — heatmap décalé (C2.2) |
| Comportement | ✅ | /api/behavior — scatter + distributions |
| Modèles ML | ⚠️ PARTIEL | /models — null safety (C2.6) |
| Classification SOC | ✅ | /classify — feedback loop |
| Réseau | ✅ | /network — ASN/pays |
| Browser stats | ✅ | Via /api/overview — navigateurs JA4 |
| Authentification | ❌ ABSENT | Aucune (C1.3) |
| CSRF protection | ❌ ABSENT | Aucune (C1.4) |