Hacker News: AI bài nổi bật
92

Thủ thuật

Đội ngũ Strix chiếm quyền admin GitHub của Baseten chỉ trong 25 phút

(giờ Việt Nam)

Tóm tắt AI

Trong quá trình đánh giá dịch vụ, nhóm Strix đã phát hiện một GitHub Personal Access Token bị lộ trong lịch sử Docker build trên registry công khai của Baseten, cho phép truy cập trái phép vào hệ thống.

Bản dịch AI

We wanted to use Baseten for inference. We ended up with admin access to Baseten GitHub repos

Chúng tôi đã chuẩn bị tin tưởng giao dữ liệu của mình và khách hàng cho Baseten. Vì vậy, để đảm bảo an toàn, trước tiên chúng tôi đã chạy Strix để kiểm tra mức độ bảo mật của họ. Khoảng 25 phút sau, nó đã tìm thấy một GitHub token đang hoạt động với quyền quản trị cấp kho lưu trữ (repository-level) trên các kho lưu trữ nội bộ của Baseten.

Chúng tôi xây dựng Strix, một tác nhân hack tự động, điều này đồng nghĩa với việc chúng tôi cần khả năng suy luận (nhanh và rẻ). Chúng tôi đã cân nhắc các lựa chọn của mình và Baseten là một trong những cái tên hiển nhiên. Đó là một sản phẩm tuyệt vời, họ được định giá 13 tỷ USD và rất nhiều công ty lớn đang phụ thuộc vào họ.

Nhưng... chúng tôi là một công ty bảo mật. Trước khi cung cấp dữ liệu, mô hình hoặc mã nguồn cho bên thứ ba, chúng tôi đều quét qua họ. Chúng tôi thà tìm ra vấn đề và giúp khắc phục nó trước khi bắt đầu phụ thuộc vào dịch vụ đó (chúng tôi thực hiện điều này với hầu hết các nhà cung cấp của mình và có tỷ lệ phát hiện các vấn đề nghiêm trọng rất cao).

Vì vậy... chúng tôi đã hướng Strix vào *.baseten.co và để nó tự chạy mà không cần thông tin đăng nhập hay mã nguồn.

Nó đã trả về một GitHub personal access token đang hoạt động của basetenbot. Token đó có quyền quản trị và quyền đẩy (push) mã nguồn vào kho lưu trữ sản phẩm chính của Baseten, kho lưu trữ GitOps điều khiển các cụm (cluster) của họ, và Homebrew tap của họ, cộng với quyền đọc/ghi vào các kho lưu trữ riêng tư khác, bao gồm cả các kho lưu trữ cụ thể cho từng khách hàng.

Bản dựng hình ảnh (image build) có từ tháng 3 năm 2023, và token vẫn hoạt động khi chúng tôi tìm thấy nó vào tháng 7 năm 2026.

Nhưng trước khi đi vào chi tiết, hãy dành lời khen ngợi cho đội ngũ bảo mật của Baseten. Họ đã xác nhận vấn đề là nghiêm trọng, khóa dự án registry và thu hồi token vào chiều hôm sau. Họ làm việc rất chuyên nghiệp và xử lý vấn đề cực kỳ nhanh chóng (điều hiếm thấy trong những tình huống như thế này).

Strix đã tìm thấy nó như thế nào

Strix bắt đầu theo cách mà bất kỳ đợt kiểm thử xâm nhập (pentest) tốt nào cũng làm: trinh sát (recon). Nhiều khi lỗ hổng nghiêm trọng nhất trong cơ sở hạ tầng của bạn lại nằm trên một dịch vụ ở tên miền phụ mà bạn đã quên mất (đó là lý do tại sao chúng tôi luôn khuyến nghị kiểm thử hộp đen song song với kiểm thử có quyền truy cập mã nguồn)! Vì vậy, Strix đã liệt kê các máy chủ, xem qua nhật ký chứng chỉ và lập bản đồ toàn bộ bề mặt tấn công. Cuối cùng, nó tìm thấy một Harbor registry tại gcp-us-east4-zlw.registry.baseten.co.

