CHƯƠNG 06 · SECURITY · ~120 phút

HTTPS, TLS,
Certificates

Mã hoá & xác thực HTTP. Hiểu chương này, bạn sẽ trả lời được câu phỏng vấn kinh điển: "Khi gõ https://google.com, có chuyện gì xảy ra?". Học TLS handshake, asymmetric vs symmetric encryption, certificate chain, Let's Encrypt, và tại sao có HTTPS thì attacker vẫn nhìn được domain.

6.1 Tại sao cần HTTPS?

HTTP plain có 3 vấn đề bảo mật:

  1. Sniffing (eavesdropping): bất kỳ ai trên đường truyền (Wi-Fi cùng quán cà phê, ISP) đều đọc được password, cookie
  2. Tampering: attacker chèn quảng cáo, JavaScript độc vào response (xảy ra với ISP một số nước)
  3. Impersonation: attacker giả mạo server (DNS spoofing, ARP poisoning)

HTTPS = HTTP + TLS (Transport Layer Security). Giải quyết cả 3:

  • Confidentiality: mã hoá → không sniff được
  • Integrity: MAC (Message Authentication Code) → phát hiện tamper
  • Authentication: certificate → xác thực server thật là server

HTTPS port

Mặc định 443. HTTP plain: 80.

6.2 Symmetric vs Asymmetric Encryption

Symmetric — 1 key cho cả encrypt và decrypt

  • Vd: AES, ChaCha20
  • Cực nhanh — hardware AES-NI có thể đạt nhiều GB/s
  • Vấn đề: làm sao 2 bên có cùng key mà không bị lộ qua network?

Asymmetric — 2 key (public + private)

  • Vd: RSA, ECDSA, EdDSA
  • Encrypt bằng public key → chỉ private key decrypt được
  • Sign bằng private key → bất kỳ ai có public key cũng verify được
  • Chậm hơn symmetric ~1000x
  • Giải quyết được vấn đề key exchange
Symmetric (AES): Asymmetric (RSA): ┌─────┐ ┌─────────┐ │ key │ encrypt + decrypt │ public │ encrypt │ │ (giống nhau) │ key │ └─────┘ └─────────┘ ┌─────────┐ │ private │ decrypt │ key │ └─────────┘

TLS dùng cả hai

  1. Asymmetric chỉ dùng 1 lần ở handshake để trao đổi 1 "session key" symmetric
  2. Sau đó dùng symmetric để mã hoá data thực — nhanh

Đây là hybrid encryption — kết hợp ưu điểm cả hai.

6.3 TLS 1.2 Handshake — phải vẽ được

Đây là phần phỏng vấn hay yêu cầu vẽ. TLS 1.2 cần ~2 RTT.

Client Server ────── ────── 1. Client Hello ─────────────▶ (TLS version, cipher suites, client random) ◀───────── 2. Server Hello (chosen cipher, server random) ◀───────── 3. Certificate (server's public key + chain of CAs) ◀───────── 4. Server Key Exchange (DH parameters cho PFS) ◀───────── 5. Server Hello Done 6. Verify certificate: - Cert chain → trusted root CA? - Hostname match? - Not expired? 7. Client Key Exchange ────────▶ (encrypt pre-master secret với server's public key) 8. Cả 2 bên derive session key từ pre-master + 2 random. 9. Change Cipher Spec ─────────▶ Finished (encrypted) ◀───────── 10. Change Cipher Spec Finished (encrypted) ──────── Bắt đầu HTTPS data trên symmetric encryption ────────

Các bước key

  1. Client Hello: client báo TLS version + danh sách cipher mình support + client random
  2. Server Hello: server chọn cipher + gửi server random + certificate
  3. Verify cert: client check cert chain, hostname, expiry
  4. Key Exchange: client tạo pre-master secret, encrypt bằng server's public key, gửi
  5. Derive session key: 2 bên dùng pre-master + 2 random → derive cùng 1 session key (symmetric)
  6. Finished: 2 bên gửi message encrypted để confirm

2 RTT trước khi có thể gửi HTTP request. Cộng với 1.5 RTT của TCP = 3.5 RTT tổng cho HTTPS qua HTTP/1.1.

6.4 TLS 1.3 (2018) — đơn giản hoá đáng kể

