Bài viết kỹ thuật

HotXLS: Phát hiện XLSX bị sửa bằng HMAC dataIntegrity Agile

HotXLS ghi một khối dataIntegrity hợp chuẩn vào các gói XLSX mã hóa Agile và xác minh nó khi mở tệp. HMAC-SHA-512 bao phủ toàn bộ luồng EncryptedPackage, bao gồm cả tiền tố StreamSize 8 byte của nó, và được kiểm tra trên bản mã trước khi bất kỳ phân đoạn nào được giải mã, nên một mật khẩu sai hoặc một gói đã bị sửa đổi sẽ được phát hiện thay vì bị giải mã thành dữ liệu rác

Mã hóa mà thiếu tính toàn vẹn chỉ là một nửa câu trả lời, và các định dạng tệp Office khiến khoảng trống đó dễ bị bỏ qua vì việc mã hóa trông có vẻ kỹ lưỡng từ bên ngoài. Hiểu rõ mỗi lớp hứa hẹn điều gì chính là điều giúp một cuộc rà soát bảo mật ngắn gọn

Một sổ làm việc được mã hóa thực sự hứa hẹn điều gì?

Mã hóa Agile, được định nghĩa trong [MS-OFFCRYPTO], mang lại tính bí mật thông qua AES ở chế độ CBC với một khóa dẫn xuất từ chuỗi băm mật khẩu SHA-512 lặp lại. Tính bí mật là toàn bộ lời hứa của cấu trúc đó. CBC không phải là một chế độ có xác thực: nó không nói gì về việc liệu bản mã bạn đang giải mã có đúng là bản mã đã được ghi ra hay không

Hệ quả thực tế rất cụ thể. Đảo bit trong một gói đã mã hóa và CBC sẽ vui vẻ giải mã chúng thành một bản rõ khác. Bạn thường sẽ gặp một lỗi phân tích ZIP ở đâu đó phía sau, vì một luồng deflate bị hỏng hiếm khi sống sót, nhưng chữ "thường" đang gánh rất nhiều trọng lượng trong câu đó, và một lỗi phân tích cú pháp ở tầng sau là một nơi tệ hại để nhận ra rằng một tệp đã bị sửa đổi. Phần tử dataIntegrity tồn tại để trả lời trực tiếp câu hỏi đó, trước khi giải mã, bằng một MAC trên đúng những byte đã có

Cách kiểm tra chạy, và theo thứ tự nào

Thứ tự chính là phần đáng chú ý. HotXLS dẫn xuất khóa trung gian từ mật khẩu, giải mã khóa HMAC và giá trị HMAC đã mã hóa từ các thuộc tính dataIntegrity bằng các IV dẫn xuất từ khóa khối, tính HMAC-SHA-512 trên gói đã mã hóa như được lưu trữ, rồi so sánh. Chỉ sau đó việc giải mã phân đoạn mới bắt đầu

Việc kiểm tra MAC trên bản mã thay vì bản rõ là kỷ luật encrypt-then-MAC tiêu chuẩn, và đó chính là điều khiến việc kiểm tra có ý nghĩa: một gói bị can thiệp sẽ bị từ chối mà không có bất kỳ byte nào do kẻ tấn công kiểm soát từng đi qua đường giải mã và giải nén. Cả hai phép so sánh trong đường mở tệp, băm verifier mật khẩu và giá trị HMAC, đều cộng dồn sự khác biệt bằng XOR và OR trên toàn bộ digest thay vì trả về sớm ngay khi gặp byte không khớp đầu tiên, nên không phép so sánh nào để lộ vị trí byte thông qua thời gian xử lý

var
  Book: TXLSXWorkbook;
begin
  Book := TXLSXWorkbook.Create;
  try
    // Hoạt động với tệp thường, mã hóa Standard và mã hóa Agile
    if Book.OpenEncrypted('incoming.xlsx', PasswordFromVault) = 1 then
      ProcessWorkbook(Book)
    else
      // Sai mật khẩu, hoặc một gói mà HMAC dataIntegrity không khớp
      Quarantine('incoming.xlsx');
  except
    on E: Exception do
      Quarantine('incoming.xlsx: ' + E.Message);
  end;
  Book.Free;
end;

Ở phía ghi, không có gì thay đổi trong mã của bạn. SaveAsEncrypted tự động phát ra khối này, và các muối, dữ liệu đầu vào verifier cùng khóa HMAC đến từ CryptGenRandom. Nếu lệnh gọi đó thất bại, HotXLS sẽ raise thay vì rơi về một nguồn ngẫu nhiên yếu hơn. Một CSPRNG fail-closed không phải là sự thận trọng thái quá; một sự hạ cấp âm thầm về một nguồn ngẫu nhiên có thể đoán trước sẽ tạo ra các tệp trông như đã mã hóa, vượt qua mọi bài kiểm thử chức năng, và hoàn toàn vô giá trị

Vì sao các tệp thiếu khối này vẫn mở được?

