Teknisk artikel

Upptäck manipulerad XLSX: HotXLS Agile dataIntegrity HMAC

HotXLS skriver ett konformt dataIntegrity-block in i Agile-krypterade XLSX-paket och verifierar det vid öppning. HMAC-SHA-512 täcker hela EncryptedPackage-strömmen, inklusive dess åtta-byte-långa StreamSize-prefix, och kontrolleras mot chiffertexten innan något segment dekrypteras, så ett fel lösenord eller ett modifierat paket upptäcks i stället för att dekrypteras till skräp

Kryptering utan integritet är ett halvt svar, och Office-filformat gör det lätt att förbise den luckan eftersom krypteringen ser så grundlig ut utifrån. Att förstå vad varje lager lovar är det som håller en säkerhetsgranskning kort

Vad lovar egentligen en krypterad arbetsbok?

Agile-kryptering, definierad i [MS-OFFCRYPTO], ger dig konfidentialitet genom AES i CBC-läge med en nyckel härledd från en itererad SHA-512-lösenordshash. Konfidentialitet är hela löftet i den konstruktionen. CBC är inget autentiserat läge: det säger ingenting om huruvida chiffertexten du dekrypterar är den chiffertext som skrevs

Den praktiska konsekvensen är specifik. Vänd bitar i ett krypterat paket och CBC dekrypterar dem gladeligen till annan klartext. Du får oftast ett ZIP-tolkningsfel någonstans nedströms, eftersom en skadad deflate-ström sällan överlever, men ”oftast” gör mycket jobb i den meningen, och ett tolkningsfel nedströms är ett fruktansvärt ställe att få reda på att en fil har ändrats. Elementet dataIntegrity finns för att besvara frågan direkt, före dekryptering, med en MAC över exakt de byten

Hur kontrollen körs, och i vilken ordning

Ordningen är den intressanta delen. HotXLS härleder mellannyckeln från lösenordet, dekrypterar den krypterade HMAC-nyckeln och HMAC-värdet från attributen i dataIntegrity med blocknyckelhärledda IV:n, beräknar HMAC-SHA-512 över det krypterade paketet som det är lagrat, och jämför. Först därefter börjar segmentdekrypteringen

Att kontrollera MAC:en över chiffertexten snarare än klartexten är den vedertagna disciplinen kryptera-sedan-MAC, och det är det som gör kontrollen meningsfull: ett manipulerat paket avvisas utan att några angriparkontrollerade byte har körts genom dekrypterings- och uppackningsvägen. Båda jämförelserna i öppningsvägen, lösenordsverifierarens hash och HMAC-värdet, ackumulerar skillnader med XOR och OR över hela digesten i stället för att returnera tidigt vid den första omatchade byten, så ingen av dem läcker en byteposition genom timing

var
  Book: TXLSXWorkbook;
begin
  Book := TXLSXWorkbook.Create;
  try
    // Fungerar för vanliga, Standard-krypterade och Agile-krypterade filer
    if Book.OpenEncrypted('incoming.xlsx', PasswordFromVault) = 1 then
      ProcessWorkbook(Book)
    else
      // Fel lösenord, eller ett paket vars dataIntegrity-HMAC inte matchade
      Quarantine('incoming.xlsx');
  except
    on E: Exception do
      Quarantine('incoming.xlsx: ' + E.Message);
  end;
  Book.Free;
end;

På skrivsidan ändras ingenting i din kod. SaveAsEncrypted sänder ut blocket automatiskt, och salterna, verifierarindatan och HMAC-nyckeln kommer från CryptGenRandom. Om det anropet misslyckas höjer HotXLS ett undantag i stället för att falla tillbaka till en svagare källa. En fail-closed CSPRNG är ingen paranoia; en tyst nedgradering till en förutsägbar slumpkälla producerar filer som ser krypterade ut, klarar varje funktionstest, och är värdelösa

Varför öppnas filer utan blocket ändå?

