Fiabilité et Sécurité des Applications

Authentification serveur et client

Romuald THION

2024-05-17 – TIW-FSA/MIF29

Introduction

👉 L’authentification désigne le processus visant à vérifier qu’une entité (personne, service, machine) est bien légitime pour accéder au système.

Authentification versus autorisation

401 Unauthorized Authentication
403 Forbidden Authorization

Voir Authentication vs. Authorization.

Les facteurs de validation pour l’authentification

  • Ce que je sais (knowledge factors)
    • PIN, mot de pass, passphrase, question de sécurité
  • Ce que je possède (ownership factors)
    • carte à puce, clef usb, téléphone, jeton,
  • Ce que je suis (inherence factors)
    • empreintes digitales, rétine, voix, visage, ADN.

👉 Pour le dernier, on parle plutôt d’identification, car il n’y a pas de secret.

Briques cryptographiques

Principales primitives 🧱

  • 🎲 Nombres aléatoires
  • #️⃣ Fonctions de hachage
  • 🔑 Chiffrement symétrique
  • 🔒 Chiffrement asymétrique
  • ✉️ Message authentifié
  • 🔏 Signature

Des primitives aux applications

  • Primitive cryptographique : e.g., RSA
    • Schéma cryptographique : e.g., PKCS#1 OAEP
      • Protocole cryptographique : e.g., TLS 1.3
        • Application : vous êtes ici 👈

Références

🔖 Voir http://mif29-crypto-sec.pages.univ-lyon1.fr/ pour des rappels :

Authentification par mot de passe

A Research Agenda Acknowledging the Persistence of Passwords

Despite countless attempts and near-universal desire to replace passwords, they’re more widely used than ever. The authors assert that, in many instances, passwords are the best-fit solution […].

Among security experts, there is near-unanimous agreement on the desirability of replacing passwords. Yet, this meta-goal is accepted without an understanding of what exactly is required of a replacement or what will improve once they are replaced.

Principe de la vérification des mots de passe, crédits LAURADOUX C.

Avec h une fonction de hachage, le protocole usuel de vérification :

  1. A_i \to B: \langle A_i, pw_i \rangle
  2. B \to A_i: OK si \langle A_i, h(pw_i) \rangle \in \mathrm{pt}

Le vérificateur stocke les paires \langle A_i, h(pw_i) \rangle dans la table des mots de passe \mathrm{pt}

maintainer:OYnL8rCBbf7rc
edgar:C8Z6wDFKm5bV6
patrick:58kk0mpCjpL9o
edwin:.8cBf8RFZqfvI
frank:gvEFH2KSvYZS2
jaap:NMS4yrkEfQz9c

On ne stocke pas les mots de passes en clair, mais on reste exposé à une attaque hors ligne si on connaît \mathrm{pt}.

☢️ Dans ce protocole les mots de passe circulent en clair, il est donc nécessaire d’avoir un canal de communication sécurisé entre les partenaires, typiquement TLS/HTTPS. ☢️

🤔 Passer A_i \to B: \langle A_i, h(pw_i) \rangle ne change pas la sécurité, car on peut rejouer le haché.

Attaques et contre-mesures

On a un compromis temps/mémoire en calculant les hachés à l’avance.

  • On calcule et stocke des \langle pw_i, h(pw_i) \rangle dans \mathrm{t}
  • On indexe \mathrm{t} sur h(pw_i).
  • Pour casser \langle A_i, h(pw_i) \rangle \in \mathrm{pt}, il suffit d’une recherche dichotomique sur \mathrm{t}.

La méthode des rainbow tables est un très beau compromis entre calculer tous les hash à l’avance et tout calculer à la volée, voir Making a Faster Cryptanalytic Time-Memory Trade-Off

Exemple sur la base https://haveibeenpwned.com, disponible dans la base pedago du serveur PostgreSQL bd-pedago.univ-lyon1.fr :