Vì rất nhiều sổ làm việc mã hóa Agile đang lưu hành được ghi ra bởi các trình tạo bỏ qua hoàn toàn dataIntegrity, và việc từ chối chúng sẽ phá hỏng nhiều công việc hợp lệ hơn là bảo vệ được. HotXLS chỉ coi tính toàn vẹn là hiện diện khi cả hai thuộc tính, khóa HMAC đã mã hóa và giá trị HMAC đã mã hóa, đều có mặt và đúng định dạng. Nếu không, việc xác minh bị bỏ qua và tệp mở như trước

Đây là một quyết định tương thích kèm theo một hệ quả bảo mật mà bạn nên nêu rõ ràng trong mô hình đe dọa của chính mình: sự vắng mặt của khối này không thể phân biệt được với việc kẻ tấn công đã gỡ bỏ nó, vì các thuộc tính này nằm ngoài phạm vi MAC mà chúng lẽ ra phải mang theo. Nếu bạn kiểm soát cả hai đầu của một pipeline, hãy coi một khối bị thiếu là một lỗi chính sách ở cấp ứng dụng. Nếu bạn đang tiếp nhận tệp từ bên ngoài, hãy coi việc kiểm tra này đúng như bản chất của nó, một tín hiệu có giá trị khi hiện diện và hoàn toàn không phải tín hiệu gì khi vắng mặt

Mật khẩu để sửa đổi là một quy ước, không phải một ranh giới

Các sổ làm việc XLS cổ điển hỗ trợ một cơ chế riêng biệt thường bị nhầm lẫn với mã hóa: đặt chỗ ghi, lời nhắc "password to modify" của Excel. HotXLS cung cấp nó qua SetModifyPassword, nhận mật khẩu, một cờ khuyến nghị chỉ đọc và tên người dùng đặt chỗ, và báo cáo trạng thái qua IsWriteReserved. Truyền một mật khẩu rỗng sẽ xóa việc đặt chỗ

Những gì được ghi ra là một cặp bản ghi WRITEPROT và FILESHARING mang theo cờ khuyến nghị chỉ đọc, một mã băm mật khẩu 16-bit kiểu cũ và tên người dùng dưới dạng chuỗi Unicode BIFF8. Mã băm 16-bit đó là một checksum, không phải một digest mật mã học, và nội dung tài liệu hoàn toàn không được mã hóa. Bất kỳ ai mở tệp bằng công cụ khác đều đọc được mọi thứ. Công dụng thực sự của tính năng này là điều phối: nó báo cho người tiếp theo biết rằng ai đó coi tệp này là của họ để chỉnh sửa, cùng hạng mục với các kiểm soát cấp trang tính được trình bày trong bảo vệ trang tính XLSX và các tùy chọn allow

var
  Book: IXLSWorkbook;   // đếm tham chiếu interface: đừng gọi Free
begin
  Book := TXLSWorkbook.Create;
  if Book.Open('shared-model.xls') = 1 then
  begin
    // Khuyến nghị chỉ đọc, đặt chỗ bởi dịch vụ báo cáo
    Book.SetModifyPassword('edit-me', True, 'Reporting Service');

    if Book.IsWriteReserved then
      Book.SaveAs('shared-model.xls', xlExcel97);
  end;
end;

Hãy dùng cả hai lớp cho đúng thế mạnh của chúng. Tính bí mật thực sự đến từ SaveAsEncrypted với một mật khẩu không ai ngoài đối tượng dự kiến nắm giữ, tạo ra đầu ra AES-256 được mô tả trong đầu ra XLSX được bảo vệ bằng AES. Việc đặt chỗ ghi được thêm vào khi sổ làm việc là một tạo phẩm chỉnh sửa chung và bạn muốn Excel hỏi trước khi ai đó lưu đè lên

Cần kiểm tra gì trên một đường tiếp nhận không đáng tin

Xác minh tính toàn vẹn bảo vệ tải trọng đã mã hóa, không phải phần vỏ chứa xung quanh nó. Một tệp XLSX là một kho lưu trữ ZIP, và cấu trúc kho lưu trữ được phân tích trước khi bất kỳ logic mã hóa nào chạy, nên việc kiểm tra hợp lệ ở cấp container thuộc về vị trí đầu tiên trong chuỗi; các dạng lỗi cụ thể được trình bày trong kiểm tra hợp lệ ZIP end-of-central-directory cho XLSX không đáng tin. Sau đó, hãy coi một lỗi toàn vẹn và một mật khẩu sai là cùng một sự kiện vận hành, vì từ phía bạn, chúng không thể phân biệt được theo thiết kế, và cả hai đều có nghĩa là tệp không thể được tin tưởng là đúng như người gửi nghĩ

Hãy ghi log những tệp nào có mang theo khối dataIntegrity. Qua vài nghìn tài liệu, số liệu đó cho bạn biết điều gì đó hữu ích về công cụ của những người gửi, và biến một lần kiểm tra riêng lẻ theo từng tệp thành một quan sát ở cấp toàn hạm đội mà bạn có thể hành động

HotXLS đọc và ghi XLS, XLSX và ODS từ Delphi và C++Builder mà không cần cài Excel, triển khai các đường mã hóa Standard và Agile của [MS-OFFCRYPTO] bằng Pascal. Các API mã hóa, bảo vệ và sổ làm việc được tài liệu hóa tại trang thành phần bảng tính HotXLS cho Delphi