Artykuł techniczny

Wykryj naruszony XLSX: HotXLS Agile dataIntegrity HMAC

HotXLS zapisuje zgodny blok dataIntegrity w pakietach XLSX szyfrowanych Agile i weryfikuje go przy otwieraniu. HMAC-SHA-512 obejmuje cały strumień EncryptedPackage, łącznie z jego ośmiobajtowym prefiksem StreamSize, i jest sprawdzany na szyfrogramie, zanim jakikolwiek segment zostanie odszyfrowany, więc błędne hasło albo zmodyfikowany pakiet zostaje wykryty, zamiast zostać odszyfrowanym w bezsensowne dane

Szyfrowanie bez integralności to tylko połowa odpowiedzi, a formaty plików Office sprawiają, że tę lukę łatwo przeoczyć, ponieważ szyfrowanie z zewnątrz wygląda na tak solidne. Zrozumienie, co obiecuje każda warstwa, jest tym, co utrzymuje przegląd bezpieczeństwa krótkim

Co właściwie obiecuje zaszyfrowany skoroszyt?

Szyfrowanie Agile, zdefiniowane w [MS-OFFCRYPTO], daje ci poufność przez AES w trybie CBC z kluczem wyprowadzonym z iterowanego hasza hasła SHA-512. Poufność to cała obietnica tej konstrukcji. CBC nie jest trybem uwierzytelnionym: nie mówi nic o tym, czy szyfrogram, który odszyfrowujesz, jest tym samym szyfrogramem, który zapisano

Praktyczna konsekwencja jest konkretna. Odwróć bity w zaszyfrowanym pakiecie, a CBC chętnie odszyfruje je na inny tekst jawny. Zwykle dostaniesz gdzieś dalej błąd analizy ZIP, ponieważ uszkodzony strumień deflate rzadko przetrwa, ale słowo „zwykle” wykonuje w tym zdaniu ogromną pracę, a błąd analizatora dalej w potoku to okropne miejsce, by dowiedzieć się, że plik został zmodyfikowany. Element dataIntegrity istnieje właśnie po to, by odpowiedzieć na to pytanie wprost, przed odszyfrowaniem, za pomocą MAC obliczonego nad dokładnymi bajtami

Jak przebiega kontrola i w jakiej kolejności

Kolejność to interesująca część. HotXLS wyprowadza klucz pośredni z hasła, odszyfrowuje zaszyfrowany klucz HMAC i wartość HMAC z atrybutów dataIntegrity, używając wektorów IV wyprowadzonych z klucza blokowego, oblicza HMAC-SHA-512 nad zapisanym pakietem szyfrowanym i porównuje. Dopiero wtedy zaczyna się odszyfrowywanie segmentów

Sprawdzanie MAC nad szyfrogramem zamiast nad tekstem jawnym to standardowa dyscyplina encrypt-then-MAC i to właśnie czyni tę kontrolę sensowną: zmanipulowany pakiet zostaje odrzucony, zanim jakiekolwiek kontrolowane przez atakującego bajty przejdą przez ścieżkę odszyfrowywania i dekompresji. Oba porównania w ścieżce otwierania, hasz weryfikatora hasła i wartość HMAC, kumulują różnice przez XOR i OR na całym digeście, zamiast kończyć się wcześniej przy pierwszym niezgodnym bajcie, więc żadne z nich nie zdradza pozycji bajtu przez pomiar czasu

var
  Book: TXLSXWorkbook;
begin
  Book := TXLSXWorkbook.Create;
  try
    // Działa dla plików niezaszyfrowanych, szyfrowanych Standard i szyfrowanych Agile
    if Book.OpenEncrypted('incoming.xlsx', PasswordFromVault) = 1 then
      ProcessWorkbook(Book)
    else
      // Błędne hasło albo pakiet, którego HMAC dataIntegrity się nie zgadza
      Quarantine('incoming.xlsx');
  except
    on E: Exception do
      Quarantine('incoming.xlsx: ' + E.Message);
  end;
  Book.Free;
end;

Po stronie zapisu w twoim kodzie nic się nie zmienia. SaveAsEncrypted emituje blok automatycznie, a sole, dane wejściowe weryfikatora i klucz HMAC pochodzą z CryptGenRandom. Jeśli to wywołanie zawiedzie, HotXLS zgłasza wyjątek zamiast przechodzić na słabsze źródło. Bezpieczne zamknięcie w razie awarii CSPRNG to nie paranoja; ciche przejście na przewidywalne źródło losowości tworzy pliki, które wyglądają na zaszyfrowane, przechodzą każdy test funkcjonalny i są bezwartościowe

Dlaczego pliki bez tego bloku wciąż się otwierają?

