2 điểm bởi GN⁺ 2024-09-20 | 1 bình luận | Chia sẻ qua WhatsApp

Giới thiệu tính năng đám mây của Arc

  • Cần có tài khoản để dùng Arc
  • Sử dụng Firebase cho xác thực
  • Có tính năng giống bảng trắng tên là 'Easels'
  • Ngay cả khi nhấp nút chia sẻ, yêu cầu cũng không xuất hiện trong mitmproxy

Tấn công ứng dụng Firebase nền tảng Objective-C

  • Dùng Firestore để xây dựng mà không cần viết backend, chỉ cần viết các quy tắc bảo mật cơ sở dữ liệu
  • Firestore không tuân theo thiết lập proxy hệ thống trong Swift SDK
  • Viết script Frida để dump các lời gọi liên quan
var documentWithPath = ObjC.classes.FIRCollectionReference["- documentWithPath:"];
var queryWhereFieldIsEqualTo = ObjC.classes.FIRQuery["- queryWhereField:isEqualTo:"];
var collectionWithPath = ObjC.classes.FIRFirestore["- collectionWithPath:"];

function getFullPath(obj) {
  if (obj.path && typeof obj.path === "function") {
    return obj.path().toString();
  }
  return obj.toString();
}

var queryStack = [];

function logQuery(query) {
  var queryString = `firebase.${query.type}("${query.path}")`;
  query.whereClauses.forEach((clause) => {
    queryString += `.where("${clause.fieldName}", "==", "${clause.value}")`;
  });
  console.log(queryString);
}

Interceptor.attach(documentWithPath.implementation, {
  onEnter: function (args) {
    var parent = ObjC.Object(args[0]);
    var docPath = ObjC.Object(args[2]).toString();
    var fullPath = getFullPath(parent) + "/" + docPath;
    var query = { type: "doc", path: fullPath, whereClauses: [] };
    queryStack.push(query);
    logQuery(query);
  },
});

Interceptor.attach(collectionWithPath.implementation, {
  onEnter: function (args) {
    var collectionPath = ObjC.Object(args[2]).toString();
    var query = { type: "collection", path: collectionPath, whereClauses: [] };
    queryStack.push(query);
  },
});

Interceptor.attach(queryWhereFieldIsEqualTo.implementation, {
  onEnter: function (args) {
    var fieldName = ObjC.Object(args[2]).toString();
    var value = ObjC.Object(args[3]).toString();

    if (queryStack.length > 0) {
      var currentQuery = queryStack[queryStack.length - 1];
      currentQuery.whereClauses.push({ fieldName: fieldName, value: value });
    }
  },
  onLeave: function (retval) {},
});

var executionMethods = [
  "- getDocuments",
  "- addSnapshotListener:",
  "- getDocument",
  "- addDocumentSnapshotListener:",
  "- getDocumentsWithCompletion:",
  "- getDocumentWithCompletion:",
];

executionMethods.forEach(function (methodName) {
  if (ObjC.classes.FIRQuery[methodName]) {
    Interceptor.attach(ObjC.classes.FIRQuery[methodName].implementation, {
      onEnter: function (args) {
        if (queryStack.length > 0) {
          var query = queryStack.pop();
          logQuery(query);
        }
      },
    });
  }
});

function formatFirestoreData(data) {
  if (data.isKindOfClass_(ObjC.classes.NSDictionary)) {
    let result = {};
    data.enumerateKeysAndObjectsUsingBlock_(
      ObjC.implement(function (key, value) {
        result[key.toString()] = value.toString();
      })
    );
    return JSON.stringify(result);
  }
  return data.toString();
}

var documentMethods = [
  { name: "- updateData:completion:", type: "update" },
  { name: "- updateData:", type: "update" },
  { name: "- setData:completion:", type: "set" },
  { name: "- setData:", type: "set" },
];