Harbor lưu trữ các container image và nhóm các kho lưu trữ thành các dự án. Một trong những dự án này là công khai. Không cần token hay xác thực, Strix có thể liệt kê các kho lưu trữ, lấy các token kéo (pull) ẩn danh và tải xuống các tệp manifest và blob thực tế của hình ảnh. Trong đó bao gồm một hình ảnh có tên là baseten/baseten-app.

Đến đây, việc báo cáo một registry bị lộ rồi bỏ qua sẽ rất dễ dàng. Nhưng các công ty thường cố tình xuất bản hình ảnh, và Strix không bao giờ muốn báo cáo nhầm (false positive). Câu hỏi quan trọng là tác động của việc các hình ảnh này bị lộ là gì.

Strix quyết định kéo một hình ảnh về và xem bên trong có gì. Đây là phần chạy đó như hiển thị trong Strix (vâng, cách viết của chính tác nhân này nghe giống AI, vì những lý do hiển nhiên):

Đánh giá tác động của việc lộ Harbor

Suy nghĩ

Nếu các dự án Harbor đó không được công khai, thì đây là một sự cố lộ lọt thực sự, không phải là nhiễu siêu dữ liệu. Chuỗi hành động mới là điều quan trọng: liệt kê các dự án công khai, đọc siêu dữ liệu của artifact, tạo một dịch vụ/token ẩn danh với phạm vi repository:baseten/baseten-app:pull, kéo manifest, sau đó lấy blob thông qua một liên kết lưu trữ được ký. Điều đó chứng minh quyền truy cập kéo ẩn danh là có thật. Cách để bộ phận xử lý sự cố coi trọng vấn đề này là chứng minh một thứ từ hình ảnh đã kéo về: mã nguồn độc quyền, tệp nhị phân nội bộ, thông tin đăng nhập được mã hóa cứng (hardcoded) hoặc tên máy chủ nội bộ.

Kết quả hứa hẹn đầu tiên là một cặp khóa AWS trong baseten/baseten-app. Strix đã thử một lệnh gọi chỉ đọc sts:GetCallerIdentity, lệnh này cho biết thông tin xác thực thuộc về tài khoản nào. Phản hồi trả về là InvalidClientTokenId.

Khóa đó đã chết, vì vậy Strix tiếp tục tìm kiếm.

Sau đó, một token thực sự hoạt động

Nó đã kéo các lớp (layer), chạy TruffleHog (gửi lời cảm ơn đến những người bạn bảo mật mã nguồn mở của chúng tôi!), và kiểm tra trực tiếp cấu hình hình ảnh. Và nó ở đó: một GitHub personal access token cổ điển, nằm trong history[].created_by.

Tôi không phải là chuyên gia về Docker runtime, nhưng may mắn thay Strix thì có (nhờ việc nó có quyền truy cập vào hầu hết kiến thức của nhân loại). Vì vậy, nó biết rằng trường đó ghi lại cách một bước xây dựng được tạo ra. Trong trường hợp này, nó chứa một lệnh RUN với giá trị của GITHUB_TOKEN được mở rộng trực tiếp vào đó.

Strix đã sử dụng token đó cho một yêu cầu GET /user chỉ đọc tới GitHub và… VOILÀ. Mã 200, với tên tài khoản là basetenbot.

Hãy chú ý nơi tìm thấy token. Như tôi đã học được, một Docker image có các lớp hệ thống tệp, nhưng nó cũng có một cấu hình chứa thông tin về hình ảnh và lịch sử xây dựng của nó. Cấu hình đó có thể tải xuống cùng với hình ảnh. Việc xóa tệp chứa thông tin xác thực không có tác dụng nếu lịch sử xây dựng vẫn chứa một bản sao khác của token.

Và cái này vẫn hoạt động sau hơn ba năm.

Được rồi, basetenbot có thể làm gì?

Một token đang hoạt động rất thú vị, nhưng rõ ràng quyền hạn mới là điều quan trọng. Token này có thể có 0 quyền và do đó có 0 tác động. Vì vậy, Strix đã kiểm tra tài khoản và tư cách thành viên tổ chức của nó. GitHub trả về X-OAuth-Scopes: repo, và tài khoản thuộc về basetenlabs.

