Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ADR-105 — Campagne de tests de sécurité d’air-sshd : confrontation aux attaques SSH connues

Statut : Accepté (2026-07-25, décision BDFL). RFC de direction (ADR-015). S’appuie sur ADR-093 (transport, strict-KEX), ADR-094 (userauth : login-grace, essais bornés, anti-énumération), ADR-104 (SFTP), ADR-031 (mesure privilégiée sur runners self-hosted).

Catégorie : Assurance sécurité. Ne modifie aucune couche ; définit une méthode de test et ses critères de réussite. À lancer après la clôture d’air-sshd.

Contexte

air-sshd est un démon SSH exposé au réseau, écrit pour être secure-first. Plusieurs de ses choix de conception sont précisément des contre-mesures à des attaques SSH connues : strict-KEX contre Terrapin (CVE-2023-48795), login-grace + essais bornés contre le brute-force, temps constant contre l’énumération de comptes (CVE-2018-15473 côté OpenSSH). Ces contre-mesures ont été implémentées et testées unitairement ; elles n’ont pas encore été confrontées à des outils d’attaque réels.

Directive BDFL (2026-07-25) : après clôture d’air-sshd, monter une campagne qui confronte le démon à tous les types d’attaques SSH connus — flooding, DoS, brute-force, timing / énumération de login — et qui prouve les contre-mesures plutôt que de les supposer. Le test sert donc autant à attester nos choix qu’à chercher des failles : sur beaucoup de vecteurs (algorithmes legacy, compression, KEX faible) nous n’avons rien à trouver parce que la surface n’existe pas (moderne-only, charte) — la campagne le démontre.

Décision

1. Deux niveaux, parce que le timing réseau ne prouve pas le constant-time

Le point le plus délicat de la commande — prouver le temps constant — ne se démontre pas de façon fiable à travers le réseau : le jitter réseau masque des fuites (faux négatifs) et en invente (faux positifs). Une campagne uniquement réseau donnerait une fausse assurance. La méthode est donc à deux étages, complémentaires :

  • Niveau 1 — local, cycle-précis (LA preuve). Mesure du chemin de code sensible sur la machine, sans réseau : vérification Argon2id du mot de passe admin, comparaison de clé publique, résolution de login (air-account). Méthode dudect (Reparaz et al.) : deux classes d’entrées, mesure des cycles, test statistique de distinguabilité. C’est la preuve algorithmique du constant-time.
  • Niveau 2 — réseau, bout-en-bout (le test d’attaque). Confrontation du vrai démon depuis une machine distincte, avec outils d’attaque réels + harnais maison. Valide l’intégration et la défense en profondeur, jamais le constant-time à lui seul.

Sans le niveau 1, on ne peut pas conclure au constant-time. Le niveau 2 le corrobore, il ne le démontre pas.

2. Topologie — attaquant et cible séparés, réseau fermé

  • Attaquant : carbon (8 cœurs, 16 Gio) — porte l’outillage offensif.
  • Cible : air-sshd sur speedy, écoutant sur :2222 (parallèle à OpenSSH).
  • Réseau interne uniquement (air-desktop, speedy.netcarbon.net) : jamais de cible externe. C’est un pentest de notre propre infrastructure — légitime, cadré, et écrit ici pour qu’il ne dérive pas.

Cibler le vrai livrable. La cible doit être le binaire *-unknown-linux-air (notre std, sans glibc, static-pie — ADR-103), pas la version gnu de test : tester un artefact qu’on ne livre pas ne prouverait rien sur ce qu’on livre. Prérequis : air-sshd linux-air redéployé et active sur speedy.

3. Outillage — tiers pour la confrontation, maison pour la mesure fine

Installé sur carbon (hors dépôt, comme cbindgen — n’altère ni l’arbre Air ni le Cargo.lock) :

CatégorieOutilCe qu’il éprouve
Audit algos + politiquessh-audit 3.9.0on n’annonce que du moderne ; détecte Terrapin, algos faibles
Terrapin (CVE-2023-48795)Terrapin-Scanner 1.1.3le strict-KEX (U.0) mitige réellement
Recon / méthodes d’authnmap 7.98 + NSEsurface annoncée conforme
Brute-force / dropncrack 0.7, hydra 9.6login-grace + essais bornés (U.4) coupent
DoS réseauhping3 3.0tenue sous SYN flood