Ponieważ ogromna liczba skoroszytów szyfrowanych Agile w obiegu została napisana przez producentów, którzy całkowicie pomijają dataIntegrity, a ich odrzucenie zepsułoby znacznie więcej legalnej pracy, niż by ochroniło. HotXLS traktuje integralność jako obecną tylko wtedy, gdy oba atrybuty, zaszyfrowany klucz HMAC i zaszyfrowana wartość HMAC, są obecne i poprawnie sformowane. W przeciwnym razie weryfikacja jest pomijana, a plik otwiera się jak dotychczas

To decyzja o zgodności z konsekwencją bezpieczeństwa, którą warto jawnie nazwać we własnym modelu zagrożeń: braku bloku nie da się odróżnić od usunięcia go przez atakującego, ponieważ atrybuty leżą poza MAC, który by go niósł. Jeśli kontrolujesz oba końce potoku, traktuj brakujący blok jako naruszenie polityki na poziomie aplikacji. Jeśli przyjmujesz pliki ze świata, traktuj tę kontrolę jako to, czym jest: cenny sygnał, gdy jest obecny, i żaden sygnał, gdy go nie ma

Hasło do modyfikacji to konwencja, nie granica

Klasyczne skoroszyty XLS obsługują osobny mechanizm, regularnie mylony z szyfrowaniem: rezerwację zapisu, czyli okno Excela „hasło do modyfikacji”. HotXLS udostępnia ją przez SetModifyPassword, która przyjmuje hasło, flagę zalecanego trybu tylko do odczytu i nazwę użytkownika rezerwującego, a stan zgłasza przez IsWriteReserved. Przekazanie pustego hasła czyści rezerwację

To, co zostaje zapisane, to para rekordów WRITEPROT i FILESHARING niosąca flagę zalecanego trybu tylko do odczytu, przestarzały 16-bitowy hasz hasła oraz nazwę użytkownika jako łańcuch Unicode BIFF8. Ten 16-bitowy hasz to suma kontrolna, nie kryptograficzny skrót, a treść dokumentu w ogóle nie jest szyfrowana. Każdy, kto otworzy plik dowolnym innym narzędziem, przeczyta wszystko. Prawdziwym zadaniem tej funkcji jest koordynacja: informuje kolejną osobę, że ktoś uważa ten plik za swój do edycji, w tej samej kategorii co kontrole na poziomie arkusza opisane w ochronie arkusza XLSX i opcjach zezwoleń

var
  Book: IXLSWorkbook;   // licznik odwołań interfejsu: nie wywołuj Free
begin
  Book := TXLSWorkbook.Create;
  if Book.Open('shared-model.xls') = 1 then
  begin
    // Zalecany tryb tylko do odczytu, zarezerwowane przez usługę raportowania
    Book.SetModifyPassword('edit-me', True, 'Reporting Service');

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

Używaj obu warstw do tego, w czym każda jest dobra. Prawdziwa poufność pochodzi z SaveAsEncrypted z hasłem, którego nikt spoza odbiorców nie zna, co daje wyjście AES-256 opisane w chronionym AES wyjściu XLSX. Rezerwacja zapisu dokłada się na wierzch, gdy skoroszyt jest artefaktem wspólnej edycji, a ty chcesz, aby Excel zapytał, zanim ktoś nadpisze plik

Co sprawdzić na niezaufanej ścieżce przyjmowania plików

Weryfikacja integralności chroni zaszyfrowany ładunek, nie kontener wokół niego. Plik XLSX to archiwum ZIP, a struktura archiwum jest analizowana, zanim uruchomi się jakakolwiek logika szyfrowania, więc walidacja na poziomie kontenera musi być pierwsza w łańcuchu; konkretne tryby awarii są omówione w walidacji EOCD ZIP dla niezaufanych plików XLSX. Potem traktuj niepowodzenie integralności i błędne hasło jako to samo zdarzenie operacyjne, ponieważ z twojej strony są nie do odróżnienia z założenia, a oba oznaczają, że plikowi nie można ufać, że jest tym, za co uważa go nadawca

Zapisuj w logu, które pliki w ogóle niosły blok dataIntegrity. Na przestrzeni kilku tysięcy dokumentów ta statystyka mówi ci coś użytecznego o narzędziach twoich nadawców i zamienia kontrolę pojedynczego pliku w obserwację na poziomie całej floty, na której możesz działać

HotXLS odczytuje i zapisuje XLS, XLSX i ODS z poziomu Delphi i C++Builder bez instalacji Excela, implementując w Pascalu ścieżki szyfrowania Standard i Agile z [MS-OFFCRYPTO]. API szyfrowania, ochrony i skoroszytu jest udokumentowane na stronie komponentu arkusza kalkulacyjnego HotXLS dla Delphi