Cách tìm AWS Account ID của một bucket S3 bất kỳ
(tracebit.com)- Tracebit tổng hợp kỹ thuật suy đoán AWS Account ID của bucket S3 công khai và riêng tư, và khôi phục
123456789101từ bucket ví dụbucket-alpha - Manh mối cốt lõi là điều kiện
s3:ResourceAccounttrong policy của Interface VPC Endpoint cho S3 và việc request có xuất hiện trong log CloudTrail của chính mình hay không - Với bucket riêng tư, dù phản hồi cuối cùng vẫn luôn là
AccessDenied, vẫn có thể xác định xem mẫu chữ số có khớp hay không vì chỉ những request vượt qua policy của VPC Endpoint mới xuất hiện trong CloudTrail - Do độ trễ lan truyền policy và độ trễ của CloudTrail, cách dò đơn giản có thể mất khoảng
40 * 12 phút = 8 giờ, nhưng có thể giảm xuống dưới 10 phút bằng cách kiểm tra song song 120 câu lệnh policy sử dụngaws:useridvàRoleSessionName - Kỹ thuật này khả thi vì
StringLikecho phép khớp một phần vớis3:ResourceAccount, và một số hoạt động cũng có thể xuất hiện trong CloudTrail của chủ sở hữu bucket
Mở rộng từ kỹ thuật dành cho bucket công khai
- Năm 2021, Ben Bridts đã công bố cách tìm AWS Account ID của một bucket S3 công khai
- Cách làm của Tracebit tái sử dụng nhiều thành phần của ý tưởng này, nhưng tập trung vào việc tìm Account ID của bucket S3, bao gồm cả bucket riêng tư
- Trong ví dụ thực thi, với
bucket-alpha, họ thu thập các tên phiên đã vượt qua trong CloudTrail và cuối cùng khôi phục được123456789101
Vì sao cách cũ cho bucket công khai hoạt động
- Phương pháp của Ben Bridts hoạt động khi hội đủ ba điều kiện
- Có thể áp dụng IAM policy cho request
- Có thể suy ra policy đã cho phép hay chặn request
- Có thể áp dụng khớp wildcard cho khóa điều kiện
s3:ResourceAccount
- Với bucket công khai, nếu policy chặn request thì sẽ nhận
AccessDenied, còn nếu policy cho phép thì request thành công, nên rất dễ phân biệt request có vượt qua policy hay không - Khi thu hẹp
s3:ResourceAccounttừng chữ số một, toàn bộ không gian tìm kiếm giảm từ hàng nghìn tỷ khả năng xuống chỉ còn vài trăm
Với bucket riêng tư, nhìn vào CloudTrail thay vì phản hồi
- Với bucket riêng tư, dù áp dụng policy nào thì phản hồi cuối cùng vẫn là AccessDenied do bucket policy của đích từ chối
- Cách làm của Tracebit không dựa vào kết quả phản hồi mà dựa vào việc request có xuất hiện trong log CloudTrail của chính mình hay không
- Nếu request xuất hiện trong CloudTrail, nghĩa là VPC Endpoint policy đã cho phép, sau đó mới bị bucket policy từ chối
- Nếu request không có trong CloudTrail, nghĩa là nó đã bị chặn ở VPC Endpoint policy
- Khi tạo Interface VPC Endpoint cho S3, có thể áp dụng VPC Endpoint policy cho request, và policy này sẽ được đánh giá cùng với các policy khác như bucket policy và IAM policy của chủ thể gửi request
- Trong VPC Endpoint policy cũng có thể dùng wildcard
StringLikevà các khóa điều kiện tài nguyên, nên có thể áp dụng cùng kiểu dò tìm như trên
Quy trình cơ bản: từ xác định region đến truy vấn sự kiện
- Trước tiên phải tìm region của bucket đích
- Gửi
curltới HTTP endpoint của bucket, ngay cả khi request bị cấm thì headerx-amz-bucket-regionvẫn được trả về - Trong ví dụ, họ xác nhận
us-east-1từ header phản hồi củabucket-alpha.s3.amazonaws.com
- Gửi
- Triển khai VPC và VPC Endpoint cho S3 trong cùng region với bucket đích
- VPC Endpoint phải là loại Interface thì mới áp dụng được policy
- Vì VPC Endpoint này sẽ ảnh hưởng đến các request S3 trong VPC, tốt nhất nên tạo một VPC riêng chỉ phục vụ mục đích này
- Chạy một EC2 instance trong VPC để gửi request S3, và xác nhận instance đó đang sử dụng VPC Endpoint cho S3
- Chỉnh sửa VPC Endpoint policy để kiểm tra xem
s3:ResourceAccountcó bắt đầu bằng một chữ số cụ thể hay không- Ví dụ, để kiểm tra Account ID có bắt đầu bằng
0hay không, đặt điều kiện"0*"chos3:ResourceAccount
- Ví dụ, để kiểm tra Account ID có bắt đầu bằng
- Từ EC2 instance, gửi một request quản trị như
GetBucketAcltới bucket đích- Dùng request quản trị sẽ bớt cần xử lý riêng trong cấu hình CloudTrail
- Kết quả request đúng như dự đoán vẫn là
AccessDenied
Cách phân biệt mẫu chữ số bằng CloudTrail
- Sau request, truy vấn CloudTrail xem có xuất hiện sự kiện
GetBucketAclhay không - Nếu sự kiện xuất hiện, nghĩa là VPC Endpoint policy đã cho phép request, nên Account ID khớp với mẫu đang kiểm tra
- Ví dụ: nếu có sự kiện khi dùng điều kiện
"0*", thì Account ID bắt đầu bằng0
- Ví dụ: nếu có sự kiện khi dùng điều kiện
- Nếu sự kiện không xuất hiện, nghĩa là request đã bị chặn ở VPC Endpoint policy, nên không khớp mẫu đó
- Vì có thể mất vài phút để sự kiện xuất hiện trong CloudTrail, nên họ khuyến nghị chờ 10 phút trước khi kết luận là không có sự kiện
- Việc thay đổi VPC Endpoint policy cũng cần thời gian để lan truyền và có hiệu lực hoàn toàn; chờ 5 phút sau khi sửa policy cho kết quả tốt
Đã tự động hóa nhưng cách cơ bản vẫn chậm
- Tracebit đã viết script tự động hóa quy trình này để có thể tìm Account ID của bucket một cách ổn định
- Thay vì kiểm tra mọi chữ số theo cách tuần tự từng vị trí, họ giảm số lần thử bằng cách dùng cách tiếp cận gần với tìm kiếm nhị phân ở mỗi vị trí
- Ví dụ, đưa nhiều mẫu vào điều kiện
s3:ResourceAccountnhư["0*", "1*", "2*", "3*", "4*"]để chia nhỏ phạm vi
- Ví dụ, đưa nhiều mẫu vào điều kiện
- Dù vậy, thời gian chờ policy được áp dụng và thời gian chờ xác nhận trong CloudTrail vẫn là nút thắt
- Ngay cả khi dùng tìm kiếm nhị phân, vẫn có thể mất khoảng
40 * 12 phút = 8 giờ
- Ngay cả khi dùng tìm kiếm nhị phân, vẫn có thể mất khoảng
- Trong ví dụ chạy suốt nhiều giờ, họ đã tìm thành công Account ID của
bucket-alphalà123456789101
Rút xuống dưới 10 phút bằng 120 câu lệnh policy
- Cách nhanh hơn là điền trước vào VPC Endpoint policy tất cả các tổ hợp vị trí và chữ số có thể có
- Policy này chứa tổng cộng 120 câu lệnh
- Kiểm tra 10 chữ số có thể có cho từng vị trí trong AWS Account ID
- Mỗi câu lệnh kết hợp mẫu theo vị trí cụ thể của
s3:ResourceAccountvới điều kiệnaws:userid
- Điều kiện
aws:useridđược dùng để khớp với giá trịRoleSessionNamecó thể chỉ định tự do trong lệnh gọi STSAssumeRole- Khi assume role với một
RoleSessionNamecụ thể, có thể chọn để chỉ cho phép câu lệnh policy tương ứng với phép thử cho một vị trí và chữ số nhất định đi qua
- Khi assume role với một
- Policy này vừa khít giới hạn độ dài ký tự tối đa của VPC Endpoint policy
- Vì kiểm tra song song toàn bộ 120 khả năng, không còn cần sửa policy liên tục hay chờ riêng kết quả CloudTrail cho từng trường hợp
- Nhờ đó, thời gian dò Account ID giảm xuống dưới 10 phút
Phạm vi lộ diện và khả năng mở rộng
- Một phần hoạt động có thể xuất hiện trong log CloudTrail của chủ sở hữu bucket đích
- Tracebit đã trao đổi với đội ngũ AWS Security trước khi công bố
- Việc AWS Account ID có phải thông tin nhạy cảm hay không vốn đã được bàn luận nhiều, và trong sự kiện CloudTrail ví dụ, Account ID của bên thứ ba được che bằng
HIDDEN_DUE_TO_SECURITY_REASONS - Cùng kỹ thuật này cũng có thể áp dụng cho các khóa điều kiện tài nguyên khác liên quan đến bucket
- Ví dụ:
aws:ResourceOrgID - Ví dụ:
aws:ResourceOrgPaths - Ví dụ:
aws:ResourceTag
- Ví dụ:
- Kỹ thuật này cũng có thể được áp dụng sang các dịch vụ khác ngoài S3 nếu có điều kiện tương tự
- Nếu tạo VPC và VPC Endpoint được peering lẫn nhau trên mọi region, có thể xây dựng một cấu hình hoạt động bất kể bucket đích nằm ở region nào
- Kỹ thuật này khả thi vì có thể dùng khớp một phần bằng StringLike với điều kiện
s3:ResourceAccount - Sẽ hữu ích nếu cả những sự kiện bị VPC Endpoint policy từ chối cũng được ghi vào CloudTrail
1 bình luận
Ý kiến trên Hacker News
Việc có thể áp dụng khớp ký tự đại diện cho khóa điều kiện s3:ResourceAccount thật sự kỳ lạ
Có vẻ không có lý do chính đáng nào để cho phép hoặc từ chối quyền dựa trên việc khớp một phần ID tài khoản
StringLikecho chuỗi ID tài khoảnKhá thú vị khi thấy phía DevOps giờ cũng bắt đầu phát hiện các tấn công kênh kề. Các kênh kề từ thực thi suy đoán của CPU như Meltdown, Spectre khi được phát hiện cũng đã gây chấn động lớn; trước đó còn có các lĩnh vực như phân tích điện năng, phát hiện biến dạng từ và mật mã học thời gian hằng
https://en.m.wikipedia.org/wiki/Side-channel_attack
https://en.m.wikipedia.org/wiki/Power_analysis
Trong một dự án phụ gần đây, tôi đã làm chức năng viết truy vấn theo dạng lấy cảm hứng từ OWL, có một thư viện toán tử quan hệ để trích host từ URL, truy vấn tiền tố, truy vấn
like, truy vấn biểu thức chính quy, v.v.Vì đó là dự án phụ của một dự án phụ khác của tôi nên tôi làm theo cách dễ nhất, và để các toán tử luôn có thể dùng được ngay cả khi trường hợp đó không hợp lý. Tôi cũng không biết và không quan tâm nếu truy vấn biểu thức chính quy trên số thì sẽ ra sao. Có thể nội bộ AWS cũng có thứ tương tự, nhưng với một hệ thống có nhiều người dùng và nhạy cảm về bảo mật thì tiêu chuẩn phải khác
Ai đó có thể nghĩ ra ý tưởng này và thấy mình thông minh, nhưng triển khai nó trong một hệ thống mà bạn không kiểm soát 100% thì có vẻ là điều ngớ ngẩn
Thông thường sẽ không công khai rải ID tài khoản, nhưng nên giả định rằng một phần nào đó rồi cũng sẽ bị lộ vào một lúc nào đó
Ngày càng nhiều nhà cung cấp bên thứ ba và nền tảng SaaS đang chuyển sang các kiểu tích hợp ưu tiên ủy quyền vai trò thay vì IAM user và access key, và đúng là nên như vậy. Khi đó, ít nhất ID tài khoản của tài khoản dùng làm điểm tích hợp sẽ được bên khác biết, mà phía đó cũng có phụ thuộc, lỗ hổng, v.v.
AWS account ID giống như địa chỉ IP. Nó có thể nhạy cảm, nhưng để làm việc thì phải có ai đó biết
Ví dụ 1–2 năm trước, vì quy trình chống rửa tiền, chúng tôi phải tích hợp với một bên thứ ba. Tôi đề xuất thiết lập PrivateLink với tổ chức đó vì thường an toàn hơn cổng SFTP công khai, nhưng công ty bên kia từ chối vì lý do bảo mật rằng họ phải giấu account ID. Dù account ID là thứ cần thiết trong role ARN của PV endpoint để cấp quyền qua lại
Cuối cùng chúng tôi đưa dải IP công khai mà họ dùng cho cổng inbound 22 vào danh sách cho phép
Bài học là bạn có thể nghĩ mình thông minh khi làm rối ID, nhưng nếu bên kia không biết địa chỉ để liên lạc lại thì rất khó vận hành kinh doanh
Từ phía nhà cung cấp, chúng tôi thường tích hợp bằng VPC Endpoint Service. Cách này giao tiếp một chiều, và dịch vụ của chúng tôi được phơi ra dưới dạng endpoint load balancer trong VPC của khách hàng
Với những ai quan tâm, tôi đã đưa mã lên đây: https://github.com/tracebit-com/find-s3-account
Đúng là một phát hiện thú vị, nhưng nhìn tiêu đề thì tôi tưởng sẽ có một cách trực tiếp hơn
Sẽ rất hay nếu trong AWS, với tài khoản quản trị, ta có thể đơn giản hỏi trong tổ chức rằng “tài nguyên X nằm ở đâu” và nhanh chóng biết một S3 bucket cụ thể nằm trong tài khoản nào. Các tài nguyên khác cũng vậy, nhưng S3 bucket là vấn đề đặc biệt lớn
Nói thật thì đây chủ yếu là vấn đề với các bucket legacy có từ trước khi có thực hành tốt hơn, hoặc những thứ tồn tại từ trước khi toàn bộ bucket được định nghĩa bằng code. Dù vậy, nếu có nhiều AWS account, việc tìm tài nguyên nằm trong tài khoản và region không rõ có thể rất tẻ nhạt
Khi đó, việc tìm tài khoản nào sở hữu tài nguyên đại khái có thể làm bằng
select accountId where arn = "x"Các tài nguyên AWS công khai khác có namespace toàn cục cũng làm lộ AWS account ID
https://blog.plerion.com/conditional-love-for-aws-metadata-e...
Liên quan một chút, Cloudflare account_id và zone_id có công khai cũng an toàn
https://github.com/cloudflare/cloudflare-docs/issues/474
https://community.cloudflare.com/t/api-zone-id/355566
Tuy nhiên, một trong những điều có thể làm với nó là xác định mối tương quan. Nếu vận hành nhiều site S3 trên cùng một tài khoản AWS, người ta có thể thấy chúng được host từ cùng một tài khoản. Việc này có quan trọng hay không tùy thuộc vào threat model
Không hoàn hảo, nhưng nó thêm một lớp trừu tượng nữa
Liên quan, AWS key ID dù không phải phần secret key cũng chứa account ID bên trong ở dạng bị dịch một bit
https://medium.com/@TalBeerySec/a-short-note-on-aws-key-id-f...
Key ID này được đưa vào URL được ký sẵn của S3, nên nhiều khả năng bạn vốn đã công khai account ID rồi
Có lẽ sẽ bị downvote, nhưng nếu vẫn đọc thì đây là một ví dụ cho thấy vì sao bảo mật nhờ che giấu không phải là biện pháp phòng thủ tốt. Bản thân mình sẽ bỏ sót thứ gì đó, còn kẻ tấn công kiên trì thì sẽ không bỏ sót
Bảo mật không dựa vào che giấu vẫn có hiệu lực bất kể tôi có hiểu điều gì đó hay không, trừ khi kẻ tấn công thuê được một thiên tài có thể phá AES-256 chẳng hạn: https://www.youtube.com/watch?v=KEkrWRHCDQU
Vì sao chuyện này có thể quan trọng? Một ví dụ rõ ràng là, nếu có một bucket production, giờ bạn có thể tìm được các bucket development của cùng tổ chức. Cá nhân tôi thì đây không phải hành vi tôi dự đoán trước
Muốn ngăn kiểu thử liệt kê này, nên thêm tiền tố hoặc hậu tố được tạo ngẫu nhiên vào tên bucket. Ngoài ra, không phải để thay thế mà như biện pháp bổ sung, cũng nên công khai object trong bucket dưới một tên không phải hostname mặc định để bản thân tên bucket không bị lộ
Ví dụ địa chỉ nhà về mặt kỹ thuật là thông tin công khai, nhưng tôi tuyệt đối không muốn nó xuất hiện trên một billboard cạnh đường cao tốc kèm ảnh gia đình với dòng chữ đây là nơi tôi sống. Tôi chỉ đưa cho người cần biết, và tin cũng như kỳ vọng rằng nhìn chung nó sẽ được giữ gần như bí mật hoặc có giới hạn mục đích sử dụng
Nếu không phải bí mật, không nhạy cảm, cũng không phải thông tin mật, thì vì sao phải chia sẻ cẩn thận?
Người dùng có thể nhìn nhận khác