TLS 1.3 cải tiến lớn:

1. Handshake còn 1 RTT

Client gửi key share luôn ở Client Hello — không đợi 1 round nữa.

Client Server ────── ────── ClientHello + key_share ─────────▶ Server xử lý: - chọn cipher - tính shared secret - encrypt cert + ack ◀────── ServerHello + key_share + (encrypted) Cert + Finished Verify cert, derive key ── Finished ──▶ Derive session key ── HTTPS data ──▶ ◀── HTTPS data ── Total: 1 RTT (vs 2 RTT của TLS 1.2)

2. 0-RTT với session resumption

Nếu client đã connect server trước đây, có "PSK" (pre-shared key) → có thể gửi data ngay trong Client Hello đầu tiên. 0 RTT!

Trade-off: 0-RTT data có thể bị replay attack — chỉ dùng cho idempotent request.

3. Forward secrecy bắt buộc

Bỏ các cipher không có Perfect Forward Secrecy. Nếu private key server bị lộ trong tương lai, traffic cũ vẫn an toàn.

4. Bỏ các thứ cũ kỹ

  • Bỏ RSA key exchange (chỉ dùng (EC)DHE)
  • Bỏ MD5, SHA-1, RC4, 3DES
  • Bỏ static DH
  • Bỏ compression (CRIME attack)

6.5 Certificate & PKI — làm sao biết server là thật?

Vấn đề: client nhận được public key — làm sao biết key đó là của google.com thật, không phải của attacker?

Giải pháp: Public Key Infrastructure (PKI). Browser tin tưởng một danh sách Root CA (Certificate Authority). Mỗi cert phải được sign bởi một CA trong chain dẫn về Root.

Certificate chain

┌──────────────────────────────────────┐ │ Root CA (vd DigiCert Global Root) │ ← Browser/OS tin sẵn │ Self-signed, public key in browser │ └──────────────┬───────────────────────┘ │ signs ▼ ┌──────────────────────────────────────┐ │ Intermediate CA (vd DigiCert TLS │ │ RSA SHA256 2020 CA1) │ └──────────────┬───────────────────────┘ │ signs ▼ ┌──────────────────────────────────────┐ │ Leaf cert (vd google.com) │ │ Public key của google.com │ │ Domain: google.com (+ wildcards) │ │ Validity: 2024-08-01 → 2024-10-30 │ └──────────────────────────────────────┘

Verify cert

Client kiểm tra theo thứ tự:

  1. Signature chain: leaf signed by intermediate, intermediate signed by root, root in trusted store
  2. Domain matches: cert có Subject Alternative Name (SAN) khớp domain đang truy cập
  3. Validity period: chưa expired, chưa "not yet valid"
  4. Revocation: chưa bị revoke (qua CRL hoặc OCSP)

Một bước fail → browser hiển thị warning đỏ.

Self-signed certificate

Bạn có thể tự tạo cert mà không qua CA. Browser sẽ warning vì không trust. Dùng cho dev/test, không cho production public.

6.6 Let's Encrypt — TLS miễn phí cho mọi người

Trước 2015, mua cert từ DigiCert/Comodo tốn $50-500/năm. Let's Encrypt (2015) cấp free, automated qua giao thức ACME.

Domain Validation (DV) flow

  1. Server gọi Let's Encrypt: "Tôi muốn cert cho example.com"
  2. LE: "Đặt file /.well-known/acme-challenge/<token> trên http://example.com với content X"
  3. Server đặt file
  4. LE truy cập http://example.com/.well-known/acme-challenge/<token> → đọc được X → chứng minh server kiểm soát domain
  5. LE cấp cert valid 90 ngày

Tools: certbot, caddy (auto), traefik (auto).

# Certbot
sudo certbot --nginx -d example.com -d www.example.com

# Hoặc Caddy auto:
# Caddyfile:
example.com {
  reverse_proxy localhost:3000
}
# Chạy caddy → tự xin cert + renew

Cert validity 90 ngày — vì sao ngắn?

  • Buộc auto-renew → nếu compromise, "blast radius" nhỏ
  • Khuyến khích automation — không ai nên renew tay mỗi năm

6.7 SNI — Server Name Indication