Sau đó, nó kiểm tra quyền truy cập kho lưu trữ cá nhân, một lần nữa sử dụng các yêu cầu chỉ đọc:

Đây là một lượng quyền truy cập điên rồ bị để lại trong một hình ảnh có thể tải xuống công khai.

basetenlabs/b*** là sản phẩm chính. Ai đó sở hữu token này có quyền quản trị và quyền đẩy mã nguồn vào kho lưu trữ mã nguồn chính của một nền tảng suy luận. Họ có thể can thiệp vào mã nguồn mà các công ty khác dựa vào để chạy mô hình của họ. Chúng tôi đã cân nhắc việc gửi mã nguồn và mô hình của chính mình cho công ty này, đó chính là lý do tại sao chúng tôi thực hiện các kiểm tra này ngay từ đầu.

basetenlabs/f*** có lẽ còn đáng sợ hơn. Đó là GitOps của họ: kho lưu trữ chứa trạng thái mong muốn của các cụm, và nó áp dụng trạng thái đó vào cơ sở hạ tầng. Quyền quản trị ở đây tạo ra một con đường từ một token xây dựng bị rò rỉ đến các thay đổi trong cơ sở hạ tầng sản xuất.

basetenlabs/h*** là cách CLI của họ được cài đặt trên máy của nhà phát triển. Việc can thiệp vào kênh phân phối này có thể biến nó thành một cuộc tấn công chuỗi cung ứng nhắm vào những người cài đặt công cụ của Baseten.

Và sau đó là basetenlabs/f***. Danh sách của kho lưu trữ riêng tư đó cho thấy một thư mục cấp cao nhất là customers/, với các thư mục con được đặt tên theo khách hàng của Baseten.

Đến thời điểm đó, chúng tôi đã có đủ bằng chứng để báo cáo và tự tin rằng đây không phải là báo cáo nhầm. Chúng tôi đã không sao chép kho lưu trữ của khách hàng, không đẩy bất cứ thứ gì, cũng không thay đổi bất kỳ cấu hình nào. Chúng tôi dừng lại ở đó và viết email thông báo ngay lập tức.

Làm thế nào một token lại nằm ở đó?

Lịch sử xây dựng có gắn dấu thời gian. Bước chứa token đã chạy vào ngày 3 tháng 3 năm 2023. Đây là một thông tin xác thực xây dựng cũ vẫn còn tất cả các quyền truy cập đó khi chúng tôi kiểm tra vào tháng 7 năm 2026.

Sai lầm cơ bản khá quen thuộc. Một bản dựng cần lấy các phụ thuộc riêng tư từ GitHub, vì vậy ai đó đã truyền một token vào dưới dạng đối số xây dựng (build argument). Mô hình liên quan trông như thế này:

Tôi có thể hiểu tại sao ai đó lại viết như vậy. Bạn cần một phụ thuộc riêng tư, bạn truyền token vào, Git xác thực và bản dựng hoạt động. Nhưng Docker có thể ghi lại đối số xây dựng đó vào siêu dữ liệu và lịch sử của hình ảnh. Trong trường hợp này, nó đã ghi lại giá trị token thực tế. Docker đã cảnh báo rõ ràng về điều này.

Ngoài ra còn có vấn đề thứ hai với mô hình này: git config --global ghi URL đã xác thực vào tệp cấu hình của Git. Ngay cả khi bạn thay đổi cách token được đưa vào bản dựng, bạn vẫn cần tránh lưu nó vào hình ảnh.

Cách khắc phục là sử dụng BuildKit secret mount và xác thực tạm thời không lưu trữ thông tin xác thực. Sau đó kiểm tra cả các lớp của hình ảnh và lịch sử của nó. Và thu hồi token cũ! Việc thay đổi Dockerfile không có tác dụng gì đối với một hình ảnh mà ai đó đã tải xuống.

Những gì Strix đã tự thực hiện

Đọc bài gốc

Bài viết được AI dịch và tổng hợp tự động từ Hacker News: AI bài nổi bật. Liên kết bài gốc ở phía trên. AIHOT.vn luôn dẫn nguồn đầy đủ — nếu bạn thấy điểm cần chỉnh sửa, hãy gửi ý kiến tại trang phản hồi.