Password-beskyttelse af en OOXML-fil

by jlundstocholm 18. September 2007 21:39

I en tråd på v2.dk for snart længe siden blev der højlydt diskuteret indholdet af Stéphane Rodriguez' artikel om OOXML og at OOXML i sig selv er ødelagt pr. design (OOXML is defective by design). Vi diskuterede bla. punkt 10 i artiklen, der taler om tilsyneladende problemer med afhængighed af OLE og password-beskyttelse af et OOXML-dokument som det gøres i MS Office 2007. Omdrejningspunktet i afsnit 10 er det billede, der efterhånden er nået hele verden rundt:

I tråden snakkede vi bla. om, hvordan passwordbeskyttelse laves i OOXML og da vi ikke kunne hitte ud af det, lovede jeg at vende tilbage, når jeg har fundet svaret - og derfor denne artikel.

Passwordbeskyttelse i OOXML og ODF

Passwordbeskyttelse er et område, hvor OOXML i angrebsvinkel adskiller sig fra ODF. I ODF sker passwordbeskyttelse på "part"-niveau, dvs de enkelte dele af ODF-filen krypteres. I ODF-spec (OASIS-udgave) er det beskrevet i afsnit 17.3 Encryption. Der står bla. at hver del-fil i ZIP-filen skal først komprimeres  og herefter krypteres med Blowfish-algoritmen med en nøglelængde på 128 bits (der er nogle andre specifikke, krypteringstekniske detaljer, men de er ikke vigtige her).

Hvis man forsøger at finde ud af, hvordan det gøres i OOXML, så kan man ikke finde noget sted, hvor det står i spec. Det står hverken i Part 4 (Reference) eller i Part 2 (OPC-spec). Det viser sig dog, at der er en grund til miséren. Man har nemlig valgt at lade kryptering af en OOXML-fil være defineret udenfor spec - eller rettere: ikke at definere kryptering. Argumentet jeg fik, da jeg spurgte Microsoft, var, at man dermed ikke låser sig fast på én algoritme og man tillader, at organisationer, der måtte have højere krav til nøglestørrelsen eller egne algoritmer stadig kunne anvende OOXML som dokumentformat

Jeg er ikke sikker på, at jeg er enig i deres designvalg. Det er klart, at der er en vis ræson i at lave et format, som NSA eller DOD kan bruge out-of-the-box (som PHK udtalte på sin blog: Erfaring har vist at når DoD taler, så lytter Microsoft.). Men det giver jo nogle praktiske problemer. Fx kan jeg ikke være sikker på, at jeg som OOXML-konsument kan hitte ud af, hvordan et dokument er krypteret, når jeg modtager det. Det giver nogle uhensigtsmæssigheder i dag. På den anden side er jeg heller ikke helt enig i ODF-valget, da det virker uovervejet, at man har låst sig fast på én krypteringsalgoritme og én nøglestørrelse. Det giver nemlig nogle uhensigtsmæssigheder i fremtiden. Jeg forstår i det hele taget ikke, at man ikke har valgt at bruge fx AES, når man nu skulle vælge algoritme. Det er i øvrigt også pudsigt, at flere kritikpunkter af OOXML fra anti-OOXML-lobbyen netop har gået på, at det skulle være muligt at anvende en hvilken som helst algoritme til kryptering af dele af et OOXML-dokument ... men det var åbenbart ikke noget problem at låse sig fast, da man moslede ODF igennem ISO.

Den famøse OLE-fil

Som nævnt har ovenstående billede været hele verden rundt, og det fortjener naturligvis en behandling. For at finde forklaringen på OLE-filen, så skal man gøre sig det klart, hvilke udfordringer det giver at lave kryptering på pakkeniveau samt ikke at slå sig fast på én metode til kryptering.  Helt overordnet skal der findes en løsning på følgende:

Hvordan er kryptering sket?