Vấn đề: 1 web server có IP duy nhất nhưng host nhiều domain (vd siteA.com, siteB.com). Khi TLS handshake bắt đầu, server chưa biết domain nào — chưa thể chọn đúng cert.

Giải pháp: SNI = client gửi domain trong Client Hello (plaintext). Server đọc, chọn đúng cert.

⚠️ Privacy issue

SNI là plaintext → ISP/firewall biết bạn đang truy cập domain nào (mặc dù không thấy URL/data nhờ HTTPS).

Giải pháp: Encrypted Client Hello (ECH) — encrypt SNI bằng key của front server. Đang được Cloudflare push nhưng chưa universal.

6.8 Cipher Suite & Perfect Forward Secrecy

Cipher suite

Một cipher suite chỉ định 4 thuật toán:

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
    │     │     │       │            │
    │     │     │       │            └─ MAC: SHA-256
    │     │     │       └────────────── Cipher: AES-128-GCM
    │     │     └────────────────────── Auth: RSA cert
    │     └──────────────────────────── Key Exchange: ECDHE (Elliptic Curve DH Ephemeral)
    └────────────────────────────────── Protocol: TLS

TLS 1.3 đơn giản hoá: chỉ chỉ định AEAD + hash, key exchange tách biệt:

TLS_AES_128_GCM_SHA256
    │     │             │
    │     │             └─ MAC/KDF: SHA-256
    │     └─────────────── AEAD: AES-128-GCM
    └─────────────────────── Protocol

Perfect Forward Secrecy (PFS)

Vấn đề: nếu attacker ghi lại traffic encrypted hôm nay, năm sau bằng cách nào đó có private key của server, có thể decrypt traffic cũ.

Giải pháp PFS: mỗi session dùng ephemeral key — sau session, key bị huỷ. Server private key chỉ dùng để authenticate, không trực tiếp encrypt data.

(EC)DHE = (Elliptic Curve) Diffie-Hellman Ephemeral cho PFS. Static RSA không có PFS → TLS 1.3 bỏ.

6.9 Tools thực tế

openssl — Swiss Army knife

# Inspect cert của 1 server
openssl s_client -connect example.com:443 -servername example.com
# Show full handshake + cert chain

# Chỉ lấy cert
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -text

# Check expiry
echo | openssl s_client -connect example.com:443 2>/dev/null \
  | openssl x509 -noout -dates

# Test specific TLS version
openssl s_client -tls1_3 -connect example.com:443

curl

curl -v https://example.com 2>&1 | grep -E '(TLS|cert|CN)'
# * TLSv1.3 (OUT), TLS handshake, Client hello (1)
# * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
# * Server certificate:
# *  subject: CN=example.com
# *  issuer: ...

SSL Labs — test online

https://www.ssllabs.com/ssltest/ — chấm điểm A+ đến F cho cấu hình TLS server. Kiểm tra: weak ciphers, cert chain, HSTS, ...

Chrome DevTools

Browser → Padlock icon → Connection is secure → Certificate viewer. Show full chain, validity, fingerprints.

Bài tập

Bài 1 — Inspect cert

Chạy openssl s_client -connect github.com:443. Tìm: TLS version, cipher, cert chain, expiry.

Bài 2 — Self-signed cert dev

Tạo self-signed cho localhost: openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days 30 -subj "/CN=localhost". Dùng cho local HTTPS test.

Bài 3 — Vẽ TLS 1.2 handshake

Trên giấy, vẽ đầy đủ TLS 1.2 handshake — labels mỗi message, ai gửi cho ai. Đếm số RTT.

Bài 4 — Let's Encrypt thực hành

Thuê 1 VPS (DigitalOcean $5), trỏ subdomain về VPS. Cài Caddy, viết Caddyfile. Quan sát Caddy tự xin cert.

Bài 5 — SSL Labs

Test 3 site quen thuộc trên ssllabs.com (vd github.com, facebook.com, site cá nhân). So sánh điểm.

Bài 6 — Suy ngược

Khi vào https://example.com, attacker trên cùng Wi-Fi có thể biết: (a) URL? (b) Domain? (c) Cookie? (d) Password gửi POST? (e) Kích thước response? Trả lời từng câu.

🧪 Quiz cuối chương

