Chứng chỉ eMudhra đã thu hồi, phần mềm chưa cập nhật vẫn có thể dùng chứng chỉ này
Khóa CA yếu có thể giúp kẻ đứng giữa mạo danh server HTTPS. Demo TLS giải thích vì sao thu hồi chứng chỉ chưa đủ và pip cần cập nhật riêng.
Tôi vào PyPI thì thấy một dải cảnh báo vàng ngay đầu trang, yêu cầu cập nhật certifi, pip và uv vì sự cố chứng chỉ CA. Nhìn có vẻ nguy hiểm.
Bấm "See more", tôi tới thông báo ngày 20/10/2026 của đội Python. Họ yêu cầu cập nhật các công cụ tải package và cảnh báo nguy cơ MITM, tức kẻ đứng giữa mạo danh đầu bên kia của kết nối. Nếu attacker điều khiển được đường kết nối và client còn tin các khóa CA liên quan, server giả vẫn có thể qua bước kiểm tra chứng chỉ HTTPS. [1]
Với người đang cài dependency, hậu quả có thể là nhận nội dung do attacker gửi, dù URL vẫn bắt đầu bằng https://. Cảnh báo này nói về khả năng mạo danh đầu bên kia của kết nối. Nó không phải thông báo PyPI đã bị xâm nhập.
Tôi mở link tiếp theo và tới emudhra.we-have-a-problem.com. Ở đây, họ xác nhận private key của tám CA trung gian eMudhra đã bị lộ, kèm các chữ ký để người khác kiểm chứng quyền sử dụng khóa. [2]
Các chứng chỉ liên quan đã được thu hồi, nhưng từng phần mềm nhận và áp dụng thông tin ấy khác nhau. Có client dùng danh sách CA của hệ điều hành, có client mang một bản riêng. Demo kết nối TLS tới server giả sẽ xét chain và cách client kiểm tra thu hồi.
Khóa trung gian bị lộ

eMudhra vận hành dịch vụ cấp chứng chỉ emSign. Trong HTTPS, một Certificate Authority, viết tắt là CA, ký xác nhận mối liên hệ giữa tên miền và public key. Client dùng xác nhận đó khi quyết định có đang kết nối đúng server hay không.
Ngày 17/10, một nhà nghiên cứu báo cáo rằng họ có thể sử dụng những private key này. Mozilla kiểm tra độc lập và cũng khôi phục được các khóa. Sáu khóa dùng cho TLS, hai khóa dùng cho code signing. [3]
eMudhra nói quy trình tạo khóa đã sinh thêm một bộ khóa yếu, rồi bộ khóa này được dùng cho chứng chỉ. Nguyên nhân cụ thể vẫn đang được điều tra. [4]
Ảnh hưởng cũng không chỉ nằm ở khách hàng mua chứng chỉ eMudhra. Nếu client tin một CA có quyền cấp chứng chỉ cho tên miền đang truy cập, một chứng chỉ giả do CA đó ký có thể được chấp nhận, dù server thật đang mua chứng chỉ của bên khác.
Client kiểm tra server

Giả sử bạn cần tải phần mềm từ packages.test. Domain này được dựng riêng cho demo. Client và server chạy trên cùng máy, dùng CA tự tạo; chưa có bước chiếm mạng và cũng không dùng khóa eMudhra thật.
Certificate của server chứa tên miền và public key của server. Bên cấp nó ký lên những thông tin đó bằng private key của CA. Client kiểm tra chữ ký bằng public key tương ứng. Người sửa tên miền hoặc thay public key trong certificate sẽ làm chữ ký không còn khớp.
Một chuỗi thường gặp đi qua root CA, intermediate CA, rồi tới certificate của server, còn gọi là leaf. Client đã có root trong trust store, tức danh sách bên cấp chứng chỉ mà nó chấp nhận. Từ đó client kiểm tra lần lượt các chữ ký, thời hạn và ràng buộc của chain. Root không được tin chỉ vì nó tự ký; client phải có lý do tin root từ trước. [5]
Client còn đối chiếu tên miền đang truy cập. Chứng chỉ hợp lệ cho packages.test không được dùng thay cho different.test.
Server cũng phải chứng minh nó giữ private key đi cùng public key trên leaf. Với TLS 1.3, thông điệp CertificateVerify thực hiện bước chứng minh này bằng chữ ký gắn với quá trình handshake. Copy một certificate công khai từ website khác chưa đủ để giả làm website đó. [6]
Demo chạy bằng Python 3.14.3 với OpenSSL 3.6.3 cho kết quả:
| Kết nối | Kết quả |
|---|---|
| Server có chain được tin, đúng hostname | Chấp nhận TLS 1.3 |
| Vẫn chain đó, client yêu cầu hostname khác | Từ chối, hostname mismatch |
Mã hóa bảo vệ dữ liệu trên kết nối đã thiết lập. Những bước xác thực trên giúp client tránh thiết lập kết nối ấy với nhầm người.
Chứng chỉ của server giả

