ghrc.io bị nghi là một trang web độc hại
(bmitch.net)- Sự nhầm lẫn đơn thuần giữa ghcr.io và ghrc.io do gõ sai đã gây ra mối đe dọa bảo mật nghiêm trọng
- ghrc.io thoạt nhìn trông như một máy chủ nginx mặc định, nhưng bên trong lại bị phát hiện bắt chước OCI API
- Trang này dùng header
www-authenticateđể khiến các container client gửi thông tin xác thực nhạy cảm - Nếu vô tình nhập thông tin đăng nhập như
docker loginhoặc sử dụng sai registry, có thể dẫn đến rò rỉ thông tin xác thực - Nếu đã đăng nhập vào máy chủ sai, cần đổi mật khẩu, thu hồi PAT và kiểm tra hoạt động bất thường trên tài khoản GitHub
Tổng quan
Sự nhầm lẫn thường gặp do gõ sai giữa ghcr.io và ghrc.io có thể dẫn đến một vấn đề bảo mật rất nguy hiểm. Tại ghrc.io, phiên bản gõ sai của GitHub Container Registry (ghcr.io) được nhiều nhà phát triển và nhóm sử dụng, đã phát hiện nỗ lực đánh cắp thông tin xác thực.
ghcr.io là gì
- ghcr.io là một registry tương thích OCI dành cho container image và OCI artifact
- Đây là một phần của GitHub và được dùng rộng rãi như một registry phổ biến trong nhiều dự án mã nguồn mở
ghrc.io: bề ngoài trông như thế nào
- Khi truy cập ghrc.io, chỉ thấy màn hình mặc định của nginx
- Các hành vi cơ bản như lỗi 404 điển hình cũng giống một máy chủ nginx thông thường
Bản chất của hành vi độc hại
- Vấn đề cốt lõi xuất hiện khi có gọi OCI API dưới tiền tố
/v2/ - Khi truy cập đường dẫn này, nó trả về header
www-authenticatevà phản hồi 401 với hành vi rất giống một container registry chính thức - Có tồn tại header
www-authenticate: Bearer realm="https://ghrc.io/token" - Vì header này, các client như Docker, containerd, podman, Kubernetes sẽ tự động thử gửi thông tin xác thực của người dùng tới
https://ghrc.io/token - Cấu hình nginx mặc định không có header đó, nên đây là thiết lập rõ ràng có chủ đích
Mức độ nguy hiểm: kịch bản đánh cắp thông tin xác thực
- Mẫu này được đánh giá là một cuộc tấn công đánh cắp thông tin xác thực dựa trên typo-squatting
- Rủi ro chỉ xảy ra khi client của người dùng đã nhập hoặc lưu thông tin xác thực cho ghrc.io
- Ví dụ về các tình huống thông tin xác thực thực sự có thể bị lộ
- Chạy
docker login ghrc.io - Dùng
docker/login-actiontrong GitHub Action và chỉ định registry là ghrc.io - Lưu thông tin xác thực registry cho ghrc.io trong Kubernetes secret rồi thử kéo image
- Chạy
- Chỉ đơn thuần thử push/pull image lên ghrc.io thì thông tin xác thực sẽ không bị lộ (sau khi thử token ẩn danh sẽ trả về lỗi)
Cách ứng phó
- Nếu từng vô tình đăng nhập vào ghrc.io, cần ngay lập tức đổi mật khẩu và thu hồi PAT (personal access token) đã sử dụng
- Bắt buộc phải kiểm tra đăng nhập bất thường hoặc hoạt động độc hại trên tài khoản GitHub
- Kẻ tấn công có thể lợi dụng điều này để thêm image độc hại vào repository trên ghcr.io hoặc chiếm quyền truy cập tài khoản
Kết luận
- Cần cảnh giác với trang phishing dùng địa chỉ tương tự ghcr.io
- Cần áp dụng chính sách nghiêm ngặt hơn trong việc quản lý thông tin bảo mật như thông tin xác thực, token và mật khẩu
2 bình luận
Có lẽ cứ đổi sang subdomain của github.com thì sẽ tốt hơn chăng.
Ý kiến trên Hacker News
Nhấn mạnh đây là vấn đề nghiêm trọng vì GitHub Container registry chỉ hỗ trợ token classic cũ thay vì token phân quyền chi tiết
Đồng thời đính kèm liên kết đến tài liệu liên quan và issue
Tài liệu chính thức
Thảo luận cộng đồng
Issue trên roadmap
Vì vấn đề này nên hiện không thể tắt hoàn toàn classic PAT
Một biện pháp bổ sung là đặt thời hạn phiên ngắn và buộc xác thực lại bằng enterprise SSO, nhưng đó là lựa chọn phiền toái cho trường hợp thực tế chỉ cần một classic PAT duy nhất
Sẽ tốt nếu ai đó mua hết các typo domain với thiện ý rồi bàn giao cho Microsoft
Tôi nghĩ Microsoft nên đổi tên registry
Cái tên này quá dễ gây nhầm lẫn, bản thân tôi cũng đã nhiều lần gõ sai
Đây là một vector tấn công khá thuyết phục đến mức tôi phải đọc đi đọc lại vấn đề về domain vài lần mới hiểu ra
Đã thử đi thử lại nhiều lần nhưng vẫn thất bại, thậm chí khởi động lại máy tính cũng gặp đúng vấn đề đó
Ví dụ tham khảo còn có câu trả lời trên Stack Overflow và thảo luận trên diễn đàn Docker
Đưa ra liên kết kết quả tìm kiếm mã nguồn liên quan đến ghrc.io
Tôi đã không nhận ra vấn đề cho đến khi bài viết trực tiếp chỉ ra rằng c và r đã bị đảo vị trí
Đây đúng là kiểu lỗi gõ sai mà tôi mắc gần như hơn 10 lần mỗi ngày
Vấn đề ở đây là tên domain của GitHub quá tệ
Tên của container registry thực sự rất dở
Chia sẻ liên kết đến thảo luận Hacker News trước đó
Có thể xác nhận qua whois rằng domain này được đăng ký tại dynadot
Vì vậy có vẻ đáng để báo cáo tới abuse@dynadot.com
Nhắc đến việc nhiều dự án mã nguồn mở đang sử dụng domain này, đồng thời một lần nữa chia sẻ kết quả tìm kiếm mã nguồn
GitHub cần một công cụ nội bộ có thể đề xuất và triển khai sửa tự động trên diện rộng
Cũng nhắc rằng kết quả tìm kiếm mã nguồn trên GitHub thực sự có quy mô khá lớn
Bày tỏ lo ngại rằng một lỗi gõ sai trong tác vụ CI có thể gây ra vấn đề nghiêm trọng
Khuyên nên tránh dùng các TLD có giá trị bảo mật thấp nếu có thể
Bảo mật phải được ưu tiên hơn việc trông cho dễ thương
Việc gỡ đăng ký domain độc hại có thể không nhanh như với .com, nên tôi thấy .com do Verisign của Mỹ quản lý đáng tin cậy hơn
Việc phụ thuộc vào Lãnh thổ Ấn Độ Dương thuộc Anh, Colombia hay Anguilla là không phù hợp
Đặt câu hỏi liệu rủi ro thực sự ở đây có phải là vấn đề tái sử dụng token hay không
Bearer token không trực tiếp đưa mật khẩu, và khi trích dẫn RFC cùng tài liệu của Mozilla, người này thắc mắc liệu vấn đề thực ra không nằm ở chính token xác thực mà ở quy trình nhận lại token để xác thực hay sao
Nếu OAuth giữa các domain không tái sử dụng token, thì chẳng phải domain giả cuối cùng cũng sẽ không thể nhận được token hay sao?
Trong yêu cầu để lấy Bearer token, mật khẩu hoặc PAT được gửi trong header Basic Auth dưới dạng mã hóa base64, nhưng trên thực tế vẫn được truyền gần như ở dạng văn bản thuần
Khi nhận yêu cầu, header
www-authenticatesẽ được tạo ra, token xác thực được cấp để kiểm tra quyền truy cập registry, và sau đó token này sẽ hết hạnCấu trúc tấn công ở đây không phải là kẻ tấn công đánh cắp token thực sự, mà là khiến nạn nhân gửi chính thông tin xác thực dùng để lấy Bearer token