Når en OOXML-konsument modtager et OOXML-dokument, der er krypteret, skal det være muligt at finde ud af, hvordan dette er sket. I tilfældet med ODF er dette nemt - man hiver fat i en Blowfish-implementering og gennemløber skridtene i afsnit 17.3 af ODF-spec "bagfra" og så har man det oprindelige dokument. I tilfældet med OOXML er det lidt mere tricky, for man har ikke samme information. Der skal altså findes en løsning til at sikre, at man kan se, hvordan noget er krypteret.

Hvordan skal persistering ske?

Dette er også lidt af en udfordring. Da OOXML er "pakke-agnostisk" er det ikke ligetil at definere en metode, der altid vil virke - for metoden skal jo virke både ved anvendelse af ZIP-filer som overordnet container men også for eventuelle andre måde at anvende OPC. Vær her opmærksom på, at en OPC-pakke reelt er en samling af streams, der er persisterede i en eller anden form. Igen har ODF det nemmere, da valget af én krypteringsalgoritme hjælper dig på vej.

So what can you do?

(eller rettere: hvad gjorde Microsoft?) 

Der skal altså findes en container, der indeholder en eller anden slags beskrivende del (konvolut), hvor man kan skrive, hvilken krypteringsalgoritme man har brugt. Containeren skal også kunne indeholde de krypterede streams, der udgør det oprindelige dokument. I Microsoft Office har man valgt en af Microsoft særdeles velkendt teknologi som container - nemlig en såkaldt "Compound File". Den teknologiske terminologi bag disse filer er også kendt som "Structured storage". Det navn som disse filer er mest kendte under er dog "OLE2 Compound File". "Structured storage" forklares ofte som "a file system within a file". Det er altså en måde at gemme partionerede/opdelte data på - uden at skulle vedligeholde en traditionel filstruktur. På sin vis minder dette meget om ZIP-formatet, der også tillader en slags filstruktur. Det er dog værd at bemærke, at selvom indholdet af en ZIP-fil set via fx WinZip eller WinRAR umiddelbart er anskueliggjort med folder og filer, så er selve indholdet af en ZIP-fil "blot" en række streams, der er persisterede i en samlet container. På samme vis er disse compound files "blot" et antal streams, der er persisterede i en overordnet container.

OLE - WTF?

Inden jeg kaster mig over, hvad man så gør nu, så lad mig lige knytte et par kommentarer til de fordele anvendelse af Compound Files giver. Jeg har til det formål lavet et Excel-ark som i Stéphanes artikel om OOXML og det har jeg beskyttet med et password EncryptedFile.xlsx (12,16 kb). Hvis jeg åbner filen i programmet DocFile Viewer 0.1 ser det således ud



Hver af delene i denne fil repræsenterer en persisteret stream eller en stump metadata. Som jeg nævnte ovenfor, så kræver udeladelse af spec for kryptering en eller anden "konvolut-funktionalitet", hvor man kan finde information om, hvordan den enkelte Compound File skal behandles (dekrypteres), og i denne fil ligger informationen i den del, der hedder "EncryptionInfo" samt i den del, der hedder "StrongEncryptionTransform/Primary. I delen "EncryptionInfo" ligger information om, hvilken komponent, der har lavet krypteringen. I dette tilfælde er det "M i c r o s o f t   E n h a n c e d   R S A   a n d   A E S   C r y p t o g r a p h i c   P r o v i d e r   ( P r o t o t y p e ) ". Det er en del af Cryptographic Application Programming Interface (CryptoAPI) i MS Office. I Excel 2003 kan man vælge imellem flere forskellige måder at kryptere filen på - alle fra dette API. I delen "StringEncryptionTransform/Primary" findes infromationen om, hvilken kryptografisk teknik, der er anvendt. Som det ses herunder er filen krypteret med algoritmen AES og nøglelængde 128. Et hurtigt kig i dokumentationen for CryptoAPI indikerer, at den anvendte Cryptographi Service Provider er PROV_RSA_AES.