Écrit en Rust, in-tree, au moment de la campagne (aucun outil clé-en-main fiable) :

  • Harnais de timing (niveau 2). Mesure la distribution des temps de réponse entre classes d’entrées (user existant / inexistant ; bon / mauvais secret), avec statistique robuste au bruit réseau : quantiles bas (le minimum est moins bruité que la moyenne), tests non-paramétriques (Mann-Whitney), grand nombre d’échantillons.
  • Harnais dudect (niveau 1). Le même en local, cycle-précis, sur les fonctions sensibles isolées.
  • Harnais de DoS pré-auth. Ouvre N connexions laissées en pré-auth et vérifie que le démon les drop (login-grace) au lieu d’épuiser ses descripteurs — le vecteur DoS qui ne dépend pas des algorithmes, donc le plus intéressant à éprouver.

Le harnais maison est cohérent avec la doctrine sans-IO ([ADR-091]) : le cœur de mesure est pur et testable ; seul le pilote parle au réseau.

4. Critères de réussite — écrits avant de tirer

« On résiste » n’est mesurable que si l’on a écrit à quoi. Par vecteur :

  • Terrapin : Terrapin-Scanner rapporte non vulnérable ; ssh-audit ne signale aucun algorithme faible ni downgrade.
  • Brute-force : après le nombre d’essais d’ADR-094 U.4, la connexion est coupée ; ncrack/hydra ne progressent pas et le démon reste disponible pour les autres.
  • Énumération de login : la distribution des temps de réponse user-existant vs user-inexistant est statistiquement indistinguable (niveau 2), et le chemin de résolution est constant-time (niveau 1). Idem bon/mauvais secret.
  • DoS pré-auth : N connexions pendantes n’empêchent pas une connexion légitime ; les slots sont récupérés par le login-grace.
  • DoS réseau : sous SYN flood hping3, le démon survit et se rétablit.

Un critère non atteint ouvre un correctif tracé, pas une exception silencieuse.

5. Séquence

C.0 (cet ADR) → déploiement de la cible linux-air sur speedy → audit non intrusif (ssh-audit, Terrapin, nmap) → harnais dudect (niveau 1) → harnais timing réseau (niveau 2) → brute-force → DoS pré-auth → DoS réseau. Chaque étape : résultat consigné, critère coché ou correctif ouvert.

Conséquences

  • air-sshd acquiert une attestation de robustesse face aux attaques SSH connues, au-delà des tests unitaires — et une preuve de ses contre-mesures.
  • Aucune modification de couche n’est induite par cet ADR ; les correctifs éventuels suivront la discipline habituelle (additif couche 1 si besoin, jamais de raccourci).
  • L’outillage vit sur carbon, hors dépôt ; le harnais maison sera in-tree, test-only ([ADR-030]).
  • Dépendance : la campagne attend la clôture d’air-sshd (fin de la phase SFTP) et un redéploiement linux-air de la cible sur speedy.

Alternatives rejetées

  • Prouver le constant-time par le seul timing réseau. Rejeté : statistiquement non concluant (jitter). Le niveau 1 local est indispensable.
  • N’utiliser que des outils tiers. Rejeté : aucun n’éprouve rigoureusement le timing SSH ni le DoS pré-auth — d’où le harnais maison.
  • Tester la build gnu (plus simple à outiller). Rejeté : ce n’est pas le livrable (ADR-103). On éprouve ce qu’on livre.
  • Lancer la campagne avant clôture. Rejeté : la surface bouge encore (SFTP en cours) ; on éprouve une cible figée.

Références

  • ADR-093 — transport SSH-2, strict-KEX.
  • ADR-094 — userauth : login-grace, essais bornés, anti-énumération.
  • ADR-091 — motif sans-IO (harnais fuzzable/pur).
  • CVE-2023-48795 — Terrapin. CVE-2018-15473 — énumération d’utilisateurs OpenSSH.