Attacker dựng một server khác, tạo cặp khóa riêng và ghi packages.test vào certificate. Nếu tự ký certificate ấy, client từ chối vì không tìm được bên cấp đáng tin.
Nhưng nếu attacker có private key của intermediate đang được client tin, họ có thể ký một leaf mới cho cùng tên miền. Leaf mới chứa public key của attacker. Khi client yêu cầu chứng minh quyền giữ private key của leaf, attacker làm được vì chính họ tạo ra cặp khóa đó.
| Certificate mà server giả đưa ra | Kết quả demo |
|---|---|
Tự ký, mang tên packages.test |
Từ chối, self-signed certificate |
| Intermediate được tin ký, vẫn tên đó | Chấp nhận TLS 1.3 |
Client vẫn bật kiểm tra certificate và hostname trong cả hai trường hợp. Không có verify=False.

Sơ đồ MITM mô tả cả hai phía; demo chỉ chạy kết nối giữa client và server giả.
Muốn dùng việc này để tấn công người khác, attacker còn phải khiến client nối tới server giả, chẳng hạn qua một mạng họ kiểm soát. Trong một cuộc MITM, attacker có thể kết thúc phiên TLS với client rồi mở phiên TLS khác tới server thật. Dữ liệu được giải mã tại phía attacker trước khi chuyển tiếp. Chỉ riêng khóa CA không giúp giải mã những phiên TLS đã ghi lại.
Tháng 8/2011, Google báo cáo các nỗ lực MITM nhằm vào người dùng, chủ yếu tại Iran, sử dụng chứng chỉ giả do DigiNotar cấp. Mozilla cũng nhận được báo cáo chứng chỉ bị sử dụng trong thực tế. Đó là một sự cố khác, không phải bằng chứng eMudhra đã có nạn nhân tương tự. [7] [8]
Sau khi CA thu hồi

CA có thể đưa số serial của một chứng chỉ vào Certificate Revocation List, viết tắt là CRL. Nó là danh sách chứng chỉ đã bị thu hồi, có chữ ký của bên phát hành. Certificate cũ vẫn còn nguyên những byte trước đó; chữ ký trên nó không tự biến mất.
Demo giữ nguyên server giả, rồi đưa intermediate của nó vào CRL. Client được cung cấp cả CA certificate lẫn CRL. Chỉ thay chính sách kiểm tra:
context.verify_flags |= ssl.VERIFY_CRL_CHECK_CHAIN
| Client có cùng dữ liệu CA và CRL | Kết quả demo |
|---|---|
| Không bật kiểm tra CRL | Vẫn chấp nhận TLS 1.3 |
| Bật kiểm tra CRL cho chain | Từ chối, certificate revoked |
OpenSSL phân biệt kiểm tra certificate với kiểm tra CRL. Cờ kiểm tra cả chain khiến verifier xét luôn intermediate, thay vì chỉ leaf. Nếu không tìm được CRL cần thiết, việc bật cờ này cũng có thể làm kết nối thất bại. [9]

Browser còn có các cơ chế riêng như blocklist và Certificate Transparency, hay CT. CT yêu cầu chứng chỉ đáp ứng chính sách ghi nhận vào log công khai; nó không phải một tên khác của CRL. Vì thế kết quả của client OpenSSL trong demo không thay cho phép kiểm tra browser.
Trong sự cố eMudhra, các root program đã phân phối biện pháp chặn, còn những phần mềm không nhận được thông tin thu hồi có thể phải cập nhật. Trang điều phối cũng chưa xác định được liệu các khóa yếu đã bị dùng để tấn công client không thực thi CT trước khi công bố hay chưa. [2]
Một cách khác là loại root liên quan khỏi bundle. Demo làm vậy và nhận lỗi không tìm được issuer đáng tin. Tuy nhiên, certificate có thể có đường cross-sign tới root khác. Muốn chặn đủ phải xét các đường chain còn được chấp nhận, hoặc chặn trực tiếp khóa intermediate bị lộ. [9]
Các bản CA bundle trong Python