documentMethods.forEach(function (method) {
  if (ObjC.classes.FIRDocumentReference[method.name]) {
    Interceptor.attach(
      ObjC.classes.FIRDocumentReference[method.name].implementation,
      {
        onEnter: function (args) {
          var docRef = ObjC.Object(args[0]);
          var data = ObjC.Object(args[2]);
          var fullPath = getFullPath(docRef);
          var formattedData = formatFirestoreData(data);
          console.log(
            `firebase.doc("${fullPath}").${method.type}(${formattedData})`
          );
        },
      }
    );
  } else {
    console.log("Warning: " + method.name + " not found");
  }
});
  • Arc lưu các tùy chọn mặc định của người dùng, đối tượng người dùng, đề xuất và boost trong Firestore

Arc boost là gì

  • Arc boost là cách để người dùng tùy biến website
  • Có thể chặn phần tử, đổi phông chữ, đổi màu, dùng CSS và JS tùy chỉnh
  • Có thể tạo boost và cập nhật nó bằng ID của người dùng khác

Lấy ID của người dùng khác

  • Đề xuất người dùng: có thể lấy ID người dùng từ bảng đề xuất
  • Boost công khai: snapshot của boost chứa ID người dùng của người tạo
  • Easel của người dùng: có thể chia sẻ easel để lấy ID người dùng

Chuỗi tấn công cuối cùng

  • Lấy ID người dùng của nạn nhân
  • Tạo boost độc hại và lưu vào tài khoản của mình
  • Cập nhật trường creatorID của boost thành ID của mục tiêu
  • Khi nạn nhân truy cập website mục tiêu thì sẽ bị lây nhiễm

RCE trên các trang đặc quyền

  • Boost cũng chạy trên các giao thức khác
  • Có thể leo thang đặc quyền trên trang chrome://settings

Vấn đề quyền riêng tư

  • Dữ liệu về các trang được truy cập sẽ bị gửi lên máy chủ
  • Điều này vi phạm chính sách quyền riêng tư của Arc

Tóm tắt của GN⁺

  • Bài viết phân tích các tính năng đám mây và lỗ hổng bảo mật của Arc
  • Đề cập tới vấn đề bảo mật backend khi tận dụng Firestore
  • Giải thích khả năng tùy biến người dùng và lỗ hổng bảo mật thông qua Arc boost
  • Trình bày cách lấy ID của người dùng khác để chạy boost độc hại
  • Nêu lên lo ngại về vấn đề quyền riêng tư và khả năng leo thang đặc quyền

1 bình luận

 
GN⁺ 2024-09-20
Ý kiến trên Hacker News
  • Lỗ hổng bảo mật của trình duyệt Arc ở mức không thể chấp nhận được, và vì điều này tôi sẽ không bao giờ dùng Arc nữa
  • Chú mèo pixel art chạy đến mỗi khi nhấp chuột khá vui và nhắc rằng internet có thể là một nơi thú vị
  • Cần thêm Arc vào tiêu đề bài viết để cảnh báo những người đang dùng trình duyệt Arc
  • Arc yêu cầu tài khoản và gửi tên máy chủ của mọi trang người dùng truy cập cùng ID người dùng lên Firebase của Google. Điều này có nghĩa Arc hiện là trình duyệt web ít bảo vệ quyền riêng tư nhất đang được sử dụng
  • Cấu hình mặc định của quy tắc bảo mật Firebase thật kỳ lạ, và nhà phát triển có kinh nghiệm sẽ không để client truyền ID người dùng của chính họ vào đường dẫn API được bảo vệ
  • OP đang nói về trình duyệt Arc, không nên nhầm với ngôn ngữ Arc hay các dự án khác
  • Có vẻ trình duyệt Arc sẽ không tồn tại lâu, và Chrome là trình duyệt an toàn nhất. Cần thận trọng khi chọn phần mềm mới
  • Khoản tiền thưởng 2000 USD là con số mang tính xúc phạm so với mức độ nghiêm trọng của lỗ hổng
  • Có người thắc mắc 'arc' được nhắc trong bài đăng trên blog là gì. Có vẻ là trình duyệt Arc
  • Đây là bài viết khó đọc vì không dùng chữ viết hoa đúng cách