2 điểm bởi GN⁺ 2024-09-20 | 1 bình luận | Chia sẻ qua WhatsApp
  • Sự kết hợp giữa Boosts của trình duyệt Arc và vấn đề trong quy tắc Firestore đã cho phép kẻ tấn công liên kết một Boost chứa JavaScript tùy ý với tài khoản nạn nhân
  • Việc sử dụng Firebase Authentication và Firestore được xác nhận bằng hooking Frida, qua đó lộ ra luồng truy cập các collection preferences, users, user_referrals, boosts
  • Lỗ hổng phát sinh từ việc Boost xác định đối tượng áp dụng bằng creatorID, trong khi kẻ tấn công lại có thể đổi creatorID trong tài liệu Boost của mình thành ID của người dùng khác
  • ID của nạn nhân có thể lấy từ user_referrals, boostSnapshots của Boost công khai, Easels được chia sẻ, v.v.; khi nạn nhân truy cập website mục tiêu, Boost độc hại có thể được thực thi
  • The Browser Company đã vá lỗi và trả thưởng $2.000, đồng thời sau khi CVE-2024-45489 được gán, họ quyết định thu hẹp việc dùng Firebase, kiểm toán bảo mật và triển khai chương trình bug bounty

Tính năng đám mây của Arc và việc sử dụng Firestore

  • Arc yêu cầu tài khoản để sử dụng, và quá trình đăng ký được xác nhận là dùng Firebase Authentication
  • Quan sát mạng ban đầu không thấy yêu cầu nào khác, nhưng khi xem xét tính năng chia sẻ Easels, khả năng sử dụng Firestore đã lộ ra
  • Easels là giao diện dạng bảng trắng, có thể xem trên web khi chia sẻ với người khác
  • Firestore là dịch vụ database-as-a-backend, cho phép xây dựng tính năng bằng quy tắc bảo mật cơ sở dữ liệu và truy cập trực tiếp từ client mà không cần backend riêng
  • Một ví dụ trước đây về quy tắc bảo mật Firestore yếu kém là Firewreck

Cách xác nhận các lời gọi Firebase

  • Do Firebase Swift SDK có xu hướng không tuân theo thiết lập proxy hệ thống, tác giả đã dump các lời gọi liên quan bằng script Frida thay vì mitmproxy
  • Script hook các lời gọi Firestore của các lớp Objective-C
    • FIRCollectionReference["- documentWithPath:"]
    • FIRQuery["- queryWhereField:isEqualTo:"]
    • FIRFirestore["- collectionWithPath:"]
    • Các phương thức thực thi như getDocuments, addSnapshotListener:, getDocument
    • Các phương thức ghi tài liệu thuộc nhóm updateData, setData
  • Khi Arc chạy, các loại đường dẫn và truy vấn Firestore sau được quan sát
    • preferences/{userID}
    • preferences/{userID}/stringValues/...
    • users/{userID}
    • Truy vấn inviter_id == {userID} trong user_referrals
    • Truy vấn creatorID == {userID} trong boosts
  • Từ cấu trúc này, Arc đang lưu một số thiết lập môi trường, đối tượng người dùng cơ bản, thông tin giới thiệu và Boosts trên Firestore

Vì sao Boosts trở thành đường tấn công

  • Arc Boosts là tính năng cho phép người dùng tùy biến website
    • Chặn phần tử
    • Thay đổi phông chữ
    • Thay đổi màu sắc
    • CSS tùy chỉnh
    • JavaScript tùy chỉnh
  • Boosts được lưu trong Firestore, và trình duyệt Arc truy vấn trường creatorID để quyết định sẽ áp dụng Boost nào
  • Kẻ tấn công tạo một Boost cho Google.com từ tài khoản của mình, rồi thử thay đổi một số tham số trong tài liệu Firestore
  • Do truy vấn dựa trên creatorID, không thể trực tiếp truy vấn Boost của người dùng khác, nhưng lại có thể thay đổi creatorID trong tài liệu Boost của chính mình thành ID người dùng của tài khoản khác
  • Kết quả thử nghiệm với một tài khoản khác cho thấy khi máy tính nạn nhân truy cập Google.com, Boost do kẻ tấn công tạo được áp dụng