Endelig ligger selve indholdet af den krypterede OOXML-fil i delen "EncryptedPackage"

OLE og OLE2 Compound Document Format

Hvis vi er i Windows-verdenen, så er alt stadig rosenrødt - men hvad gør vi nu, hvis vi nu sidder med OpenOffice.org på en Linux-box? Her har man jo ikke adgang til OLE.

Det er her vigtigt at være opmærksom på, at OLE og OLE2 Compound Files er to forskellige ting. OLE2 er en structured storage container - principielt at sammenligne med et ZIP-arkiv (blot uden komprimering). Eksempler på anvendelse af disse containere er MS-Office filer som .DOC, .XLS, .PPT og .VSD (Visio filer). OLE2-filer er i øvrigt ikke begrænsede til Microsoft-programmer. De anvendes generelt af masser af forskellige programmer pga. muligheden for at have "a filesystem within a file". OLE, derimod, er en teknologi, der bla. arbejder med disse filer. OLE er ansvarlig for, at et ODF-dokument i OpenOffice.org (På Windows-platformen), der er linket til et Visio-diagram, kan blive opdateret med ændringer, når diagrammet ændres. OLE er ansvarlig for, at et Word-dokument indeholdende et link til et Excel-ark opdateres, hvis en celle ændres i arket. OLE er ansvarlig for, at man kan lave et Excel-ark med et link til et Corel-dokument, hvor Excel-arket opdateres, hvis Corel-filen opdateres. På en Windows-maskine er OLE i det hele taget ansvarlig for, at det er muligt at anvende andre programmers funktionalitet i ét program, så man ikke skal åbne hvert eneste program for sig.

Men man behøver ikke hverken COM eller OLE for at anvende en OLE2 Compound File.

Det bedste, lavpraktiske, argument for dette er naturligvis, at OpenOffice.org, StarOffice, Google Docs og andre kontorpakker på ikke-Windows-platformen, kan arbejde med Microsoft Office filerne. Hvis det krævede OLE for at kunne det, så ville det ikke være muligt at gøre det på andre platforme end Windows. Vær i øvrigt opmærksom på, at det store arbejde som bla. Sun har gjort med at lave reverse engineering på de binære MS Office-filer var koncentreret omkring selve formaterne (altså hvordan man fx laver fed skrift i Word 2000) og ikke om den stuctured storage container, der indeholder selve Word-dokumentet.

Links af interesse for nogle: KDE.org maillist, What is OLE really about? (MSDN), KOffice maillist, OLE for idiots (MSDN), placering af OLE-storage kildekoden for OOo (i 2004), OOo structured Storage implementering (CVS) 

So what can you do? (Part 2)

Ønsker du at lave det hele fra bunden og implementere din egen structured storage container reader/writer-application, så kan du finde specifikationen for formatet i Microsoft Office 2007 File formats, der kan rekvireres fra Microsofts hjemmeside. Du kan også starte med Microsofts egen forklaring på, hvad disse containere er. Denne information kan du finde på MSDN. Men hvis du allerede har en applikation, der blot skal udbygges til at kunne håndtere krypterede OOXML-dokumenter og ikke gider at lave hele arbejdet selv, så hurra for bla. OSS. Der findes nemlig et væld af forskellige biblioteker (nogle koster penge) derude, der giver mulighed for manipulation af structured storage filer.

En kort og bestemt ikke udtømmende liste over disse er (ikke i nogen bestemt orden efter hverken betydning eller aktivitet)

  • libole2 - udstiller et API til læsning af structured storage filer (licens: GPL)
  • Structured storage library VCL - bibliotek til læsning af Structured storage for Delphi/c++builder udviklere (Licens: n/a, kildekode koster $40)
  • DataConv - generel oversigt over konverteringsværktøjer
  • ripOLE - bibliotek til at trække data ud af OLE2-filer (licens: BSD)
  • Chicago Project - læs Excel-filer (licens: GPL)
  • pole - C++ bibliotek til adgang til OLE2-filer (licens: n/a, men lugter lidt af BSD)
  • libgsf - C-bibliotek (licens: LGPLv2.1)
  • POI - Java API til håndtering af Microsoft Office filer (licens: n/a men er nok en eller anden variant af Apache-licensen)
  • LAOLA - "legendarisk" Perl bibliotek, oprindeligt baseret på reverse engineering af OLE2-filer (licens: GPL)
  • GemBox.CompoundFile - .Net.komponent til at læse, skrive og manipulere OLE2-filer (licens: én licens pr. udvikler, ingen licens for produktionsserver)