Därför att väldigt många Agile-krypterade arbetsböcker i omlopp skrevs av producenter som utelämnar dataIntegrity helt, och att avvisa dem skulle förstöra betydligt mer legitimt arbete än det skulle skydda. HotXLS behandlar integritet som närvarande bara när båda attributen, den krypterade HMAC-nyckeln och det krypterade HMAC-värdet, finns där och är korrekt formade. Annars hoppas verifiering över och filen öppnas som förut

Det här är ett kompatibilitetsbeslut med en säkerhetskonsekvens du bör namnge explicit i din egen hotmodell: frånvaron av blocket går inte att skilja från att en angripare tog bort det, eftersom attributen ligger utanför den MAC de skulle ha burit. Om du styr båda ändarna av en pipeline, behandla ett saknat block som ett policyfel på applikationsnivå. Om du tar emot filer från omvärlden, behandla kontrollen som vad den är, en värdefull signal när den finns och ingen signal alls när den saknas

Lösenord för att ändra är en konvention, inte en gräns

Klassiska XLS-arbetsböcker stöder en separat mekanism som rutinmässigt förväxlas med kryptering: skrivreservationen, Excels ”lösenord för att ändra”-dialogruta. HotXLS exponerar den genom SetModifyPassword, som tar lösenordet, en flagga för att rekommendera skrivskydd och namnet på den reserverande användaren, och rapporterar tillstånd genom IsWriteReserved. Att skicka ett tomt lösenord rensar reservationen

Det som skrivs är ett WRITEPROT- och FILESHARING-postpar som bär flaggan för rekommenderat skrivskydd, en äldre 16-bitars lösenordshash och användarnamnet som en BIFF8-Unicode-sträng. Den 16-bitars hashen är en kontrollsumma, inte en kryptografisk digest, och dokumentinnehållet är inte krypterat alls. Vem som helst som öppnar filen med något annat verktyg läser allt. Funktionens verkliga uppgift är samordning: den talar om för nästa person att någon betraktar den här filen som sin att redigera, i samma kategori som de bladnivåkontroller som täcks i XLSX-bladskydd och tillåt-alternativ

var
  Book: IXLSWorkbook;   // gränssnittsräknad: anropa inte Free
begin
  Book := TXLSWorkbook.Create;
  if Book.Open('shared-model.xls') = 1 then
  begin
    // Rekommendera skrivskydd, reserverad av rapporteringstjänsten
    Book.SetModifyPassword('edit-me', True, 'Reporting Service');

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

Använd båda lagren för det vardera är bra på. Verklig konfidentialitet kommer från SaveAsEncrypted med ett lösenord ingen utanför mottagarkretsen har, vilket ger den AES-256-utdata som beskrivs i AES-skyddad XLSX-utdata. Skrivreservationen läggs ovanpå när arbetsboken är ett delat redigeringsartefakt och du vill att Excel ska fråga innan någon sparar över den

Vad som bör kontrolleras på en opålitlig intagsväg

Integritetsverifiering skyddar den krypterade nyttolasten, inte behållaren runt den. En XLSX-fil är ett ZIP-arkiv, och arkivstrukturen tolkas innan någon krypteringslogik körs, så validering på behållarnivå hör hemma först i kedjan; de specifika felmoderna täcks i ZIP-EOCD-validering för opålitlig XLSX. Efter det, behandla ett integritetsfel och ett fel lösenord som samma driftshändelse, eftersom de från din sida är omöjliga att skilja åt per design, och båda betyder att filen inte kan litas på att vara vad avsändaren tror att den är

Logga vilka filer som överhuvudtaget bar ett dataIntegrity-block. Över några tusen dokument talar den statistiken om något användbart om dina avsändares verktyg, och den förvandlar en per-fil-kontroll till en flottnivåobservation du kan agera på

HotXLS läser och skriver XLS, XLSX och ODS från Delphi och C++Builder utan någon Excel-installation, och implementerar krypteringsvägarna Standard och Agile från [MS-OFFCRYPTO] i Pascal. API:erna för kryptering, skydd och arbetsbok dokumenteras på sidan för HotXLS Delphi kalkylarkskomponent