Câu 1. HTTPS đảm bảo 3 tính chất?

  • Speed, Privacy, Cache
  • SEO, Auth, Performance
  • Confidentiality (encrypt), Integrity (MAC), Authentication (cert)
  • Encryption, Compression, Routing

Đáp án: Confidentiality + Integrity + Authentication. 3 vấn đề HTTP plain không giải quyết được.

Câu 2. TLS dùng cả symmetric và asymmetric vì?

  • Để phức tạp hoá
  • Asymmetric chậm nhưng giải quyết key exchange; Symmetric nhanh cho data — kết hợp ưu điểm
  • Vì backward compat
  • Vì spec yêu cầu

Đáp án: hybrid encryption. Asymmetric chỉ ở handshake; sau đó symmetric với session key.

Câu 3. TLS 1.3 cần bao nhiêu RTT cho handshake?

  • 1 RTT (hoặc 0-RTT với resumption)
  • 2 RTT
  • 3 RTT
  • 4 RTT

Đáp án: 1 RTT. Cải thiện đáng kể từ 2 RTT của TLS 1.2. Có thể 0-RTT với PSK resumption.

Câu 4. Browser verify certificate bằng cách?

  • Hỏi search engine
  • So sánh với password
  • Check signature chain dẫn về 1 trusted Root CA, hostname match, chưa expired, chưa revoked
  • Encrypt và decrypt thử

Đáp án: chain → root CA + hostname + expiry + revocation. Bất kỳ bước fail → warning đỏ.

Câu 5. Perfect Forward Secrecy (PFS) là?

  • Mã hoá double
  • Mỗi session dùng ephemeral key — leak server's private key sau này không decrypt được traffic cũ
  • Không bao giờ cho phép decrypt
  • Encryption đối xứng

Đáp án: ephemeral session key. (EC)DHE cho PFS. Static RSA không có → TLS 1.3 bỏ.

Câu 6. Let's Encrypt cấp cert miễn phí bằng cách?

  • Trust mọi user
  • Free trial 90 ngày
  • Domain Validation tự động qua HTTP-01 challenge — verify server kiểm soát domain
  • Không cần verify

Đáp án: HTTP-01 challenge. Server đặt file đặc biệt → LE truy cập → confirm ownership → cấp cert.

Câu 7. SNI dùng để?

  • Tăng tốc handshake
  • Client báo domain đang truy cập trong Client Hello → server chọn đúng cert (1 IP host nhiều domain)
  • Mã hoá DNS
  • Authentication user

Đáp án: 1 IP host nhiều domain. Plaintext → privacy issue, ECH đang giải quyết.

Câu 8. Khi attacker trên cùng Wi-Fi với bạn truy cập https://bank.com, attacker biết được gì?

  • Mọi thứ (URL, password)
  • Không gì cả
  • Chỉ thấy domain (qua SNI/DNS), IP, kích thước traffic — không thấy URL/cookie/body
  • Chỉ thấy IP

Đáp án: domain + IP + size. HTTPS bảo vệ content nhưng metadata vẫn lộ. ECH + DoH/DoT để giấu domain.

Tổng kết chương 6

  • ✅ HTTPS = HTTP + TLS, cho 3 tính chất: Confidentiality + Integrity + Authentication
  • ✅ Hybrid encryption: Asymmetric ở handshake → Symmetric cho data
  • TLS 1.2 handshake: 2 RTT; TLS 1.3: 1 RTT (hoặc 0-RTT với PSK)
  • Certificate chain: leaf → intermediate → root CA. Browser tin sẵn root CA
  • ✅ Browser verify: chain + hostname + expiry + revocation
  • Let's Encrypt: free, automated qua ACME, HTTP-01 challenge, valid 90 ngày
  • SNI: 1 IP nhiều domain; SNI plaintext → ECH bắt đầu phổ biến
  • PFS: ephemeral key mỗi session, lộ private key tương lai cũng an toàn traffic cũ
  • ✅ Tools: openssl s_client, curl -v, SSL Labs, Chrome DevTools
  • ✅ HTTPS bảo vệ content nhưng không hide: domain (SNI/DNS), IP, kích thước
← Chương trước Chương 05: HTTP Chương kế tiếp Chương 07: DNS →