\d pwned
--                                       Table "pedago.pwned"
--     Column    |         Type          |
-- --------------+-----------------------+
--  hash_id      | integer               |
--  hash_content | character varying(40) |
--  time_used    | integer               |
-- Indexes:
--     "pwned_pkey" PRIMARY KEY, btree (hash_id)
--     "pwned_hash_content_left_5" btree ("left"(hash_content::text, 5))
select count(*) from pwned;
-- 572 611 621
select sum(time_used) from pwned;
-- 3 457 649 046
select upper(encode(digest('password', 'sha1'), 'hex'));
-- 5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8

select hash_id, time_used
from pwned
where left(hash_content::text, 5) = '5BAA6'
      and hash_content::text = '5BAA6 [...] 68FD8';
--  hash_id | time_used
-- ---------+-----------
--        4 |   3759315

Benchmark sur hashcat

OpenCL API (OpenCL 3.0 CUDA 12.1.109) [...]
========================================================================
* Device #1: NVIDIA GeForce GTX 1650, 3520/4095 MB (1023 MB allocatable), 14MCU

* (MD5) 11823.4 MH/s [...]
* (SHA1) 3724.8 MH/s [...]
* (SHA2-256) 1587.3 MH/s [...]
* (SHA2-512) 462.9 MH/s [...]
* (NTLM) 20751.5 MH/s [...]
* (NetNTLMv1 / NetNTLMv1+ESS) 10998.3 MH/s [...]
* (bcrypt $2*$, Blowfish (Unix)) [I : 32] 7333 H/s [...]

Combien de temps pour explorer tous les mots de passe de longueur n avec 62 caractères autorisés ?

Source @TerahashCorp

Contre-mesures

online

On essaie et on attend la réponse du vérificateur :

  • Limiter le nombre d’essais ;
  • Mettre un captcha pour éviter les bots ;
  • Bannir, temporiser après échec.

Pour l’utilisabilité, il faut une procédure de récupération ou de changement de mot de passe, mais attention à sa sécurité, car la surface d’attaque est augmentée. Voir CAPEC-50: Password Recovery Exploitation.

offline

On dispose de \mathrm{pt}, on cherche pw t.q. pt=h(pw).

  • 🧂 Éviter les compromis temps/mémoire
    • en ajoutant un aléa appelé un sel
  • 🐢 Rendre l’attaque complexe en temps
    • en prenant une fonction h lente,
  • 🐘 Rendre l’attaque complexe en mémoire
    • avec h qui nécessite inévitablement de la mémoire
    • limite les performances des circuits ASIC dédiés.

💡 Les fonctions sûres pour dériver des mots de passes sont appelées Key Derivation Function – KDF. Par exemple, pour élargir un secret à la taille d’un bloc (e.g., 32 octets) dans le chiffrement symétrique.

L’ajout de sel

On ajoute une donnée aléatoire non confidentielle au mot de passe, le sel.

Dans une table des mots de passes salés, le vérificateur stocke les paires \langle A_i, s_i, h(pw_i,s_i) \rangle :

maintainer:ef$OYnL8rCBbf7rc
edgar:01$C8Z6wDFKm5bV6
patrick:45$58kk0mpCjpL9o
edwin:a5$.8cBf8RFZqfvI

Exemples d’authentification par mot de passe

Authentification Linux

Les hachés sont stockés dans /etc/shadow, avec différentes méthodes :

Exemples, voir unix.stackexchange.com

    > mkpasswd -m sha-512 --salt abcdefgh
    $6$u2bvcyi0$76I3KxGizdl/PENw[...]4FUhEBcKcg.

    > openssl passwd -6 -salt abcdefgh
    $6$u2bvcyi0$76I3KxGizdl/PENw[...]4FUhEBcKcg.

Authentification HTTP

On ne parle pas ici d’HTTPS mais des moyens inclus dans HTTP (Basic, Digest, Bearer, etc.) pour l’authentification.

Voir HTTP authentication et WWW-Authenticate sur MDN.

HTTP Basic