Chuỗi tấn công và cách lấy ID người dùng

  • Luồng tấn công cuối cùng như sau
    • Lấy ID người dùng của nạn nhân
    • Tạo Boost độc hại chứa payload mong muốn từ tài khoản của kẻ tấn công
    • Thay đổi trường creatorID của tài liệu Boost thành ID của nạn nhân
    • Khi nạn nhân truy cập website mục tiêu, Boost độc hại được thực thi
  • Lỗ hổng này tồn tại vì Arc Boosts có thể chứa JavaScript tùy ý, được lưu trong Firestore, và đối tượng áp dụng được quyết định bằng trường creatorID
  • Có nhiều cách để lấy ID người dùng của nạn nhân
    • user_referrals: nếu mời ai đó dùng Arc hoặc được ai đó giới thiệu, có thể lấy ID người dùng của đối phương trong bảng user_referrals
    • Boosts công khai: Boost không có JavaScript có thể chia sẻ, và boostSnapshots trên website Arc Boosts công khai chứa ID người dùng của người tạo
    • Easels: cũng có thể lấy ID người dùng thông qua tính năng bảng trắng có thể chia sẻ

Bản vá và lịch trình công bố

  • The Browser Company thường không có bug bounty, nhưng đã trả $2.000 USD cho lỗ hổng này
  • Dòng thời gian của lỗ hổng như sau
    • 25/8 5:48pm: Liên hệ lần đầu với đồng sáng lập Arc Hursh qua Signal
    • 25/8 6:02pm: Chạy PoC lỗ hổng trên tài khoản Arc của Hursh
    • 25/8 6:13pm: Chia sẻ chi tiết ở dạng mã hóa, sau đó được thêm vào kênh Slack
    • 26/8 9:41pm: Vá lỗ hổng và trả thưởng
    • 6/9 7:49pm: Gán CVE-2024-45489
  • Sau đó Arc đã công bố bài viết riêng về vấn đề này, CVE-2024-45489 incident response

Thực thi trên trang có đặc quyền và xung đột quyền riêng tư

  • Ngay cả khi không thể tạo Boosts từ client, chúng vẫn có thể được thực thi trên các giao thức khác
  • Nếu tạo Boost nhắm vào trang settings, nó có thể chạy trên chrome://settings và dẫn đến leo thang đặc quyền
  • Khi truy cập website, truy vấn Firestore sau xảy ra
    • Truy vấn collection boosts với điều kiện creatorID == {userID}hostPattern == "www.google.com";
  • Ở đây hostPattern có nghĩa là website đã truy cập, điều này xung đột với Chính sách quyền riêng tư của Arc, nơi Arc nói rằng họ không biết người dùng truy cập website nào

Các biện pháp tiếp theo của Arc

  • Nhân lỗ hổng này và việc đưa vào các tính năng mới, Arc chuyển sang hướng rời khỏi Firebase
  • Bản tóm tắt của chính Arc bao gồm các biện pháp sau
    • Xác nhận đã khắc phục vấn đề
    • Thêm tính năng vô hiệu hóa Boosts trên client
    • Kiểm toán nội bộ các quy tắc ACL Firebase hiện tại
    • Thiết lập giao thức ứng phó vấn đề bảo mật
  • Các biện pháp bổ sung được chia sẻ trong thảo luận nội bộ của Arc như sau
    • Khắc phục vấn đề quyền riêng tư trong bản cập nhật v1.61.1
    • Ngừng sử dụng Firebase trong các tính năng và sản phẩm mới
    • Kiểm toán bảo mật bên ngoài cho phiên bản đó
    • Khởi động chương trình bug bounty cho các lỗ hổng trong tương lai