certifi cung cấp một bundle root certificate. pip upstream lại mang một bản certifi bên trong nó. Nâng package certifi trong môi trường của ứng dụng không tự thay bản nằm trong pip.
Tài liệu pip nói system certificates được dùng bổ sung cho certifi. Do đó, chỉ cập nhật danh sách CA của OS không bảo đảm bản pip cũ đã bỏ root liên quan. Bản pip do một distro đóng gói có thể được sửa để dùng CA khác; cần theo hướng dẫn của đúng nhà phân phối. [10] [1]
Các bản vá của đợt tháng 10/2026 gồm:
| Thành phần | Mốc cần phân biệt |
|---|---|
| certifi | Advisory ghi bản vá 2026.10.18; Python khuyên dùng 2026.10.19 để giữ root không bị ảnh hưởng |
| pip | 26.2.2 mang certifi đã cập nhật |
| uv | 0.13.4 bỏ root liên quan khỏi bundle riêng; 0.13.5 bổ sung chặn khóa intermediate |
| CPython | 3.15.1, 3.14.9 và 3.13.17 cập nhật bundled pip |
Đây là mốc vá của sự cố; khi cập nhật, chọn bản mới phù hợp với môi trường. [11] [12] [13] [14]
Trong đúng môi trường ứng dụng đang chạy, có thể xem interpreter và bản pip bằng:
python -c "import sys; print(sys.executable)"
python -m pip --version
python -c "from pip._vendor import certifi; print(certifi.__version__); print(certifi.where())"
uv --version
Lệnh đọc pip._vendor dành cho bản pip upstream còn giữ thư viện vendored. Nếu distro đã thay cách đóng gói, kết quả có thể khác. Không có module certifi ở ngoài cũng không chứng minh pip không mang một bản bên trong.
Để bootstrap pip qua một client còn có nguy cơ bị MITM, thông báo Python cung cấp URL wheel gắn SHA-256. Lấy URL và checksum từ thông báo chính thức qua client đã được bảo vệ, rồi kiểm đúng hash; tải wheel và hash từ cùng một đường truyền đang bị mạo danh sẽ không giải quyết được vấn đề. [14]
Với uv, bản thân công cụ, managed Python và pip trong virtualenv là những thứ cần phân biệt. Release 0.13.5 yêu cầu cập nhật managed Python bằng uv python upgrade, đồng thời nâng pip riêng trong virtualenv đã có. Các môi trường pin Python cũ không tự chuyển sang interpreter mới. [13]
Container cũng giữ filesystem của riêng nó. Cập nhật laptop không ghi lại bundle nằm trong image; cần rebuild bằng dữ liệu mới, tránh tái sử dụng layer giữ certificate cũ. [1]
Đào sâu: Khóa nhỏ hơn 256
Mozilla xác định các private scalar P-384 bị ảnh hưởng đều nhỏ hơn 256. Với scalar dương, tập ứng viên đó chỉ có các số từ 1 đến 255. Public key đã nằm trong certificate, nên có thể dùng nó để kiểm tra ứng viên nào khớp. [3]
Thuật toán vốn cần chọn khóa trong một tập rất lớn. Nếu quá trình tạo khóa chỉ chọn trong một góc nhỏ dễ dò, attacker không cần tìm cách giải bài toán tổng quát. Đây cũng là lý do không thể nhìn nhãn P-384 trên certificate rồi kết luận cách tạo khóa đã đúng.
Bình
Nguồn (14)
- Seth Michael Larson và các maintainer Python. Information for Python users regarding eMudhra / emSign CA certificate security incident. Python.org. 2026-10-20.
- Dennis Jackson và các cộng tác viên. eMudhra Intermediate CA Compromise. we-have-a-problem.com. 2026-10-20.
- Dennis Jackson, Wayne, eMudhra và các root program. eMudhra Private key compromise of Intermediate Certificates. Mozilla Bugzilla. 2026-10-18.
- eMudhra. eMudhra Statement on distrust of select Global TLS Intermediate and one Root CA. eMudhra. 2026-10-21.
- D. Cooper và cộng sự. Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile. IETF. 2008-05.
- Eric Rescorla. The Transport Layer Security Protocol Version 1.3, CertificateVerify. IETF. 2018-08.
- Heather Adkins. An update on attempted man-in-the-middle attacks. Google Security Blog. 2011-08-29.
- Johnathan Nightingale. Fraudulent *.google.com Certificate. Mozilla Security Blog. 2011-08-29.
- The OpenSSL Project. openssl-verification-options. OpenSSL.
- The pip developers. HTTPS Certificates. pip.
- Alex Gaynor. Removal of emSign root cerificate. certifi. 2026-10-20.
- William Woodruff. Removal of emSign root certificate. Astral. 2026-10-20.
- Astral. uv 0.13.5. GitHub. 2026-10-21.
- Hugo van Kemenade. Python 3.15.1, 3.14.9 and 3.13.17 are out. Python Insider. 2026-10-21.