RFC 7617 - The ‘Basic’ HTTP Authentication Scheme

  • On calcule base64(login:password).
  • On transmet l’en-tête Authorization: Basic.
HTTP Digest

RFC 7616 - HTTP Digest Access Authentication

  • On reçoit un HTTP 401 Unauthorized avec un challenge dans l’en-tête WWW-Authenticate
  • On calcule H=(HA1, nonce, nc, cnonce, qop, HA2) avec
    • HA1=H(user:realm:password)
    • HA2=H(method:uri_path)
  • On transmet l’en-tête Authorization: Digest
Autres modes
Exemples manuels en Python

🐍 Voir fichier Python http_auth.py et la trace Wireshark pour HTTP Basic et HTTP Digest.

Ci-dessous les équivalents avec https://httpie.io/ sur le serveur https://pie.dev/ :

http --verbose \
     --auth-type basic --auth romu:pwd \
     http://pie.dev/basic-auth/romu/pwd
http --verbose \
     http://pie.dev/basic-auth/romu/pwd \
     Authorization:" Basic cm9tdTpwd2Q="

http --verbose \
     --auth-type digest --auth romu:pwd \
     http://pie.dev/digest-auth/auth/romu/pwd

# uniquement la première 401 avec WWW-Authenticate,
http --verbose http://pie.dev/digest-auth/auth/romu/pwd

Recommandations

Gestion des mots de passes serveur

Voir OWASP Authentication cheat sheet

  • Implement Proper Password Strength Controls
  • Implement Secure Password Recovery Mechanism
  • Store Passwords in a Secure Fashion
  • Compare Password Hashes Using Safe Functions
  • Transmit Passwords Only Over TLS
  • Require Re-authentication for Sensitive Features

OWASP : password storage cheat sheet, voir la section Password Hashing Algorithms

Argon2 is a password-hashing function that summarizes the state of the art in the design of memory-hard functions and can be used to hash passwords for credential storage, key derivation, or other applications.

Argon2 le gagnant du concours PHC est nativement salé 🧂, coûteux en temps 🐢 et en mémoire 🐘.

👉 Voir par exemple le wrapper JavaScript ou celui Python.

Pour les utilisateurs finaux

⚠️ Utiliser un gestionnaire de mots de passe comme https://keepass.info/ ou https://keepassxc.org/. ⚠️

Extrait du rapport d’audit de Zaur Molotnikov.

KeePassXC provides sufficient cryptographic protection (confidentiality, integrity and authenticity) to the confidential information the user is storing in the database, given that the user selects a strong authentication method.

Authentification serveur / PKI

🚨 Problème majeur des systèmes à clefs publiques : l’authentification. 🚨

On peut transmettre les clefs publiques sur un canal non sûr pour ensuite établir un canal sécurisé (en choisissant une clef secrète commune aux parties), mais comment assurer effectivement qu’il s’agit du bon interlocuteur ? 🤔

Certificats

🔏 Les certificats (X509) capturent les relations de la forme A dit que K est bien la clef publique de B. Un certificat contient :

  • L’identité du certificateur.
  • L’identité du certifié.
  • La clef publique du certifié.
  • La date d’émission et la date limite de validité.
  • Numéro de série, algorithmes utilisés, etc.
  • La signature des contenus précédents avec la clef (secrète !) du certificateur.

🤔 Comment avoir confiance dans le certificateur ?

Certificate Authority

  • Chacun fait confiance à une liste de d’autorités de certification (CA - Certificate Authority 🇬🇧) dites, de confiance.
  • Ces autorités de certification se certifient elles-mêmes (racine) et entre-elles.
    • ce sont les seules du réseau à le faire ;
  • Les autorités délèguent pour créer des chaînes de certification.
    • Elles sont les racines de la forêt des relations de délégations.

🤯 Et à la racine, à quelles autorités fait-on confiance, implicitement ?! 🤯

👉 Voir Mozilla Included CA Certificate List qui fait de remarquables efforts de transparence à ce sujet.

Création de certificat / PKI

Source Bill’s security site.