1 bình luận

 
GN⁺ 2024-09-20
Các ý kiến trên Hacker News
  • Tôi là Hursh, đồng sáng lập kiêm CTO của The Browser Company, công ty làm Arc. Không có người dùng nào thực sự bị thiệt hại và chúng tôi đã vá ngay, nhưng tôi cho rằng mức độ nghiêm trọng tiềm tàng của lỗ hổng này là khó chấp nhận được
    Tôi đã tổng hợp chi tiết kỹ thuật, kế hoạch cải thiện trong thời gian tới, việc rời khỏi Firebase và thiết lập chương trình bug bounty chính thức tại đây: https://arc.net/blog/CVE-2024-45489-incident-response
    Tôi thực sự xin lỗi cả về bản thân lỗ hổng lẫn việc truyền thông chậm trễ; những phản hồi gồm thất vọng, giận dữ và động viên đã khiến chúng tôi thấy có trách nhiệm phải làm tốt hơn

    • Không rõ bài này có phải chỉ viết cho người dùng HN xem hay không. Nó không xuất hiện trong danh sách blog (https://arc.net/blog) và cũng chưa được đăng lên Twitter
      Toàn bộ cách phản ứng trông như chỉ khi chuyện đủ ồn ào thì mới phản hồi
    • Vài người bạn của tôi thích Arc nên tôi cũng từng cân nhắc chuyển sang dùng, nhưng giờ thì tôi nghĩ sẽ không dùng nữa. Không hẳn vì bản thân lỗ hổng, mà vì họ trả chỉ 2 nghìn USD tiền thưởng cho một lỗi có thể chiếm quyền nguy hiểm đối với mọi người dùng
      Tôi không muốn dùng một trình duyệt do một công ty xem nhẹ bảo mật người dùng như vậy tạo ra. Không chắc chắn, nhưng với mức độ nghiêm trọng này, nhiều khả năng nó có thể được bán với giá cao hơn rất nhiều trên chợ đen
    • Trong các bình luận bên dưới có lo ngại rằng mỗi lần tải trang, URL và ID người dùng có thể định danh lại được gửi về TBC. Những người dùng trình duyệt không phải Chrome nhìn chung nhiều khả năng cũng nhạy cảm với quyền riêng tư, nên nên trả lời phần này
      Lỗ hổng có thể xảy ra, nhưng việc gửi dữ liệu duyệt web trông giống một lựa chọn thiết kế có chủ ý
    • Sau vụ này, có vẻ không có cách nào thuyết phục rằng đội ngũ có đủ chuyên môn để bảo trì một trình duyệt. Bất kể đã sửa lỗi hay chưa, họ hiện tại và cả về sau cũng có vẻ không có năng lực tạo ra một trình duyệt an toàn
      Tôi nghĩ đây là việc mà CTO nên từ chức
    • Tôi muốn biết liệu có kế hoạch tăng mức chi trả bug bounty không. 2.000 USD là số tiền rất nhỏ so với giá trị của lỗi này, và tôi mong người phát hiện được đền đáp xứng đáng
      Có thể nói họ đang có một cơ hội tuyệt vời để đi đúng hướng
  • Nhiều người trong phần bình luận ở đây đổ lỗi cho Firebase, nhưng trông giống như đang nói theo những thứ họ thật ra không hiểu rõ. Tôi không dùng Firebase, nhưng theo kinh nghiệm từng dùng trước đây, đây không phải trường hợp rìa cũng không phải vấn đề khó giải quyết, mà là cơ bản của cơ bản
    Vấn đề thật sự là API được thiết kế để tin vào giá trị mà client gửi lên để nói “tôi là ai”. Rốt cuộc đây là lỗi nghiệp dư, và rất có thể chỉ cần sửa một dòng là xong. Chỉ cần xem tài liệu ở https://firebase.google.com/docs/rules/rules-and-auth#cloud-... cũng thấy request.auth cung cấp ID người dùng cần thiết (request.auth.uid)

    • Với tư cách người vận hành một ứng dụng làm bằng Firebase, tôi đồng ý. Như người viết đã chỉ ra đúng, cấu hình sai quả là rất dễ, nhưng những thực hành bảo mật cơ bản như thế này được nhấn mạnh bằng cảnh báo in đậm, nổi bật trong tài liệu Firebase
      Security rules phải được xử lý nghiêm túc, và trên thực tế đó gần như là tuyến phòng thủ duy nhất
    • Thật thú vị khi các kỹ sư phần mềm từng tự xây xác thực, rồi chuyển sang không tự xây nữa, và giờ lại không nhận ra cả những vấn đề bảo mật lộ liễu như thế này
      Dù có tự xây xác thực hay không, điểm cốt lõi chỉ có một: tuyệt đối không tin client
    • Nếu “rốt cuộc là lỗi nghiệp dư” thì còn tốt. Đồng nghiệp của tôi cũng đã mắc đúng lỗi này nhiều lần trong các ứng dụng frontend nội bộ
    • Một kế hoạch bảo mật dựa trên giả định rằng bất kỳ ai cũng tuyệt đối không bao giờ mắc lỗi nghiệp dư, bản thân nó chính là một lỗi nghiệp dư
    • Nếu tôi hiểu đúng, cách sửa vấn đề này chỉ ở mức thêm các quy tắc sau vào câu lệnh match trong firestore.rules. Đây là nội dung xuất hiện nguyên như vậy trong tài liệu nhập môn bảo mật Firebase Firestore
      
      // Allow create new object if user is authenticated
      
      allow create: if request.auth != null;
      
      // Allow update or delete document if user is owner of document
      
      allow update, delete: if request.auth.uid == resource.data.ownerUID
      
      
  • Tôi rất thích chú mèo pixel art nhỏ chạy tới chỗ mình bấm. Đó là một chi tiết nhỏ thú vị và sáng tạo mà dạo này hiếm thấy, như một lời nhắc rằng nếu chúng ta muốn thì internet cũng có thể là một không gian vui vẻ như thế

    • Phía tôi thì không thấy, có vẻ nhà phát triển tôn trọng prefers-reduced-motion nên nếu bật thiết lập đó thì không hiển thị. Đây là cách xử lý rất hay: mang lại niềm vui cho người muốn, và tránh gây phiền cho người không thích
    • Với một con mèo 35 tuổi thì nó vẫn di chuyển rất tốt
      https://en.wikipedia.org/wiki/Neko_(software)
    • Trên Debian có thể cài và chạy mèo như sau
      sudo apt install oneko
      oneko &
      Rất hợp để “tặng” cho máy tính của đồng nghiệp đang rời chỗ
    • Dễ thương thì có, nhưng cứ biết rằng mỗi lần di chuột hoặc cuộn trang là mèo sẽ di chuyển, tôi lại không tập trung đọc được. Tôi mở console lên và xóa nó đi. Xin lỗi nhé, mèo
    • Trên điện thoại, nó cứ che mất chữ nên tôi đang tìm cách loại bỏ. Chế độ đọc của Firefox đã giải quyết được
  • Theo bài viết này, Arc bắt buộc phải có tài khoản và gửi hostname của mọi trang bạn truy cập cùng ID người dùng lên Google Firebase. Vậy chẳng phải Arc đang trở thành trình duyệt có mức riêng tư yếu nhất trong số các trình duyệt hiện nay sao?

    • Ngay sau khi cài đặt, thấy bắt buộc phải có tài khoản là tôi gỡ Arc luôn. Nó trông vô lý như bàn chải đánh răng cần Wi‑Fi vậy, giờ nhìn lại còn nghiêm trọng hơn.
    • Có lẽ danh hiệu đó thuộc về OperaGX.
    • Cũng tò mò nếu Firebase sập thì Arc sẽ hỏng đến mức nào.
    • Vài tháng trước khi tải về, thấy muốn dùng phải có tài khoản, tôi đã có linh cảm rằng cứ tiếp tục dùng Firefox thì hơn.
    • Họ không mã hóa dữ liệu gửi lên Firebase sao? Nếu là dữ liệu nhạy cảm thì chắc Google cũng khuyến nghị làm vậy mà.
  • Đây là một lỗi thật sự thú vị. Các quy tắc bảo mật của dịch vụ backend như Firebase có những giá trị mặc định kỳ lạ khó giải thích. Nếu tự làm API, userId của các bản ghi như boost trong trường hợp này sẽ không được nhận từ payload của request, mà sẽ được đặt bằng ID người dùng trong session.
    Một lập trình viên ở mức khá trở lên thường sẽ không nghĩ đến việc để client truyền vào một giá trị mà nó tự nhận là userId của mình trên một API route được bảo vệ. Ngược lại, với các quy tắc bảo mật, bất kể cách sử dụng thực tế đã được lập trình ra sao, bạn phải tưởng tượng mọi cách hệ thống có thể bị lạm dụng.

    • Nếu tiếp cận theo cách đó thì nói thật là đang làm sai. Bắt đầu bằng từ chối mặc định thì chỉ cần hình dung các cách sử dụng hợp lệ.
    • Với thao tác insert thì đúng, nhưng với update tôi thường thấy người ta đưa toàn bộ request thẳng vào ORM hoặc document store. Rất dễ nghĩ rằng “chủ sở hữu có thể cập nhật tài liệu”, nhưng lại dễ bỏ sót việc một số field mà client chính thức không đặt, chẳng hạn chủ sở hữu hoặc thời điểm tạo, thì không được phép thay đổi.
      Cách đúng có lẽ là đặt quyền từ chối mặc định cho mọi field. Khi đó ít nhất bạn phải chỉ rõ field chủ sở hữu là có thể ghi, và cũng sẽ phải suy nghĩ về hệ quả của việc chuyển đối tượng này cho người dùng khác.
  • Thật ngạc nhiên là lỗ hổng này ngớ ngẩn đến mức khó tin. Muốn thực thi mã tùy ý thì đúng nghĩa chỉ cần gửi ID người dùng của người khác, mà ID đó cũng khá dễ lấy.
    Tôi không làm ở FAANG, mà làm ở một công ty tạo ra một sản phẩm tệ hại thậm chí không thật sự cần thiết, nhưng ngay cả tôi cũng sẽ không tạo ra lỗi như thế này. Vậy mà những người này nói họ sẽ làm trình duyệt, đồng thời gánh cả chuyên môn bảo mật và trách nhiệm đạo đức đi kèm sao?

    • Bạn có thể giải thích làm sao lấy được ID người dùng của người khác không? Tôi biết đây là một lỗ hổng lớn, nhưng muốn hiểu phần đó diễn ra thế nào.
  • Ước gì tiêu đề bài đăng có chữ Arc để những người đang dùng Arc hoặc có bạn bè dùng Arc dễ nhận ra hơn.

    • Hoàn toàn đồng ý. Lần đầu thấy hôm qua, tôi không biết chuyện này liên quan đến mình, đến khi tiêu đề đổi rồi mới bấm vào.
      Nói thật, tôi cảm thấy tiêu đề nên kiểu như “Lỗi nền tảng trong trình duyệt Arc (CVE 123-4567)”.
  • Trên đời có nhiều lỗ hổng bảo mật nghiêm trọng nhưng vẫn có thể hiểu được vì sao chúng được tạo ra, và nếu xử lý có trách nhiệm rồi sửa thì có thể tha thứ.
    Nhưng đây không phải trường hợp như vậy. Cá nhân tôi thấy nó thể hiện mức độ bất tài đủ để hủy hoại danh tiếng, đến mức khiến tôi quyết định sẽ không bao giờ dùng Arc nữa.

    • Mặt khác, tốc độ phản hồi bản thân nó khá ấn tượng.
      aug 25 5:48pm: Liên hệ lần đầu với Hursh, đồng sáng lập Arc, qua kênh mã hóa Signal
      aug 25 6:02pm: Chạy proof of concept lỗ hổng trên tài khoản Arc của Hursh
      aug 25 6:13pm: Công bố chi tiết ở dạng mã hóa và được thêm vào kênh Slack
      aug 26 9:41pm: Vá lỗ hổng, trả bounty
      sep 6 7:49pm: Gán CVE (CVE-2024-45489)
      Từ lần liên hệ đầu đột ngột đến khi triển khai bản sửa trong 4 giờ là khá tốt, dù có tính đến khả năng bản sửa đơn giản. Sửa: ngày đã đổi nên thực ra là 28 giờ. Dù vậy vẫn ổn, và phản hồi “vào kênh Slack của chúng tôi đi” chỉ 30 phút sau lần liên hệ đầu là rất nhanh.
    • Việc ngay cả để thử Arc một lần cũng cần tài khoản bắt buộc đã là dấu hiệu cảnh báo lớn ngay từ đầu, nên tôi chưa từng thử. Giờ thấy may là đã không dùng.
    • Nói thật, tôi luôn nhìn Arc, đặc biệt ở khía cạnh riêng tư, như sói đội lốt cừu.
      Với một sản phẩm quan trọng và riêng tư như trình duyệt, việc nhận 50–60 triệu USD tiền mặt và mức định giá 500 triệu USD nhưng không có mô hình kinh doanh là một dấu hiệu cảnh báo lớn. Đây không phải hoạt động từ thiện, nên bằng cách này hay cách khác sẽ có ai đó phải trả chi phí.
    • Khi một công ty phân phối trình duyệt, người ta thường nghĩ họ sẽ chú ý hơn một chút đến các quy tắc bảo mật.
      Cũng tiếc là Firebase không làm cho thứ này chống lỗi ngớ ngẩn tốt hơn. Và thật sự chỉ $2,500 thôi sao? Theo đúng nghĩa đen là có thể chiếm quyền toàn bộ người dùng Arc, nếu là NSA chắc họ sẽ thêm vài số 0 nữa.
    • Hơn nữa lại là Firebase, thật khó tin. Một công ty tuyển cả kỹ sư phần mềm cấp thấp mà lại dùng backend CRUD đóng hộp. Có thể hiệu quả về chi phí, nhưng nếu tôi thiết kế thứ như vậy thì Firebase thậm chí sẽ không nằm trong danh sách dài các ứng viên backend.
      Nhất là khi các đối thủ tương đương về chức năng như Supabase lại bọc quanh DBMS thông thường và mô hình xác thực.
  • Cảm ơn đã chia sẻ. Tôi đã dùng Arc từ tuần đầu beta.
    Nhưng việc họ không nhắc đến lỗi này và các bản sửa ở bất kỳ đâu trên mạng xã hội khá đáng lo. Thời gian dùng Arc rất thú vị, nhưng sau cách xử lý như thế này, tôi không nghĩ mình có thể tiếp tục dùng.

    • Thừa nhận vấn đề và sửa trong vòng 28 giờ chưa đủ sao? Với phản ứng như vậy, tôi lại thấy có thể tiếp tục dùng Arc.
  • $2,000 cho một lỗ hổng lớn như thế này là mức tiền mang tính xúc phạm.

    • Nhìn các bài blog trên HN, có vẻ nhiều lỗ hổng kiểu này hoặc không được thưởng gì, hoặc chỉ nhận được số tiền rất nhỏ. Trông như các công ty đang cầu xin hacker bán exploit vậy.
      Có lẽ cũng vì họ không bị cơ quan quản lý phạt khi xảy ra sự cố xâm nhập.
    • Đúng, phản ứng đầu tiên của tôi cũng là vậy. Thật ngạc nhiên là họ keo kiệt đến thế.
    • Cần một lương tâm khá vững mới không bán nó cho bên ác ý sẵn sàng trả gấp 20–50 lần số tiền này.