Bug: PDF.js Parser differential attack
Status: RESOLVED
Priority: P3
Resolution: WONTFIX
Created: 2022-03-25 13:14:47+00:00
Resolved: 2024-05-30 17:55:03+00:00

# Background 
Portable Document Format (PDF) is a popular file format for presenting legal documents and agreements between parties. The PDF standard encodes documents in an as-printed form which should be portable between systems. In this publication, we introduce a parser differential attack targeting Mozilla PDF.js users. The attack makes it possible to create a malicious PDF document which renders completely different content based on the used reader.

The presentation of PDF files is meant to be independent of the used PDF viewer software, web browser, operating system or existing font-files on the device; they should render identically even through various printer devices. PDF readers attempt to present documents as well as they can, and use as many supported and requested sophisticated PDF ISO Standards and proprietary features as possible. 

The original PDF file format is dated and limited, and more ISO Standards have been made to fill the gaps, such as Adobe PDF, Adobe PDF Optimized, PDF/A, PDF/A-2, PDF/A-3, PDF/UA, PDF/E and PDF/X. Of these, particularly interesting is Adobe's PDF 1.7 (ISO 32000-1), which introduces Adobe's Interactive Forms, including JavaScript extensions, AcroForms and Adobe XML Forms Architecture (XFA). Many PDF readers do not render content that is not standardized or contain non-essential sophisticated features. 

PDF readers are not identical and do not support the same set of proprietary or other, more sophisticated PDF features. In this write-up, we focus on the Mozilla PDF.js solution, but the overall issue is more general. That is, the PDF readers do not warn the user that the presented content contains features that might not be rendered identically everywhere. 

## Finding
Mozilla PDF.js is a popular Portable Document Format (PDF) library used in Mozilla Firefox for presenting PDF documents. On 2021-10-02 Mozilla activated PDF XFA form support by default. In practice, PDF.js renders fillable XFA form pages that most other readers do not support - these other readers present a fallback PDF page included as part of the document.

This means that XFA PDF readers and non-XFA-compliant readers can present completely different content out of the same base document. None of the readers alert that the document contains unsupported features, or that some rare PDF features are being used that most readers won't be able to render properly.

Mozilla's PDF Reader PDF.js library changelog states “This release features improved XFA support (enabled by default now),” on  v2.11.338 release (Oct 02, 2021).  https://github.com/mozilla/pdf.js/releases 
Which is introduced in the following commit:
> https://hg.mozilla.org/releases/mozilla-beta/rev/b3a0ff6bba57

## Products that present XFA content as default (POC=1337)
Mozilla Firefox 98.0.1 (64-bit), latest - 1337
Adobe Acrobat Reader DC (64-bit), 2022.001.20085, Windows – 1337
Adobe Acrobat Reader DC (64-bit), 2022.001.20085 Mac – 1337
Adobe Acrobat Mac – 1337
Wondershare PDFelement – 1337 – PDF editor
pdfjs-2.13.216-dist – 1337
https://mozilla.github.io/pdf.js/web/viewer.html -- 1337 (tested using chrome, edge and firefox)
https://mozilla.github.io/pdf.js/legacy/web/viewer.html - 1337


## PDF.js dependents potentially affected, e.g, web apps,
https://www.npmjs.com/package/pdfjs-dist?activeTab=dependents 
https://www.jsdelivr.com/package/npm/pdfjs-dist

## Products that present a fallback PDF page instead of XFA (but still not warn about unsupported features) (POC=1000)
Apple Finder (file preview)
Apple Preview
Apple Safari
Windows (File preview)
Slack
Slack (Web)
Chromium
Edge
Firefox Daylight 98,2 (8475), iPhone
Chromium extension
https://chrome.google.com/webstore/detail/pdf-viewer/oemmndcbldboiebfnladdacbdfmadadm
  
## Payload(s)
https://github.com/mozilla/pdf.js/files/7251394/Purchase.Order.pdf
https://github.com/mozilla/pdf.js/issues/14090

Payload offers “The document you are trying to load” page if the reader does not support XFA. This content can be modified, like is done in the invoice document included as an attachment. Document offers 1337 price for XFA readers, and 1000 for others. 

## Impact
As a result, PDF file can be crafted which displays completely different content, based on whether the reader uses the PDF.js library. 

As an example, an attacker could try to inject mutually exclusive pages into document, and hope the various openers are using different readers and see the different context. As an example, an invoice document could attempt to present a contract which will present different amounts to an approving supervisor and accounts payable; in this scenario the approval is made by the supervisor for a low sum, while accounting pays the approved larger fee. 

Parser differential issues happen when multiple PDF parsers are used for processing a single document. PDF.js enables embedding a PDF viewer in an HTML page making many popular sites affected regardless the web browser. Websites might present PDF file through PDF.js preview, but the download and opening the file locally leads to an alternative content.

Content previewed and downloaded using Firefox might be later opened using local PDF viewer or printed on paper. Corporate printers might accept PDF files directly, via web interfaces or through the USB stick. Also, a system default PDF viewer might change over time, changing the visible content.


## Remediation (for service owners)
Services handling arbitrary PDF files should define a list of supported PDF file format extensions and ensure that the files being accepted are in-line with the requirements. Avoid supporting file formats that cannot guarantee the same content will be visible to all users. Files could also be converted to a simpler format where the same potentially lossy converter handles those special cases and strips them out similarly.
 

## Fix (vendor)
Feature rich readers should provide a compatibility view of the document, rendering the document like a basic PDF reader would do. Basic readers should alert in a situation where the document contains an unsupported feature, and the potential consequences of the suffered document portability situation causes. If all pages can't be rendered, the reader should alert about the issue.