Chaîne de certification

Source Wikipedia – root certificate.
Exemple ssl-cert-snakeoil

Dans les distributions sur Debian :

  • /etc/ssl/private/ssl-cert-snakeoil.key
    • un couple de clef asymétrique (e.g., RSA 2048)
  • utilisé pour générer les certificats auto-signés
    • /etc/ssl/certs/ssl-cert-snakeoil.pem

👉 Voir https://mkcert.dev pour créer une mini CA pour le dev.

openssl verify -show_chain /etc/ssl/certs/ssl-cert-snakeoil.pem

ssl-cert-snakeoil.pem: OK
Chain:
depth=0: CN = localhost.localdomain

💡 La gestion des clefs est un problème difficile et technique, voir par exemple https://pki-tutorial.readthedocs.io/en/latest/ pour la mise en place de PKI – Public Key Infrastructures avec OpenSSL.

🧑‍⚖️ Le problème de la révocation en particulier, via les Certificate Revocation List – CRL ou mieux, via Online Certificate Status Protocol – OCSP.

Transport Layer Security / HTTPS

TLS est le successeur de SSL, la couche transport sécurisée de HTTP(S). Extrait de Wikipedia :

The TLS protocol aims primarily to provide security, including privacy (confidentiality), integrity, and authenticity through the use of cryptography, such as the use of certificates, between two or more communicating computer applications.

Source High Performance Browser Networking

Historique

Source Wikipedia

De nombreuses attaques ont motivé les évolutions de SSL 2.0, SSL 3.0, TLS 1.0, TLS 1.1 puis de TLS 1.2 et TLS 1.3

Attaques historiques de SSL/TLS. SSL est obsolète, les versions recommandées de TLS sont la 1.2 et la 1.3

2.1. SSL Stripping ......................................3
2.2. STARTTLS Command Injection Attack (CVE-2011-0411) ..4
2.3. BEAST (CVE-2011-3389) ..............................4
2.4. Padding Oracle Attacks .............................4
2.5. Attacks on RC4 .....................................5
2.6. Compression Attacks: CRIME, TIME, and BREACH .......5
2.7. Certificate and RSA-Related Attacks ................5
2.8. Theft of RSA Private Keys ..........................6
2.9. Diffie-Hellman Parameters ..........................6
2.10. Renegotiation (CVE-2009-3555) .....................6
2.11. Triple Handshake (CVE-2014-1295) ..................6
2.12. Virtual Host Confusion ............................7
2.13. Denial of Service .................................7
2.14. Implementation Issues .............................7
2.15. Usability .........................................8

Voir le bilan en 2015 dans la RFC 7457.

TLS 1.2

Handshake TLS 1.2 Source High Performance Browser Networking

TLS 1.3

Sur le blog IETF https://www.ietf.org/blog/tls13/

While the most widely used technology providing transport layer security for the Internet traces its origins back to SSL more than 20 years ago, the recently completed TLS 1.3 is a major revision designed for the modern Internet.

💣 TLS 1.2 était difficile à configurer à cause des nombreux algorithmes obsolètes et de leurs paramétrages. Avec TLS 1.3 :

  • RC4, DES, 3DES, AES-CBC, MD5, SHA-1
  • L’échange de clef RSA est abandonné,
    • mais RSA reste pour l’authentification
  • Le handshake a été simplifié et sécurisé.

Au final, cinq suites sont supportées par TLS 1.3 (au lieu des 37 de TLS 1.2, dont certaines non-sûres) :

TLS_AES_128_GCM_SHA256
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_128_CCM_SHA256
TLS_AES_128_CCM_8_SHA256

TLS 1.3 est maintenant bien supporté :

Voir https://caniuse.com/tls1-3

Le chiffrement authentifié Chacha20-Poly1305 aussi

Voir https://caniuse.com/chacha20-poly1305

Configuration TLS

Because the protocol is in a sense more simplified, this makes it less likely for administrators and developers to misconfigure the protocol. Jessie Victors, a security consultant, specializing in privacy-enhancing systems and applied cryptography stated. Source.