Konklusion

Som tidligere nævnt er jeg som udgangspunkt uenig i Microsofts valg af container til den krypterede fil. Set fra Microsofts stol er valget klart nok, men det kunne godt have været gjort nemmere. Det kunne jo være en simpel XML-fil med 3 elementer


Der er ganske sikkert nogle detaljer, som jeg ikke her kan gennemskue - bla. herunder det pakke-agnostiske OPC-format - men jeg er sikker på, at det kunne være gjort på en lidt mere elegant måde. Når det så er sagt, så er det tilbageværende spørgsmål jo: Er der et interoperabilitetsproblem i Microsofts valg af container til håndtering af krypterede OPC-pakker? Nej, det er der ikke. Microsoft har valgt en uelegant måde at implementere password-beskyttelse på, men der er intet, der forhindrer nogen i at arbejde med filerne. Det sker jo allerede i OpenOffice.org, i NeoOffice og alle de andre programmer derude, der kan arbejde med OLE2-filer.

Jeg er helt sikker på, at der er nogen, der vil spinne denne artikel i en retning, der siger: "OOXML indebærer et krav om OLE-tilstedeværelse på den konkrete platform" ... men jeg vil respektfuldt mene, at de tager fejl. Jeg er også helt sikker på, at der er nogen, der vil spinne denne artikel i en retning, der siger: "Jeg sagde det jo, OOXML indebærer dermed via MS Office referencer til OLE" ... men jeg vil respektfuldt påpege, at ovenstående ikke har noget med OOXML at gøre men med MS Office at gøre. Jeg vil også respektfuldt spørge, om det var et problem, hvis OOXML indeholdt referencer til OLE?

Smile

Comments

1/7/2008 9:25:41 PM #

sureshhalade

Can anybody tell me what EncryptionInfo stream contains exactly? And how it stores password related info? How to retrieve that info?

sureshhalade India |

1/7/2008 10:31:29 PM #

jlundstocholm

As far as I can see the Encryption Info stream contains more or less the same as the Strong Encryption Package stream part as displayed above. You would retrieve this information just as you would retrieve any other info from the compound file. The specification of this is available from msdn2.microsoft.com/en-us/library/aa380369.aspx, also as noted above.You could also check the source code for OOo since it seems to have no problems with opening password-protected binary MS Office files, and Microsoft Office uses the same technique for these files.

Smile

PS: Do you speak Danish?

jlundstocholm Denmark |

1/7/2008 11:39:03 PM #

sureshhalade

Hi..

No I don't speak or even understand Danish. Could you please tel me any English URL where I can read this info.?

Btw thx for the info.
Do you know any info regarding how open and modify passwords got stored in the EncryptionInfo stream? What bit-position they relates to in the stream?

Thanks.

sureshhalade India |

1/8/2008 12:31:01 AM #

jlundstocholm

Hi Suresh,

No - I do not have that information at hand (it was not the corner stone of my article. I have been playing with the idea of writing a small tool to open a password protected .XLSX-file, but I never got around to do it. I would imagine that you need to look at the Microsoft CryptoAPI since this is the tool used by Microsoft Office.

However - please note that I would seriously doubt it if you can find any password information in the encrypted file. The password - or any fragment/hash - of it is not useful in the encrypted file when decrypting - all you need is the way it was originally encrypted and - of course - the password.

jlundstocholm Denmark |

Comments are closed