Signature Wrapping Attack (SWA)

The SWA introduces a novel technique to bypass signature protection without using incremental saving.

The main idea is to move the second part of the signed /ByteRange to the end of the document while reusing the xref pointer within the signed trailer to an attacker manipulated xref. To avoid any processing of the relocated second part, it can be optionally wrapped by using a stream object or a dictionary. In the picture below, two documents are depicted. On the left side, a validly signed PDF file is depicted. On the right side, a manipulated PDF file is generated by using SWA.


The attack works as follows:

  1. (optional): The attacker deletes the padded zero Bytes within the Contents parameter to increase the available space for injecting manipulated objects.

  2. The attacker defines a new /ByteRange [a,b,c,d]* by manipulating the c value, which now points to the second signed part placed on a different position within the document.

  3. The attacker creates a new xref pointing to the new objects. It is essential that the byte offset of the newly inserted xref has the same byte offset as the previous xref. The position is not changeable since it is referenced by the signed trailer For this purpose, the attacker can add a padding block (e.g., using whitespaces) before the new xref to fill the unused space.

  4. The attacker injects malicious objects which are not protected by the signature. There are different injection points for these objects. %If Step 1 is executed, we can place the malicious object before the malicious xref. They can be placed before or after the malicious xref. If Step 1 is not executed, it is only possible to place them \emph{after} the malicious xref.

  5. Some PDF viewers need a trailer after the manipulated xref; otherwise they cannot open the PDF file or detect the manipulation and display a warning message. Copying the last trailer is sufficient to bypass this limitation.

  6. The attacker moves the signed content defined by c and d at byte offset c*. Optionally, the moved content can be encapsulated within a stream object.