Par exemple sur https://nginx.org/, en générant une configuration TLS 1.3 moderne avec https://ssl-config.mozilla.org, à comparer à la configuration intermédiaire qui prend TLS 1.2

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    ssl_certificate /path/to/signed_cert_plus_intermediates;
    ssl_certificate_key /path/to/private_key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
    ssl_session_tickets off;

    # modern configuration
    ssl_protocols TLSv1.3;
    ssl_prefer_server_ciphers off;
}

Délégation d’authentification

Principe

💡 Les mécanismes d’authentifications sont lents, lourds à mettre en œuvre (e.g. PKI) et la sécurité empêche souvent l’utilisateur. Une solution est de :

  • Centraliser l’authentification (Authentication Authority – AA)
  • Permettre l’accès à plusieurs services après une authentification principale auprès de l’AA (Single-Sign On – SSO).

👉 Les services ne sont plus responsables de l’authentification, ils la délèguent à l’AA.

Exemple avec JSON Web Token (JWT)

JSON Web Token (JWT) is an open standard (RFC RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA. Source

Extrait de la RFC 7519, Section 8. Implementation Requirements

Of the signature and MAC algorithms specified in JSON Web Algorithms [JWA], only HMAC SHA-256 (“HS256”) and “none” MUST be implemented by conforming JWT implementations. It is RECOMMENDED that implementations also support RSASSA-PKCS1-v1_5 with the SHA-256 hash algorithm (“RS256”) and ECDSA using the P-256 curve and the SHA-256 hash algorithm (“ES256”). Support for other algorithms and key sizes is OPTIONAL.

Exemple sur https://jwt.io/
Diagramme de séquence d’une application (source)

Remarques sur JWT

Central Authentication Service – CAS

Ici, le navigateur transmet un ticket qui sera échangeable par l’application auprès de l’AA (diagramme de séquence complet officiel)

Crédits Gauthier Perrineau (source)

Open Authorization – OAuth2

The OAuth 2.0 Authorization Framework

  • un protocole d’autorisations : un système de droits (appellé scopes)
    • pour accéder à un profil utilisateur après autorisation par ce dernier
  • OAuth2 implémente l’authentification car c’est un préalable à l’autorisation

OAuth2 est un standard très répandu, avec de très nombreux fournisseurs dont GitLab, Google, GitHub. Tous ne proposent pas OIDC (GitHub en particulier).

L’usage de OAuth2 pour l’authentification est tellement populaire pour avoir été standardisée par OpenID Connet – OIDC

  • OIDC est une couche d’identité au dessus d’OAuth2.
  • Permet d’obtenir un id_token JWT signé par le fournisseur.
  • Ce JWT est directement transférable au client
    • dans le cas d’OAuth2 pur, l’application est amenée à le générer elle-même.
Diagramme de séquence OAuth2 (source)

Exemple sur GitLab

Liste des scopes GitLab, e.g. https://forge.univ-lyon1.fr.

api
read_user
read_api
read_repository
write_repository
read_registry
write_registry
sudo
openid (OIDC)
profile (OIDC)
email (OIDC)

Voir aussi pour le GitLab

Références

Conclusion

Don’t roll your own crypto

The Memes of Information Security, source.

Cryptanalyse “traditionnelle”

Security, https://xkcd.com/538/.

Maintenance et dépendance logicielle

Dependency, https://xkcd.com/2347/.

Plus récemment, l’exemple de l’attaque sur xz :

Tweet sur la découverte d’Andres Freund.

🔖 Timeline of the xz open source attack et Everything I know about the XZ backdoor.

TP d’application

TP TIWFSA

👉 https://forge.univ-lyon1.fr/tiw-fsa/fsa-apps-auth

Intervention Stormshield

❓ Comment réaliser une application de ce type à l’échelle industrielle ?

Fonctionnalités, choix techniques et qualités sécurité du point de vue d’un éditeur spécialisé.