I don't so much care about OOXML signatures per se (maybe there's some European government that relies on them, but I've never seen a signed .DOCX in real life), but this paper is super useful just as a record of how to test a signature system.

https://www.usenix.org/conference/usenixsecurity23/presentation/rohlmann

Every Signature is Broken: On the Insecurity of Microsoft Office’s OOXML Signatures | USENIX

You're a vulnerability researcher and somebody drops OOXML signatures on your lap, asks "do these things work?”

Well, what does "work" mean? Here, it means "everything the renderer displays to a doc viewer today was knowingly signed by the authority who signed it yesterday”. That's a hard problem! Much harder than signing an .deb package.

So the first thing the researcher does is go figure out how OOXML works in the first place. Surprise, it's a nightmare! 40 years of stratified features dating back to Multi-Tool Word for Xenix. The first 3 weeks of your project are probably just reading the spec.

You come to learn that an OOXML .DOCX is a ZIP archive with what appear to be three different manifests inside, because why not. They are:

1. [Content_Types.xml], mapping filenames to content types; any file in the bundle not in this manifest will trigger an error.

2. document.xml.rels, mapping filenames to symbolic IDs, which are referenced from documents themselves.

3. The "Package Info" section of "sig1.xml”, the signature block, which maps files to hashes of those files.

The "index.html" of a .DOCX file is a file in the bundle called "document.xml", and that's where all rendering starts.

You can sort of spitball how you'd do a signing scheme for this system; maybe it doesn't have to be complicated at all. Just reject signatures for any .DOCX bundle that includes a file not in the "Package Info" section.

But there's this paper, so you know that's not what they did.

So, [Content_Types.xml] isn't signed at all. You can add and remove files to a .DOCX bundle without breaking the signature.

But that doesn't necessarily matter, right? Those are just files in a ZIP file What matters is whether files get pulled in by the rendering process. You imagine the designers of this format starting with an axiom like “if it's referenced by document.xml, it has to be signed”. More on that in a sec.

The bigger problem is how “document.xml.rels” is signed. Remember, this is the mapping of symbolic IDs to filenames in the bundle; it's what the renderer consults when following links between files in the bundle; it's the routing table of a .DOCX.

Instead of signing "document.xml.rels", the signer parses it, and adds the hash of each referenced file to the "Package Info" manifest. The ".rels" file itself: not signed.

This is a mystifying decision.

@tqbf This sounds eeriely similar to what MSBuild and solutions with assemblies, hashes and references. Probably less of an issue there but I could so much imagine the designers simply implementing what they already know. Probably there's even an internal MS library "XMLSignatureVerifier" they just slapped on.