NIFI-4125 Added secure transform feature and configuration to TransformXML processor to mitigate XXE file system leaks.

This closes #1946.

Signed-off-by: Andy LoPresto <alopresto@apache.org>
This commit is contained in:
yuri1969 2017-06-25 22:10:31 +02:00 committed by Andy LoPresto
parent 3089d9dce0
commit 3bf1d12706
No known key found for this signature in database
GPG Key ID: 6EC293152D90B61D
1 changed files with 24 additions and 3 deletions

View File

@ -28,6 +28,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.xml.XMLConstants;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
@ -98,6 +99,16 @@ public class TransformXml extends AbstractProcessor {
.addValidator(StandardValidators.BOOLEAN_VALIDATOR)
.build();
public static final PropertyDescriptor SECURE_PROCESSING = new PropertyDescriptor.Builder()
.name("secure-processing")
.displayName("Secure processing")
.description("Whether or not to mitigate various XML-related attacks like XXE (XML External Entity) attacks.")
.required(true)
.defaultValue("true")
.allowableValues("true", "false")
.addValidator(StandardValidators.BOOLEAN_VALIDATOR)
.build();
public static final PropertyDescriptor CACHE_SIZE = new PropertyDescriptor.Builder()
.name("cache-size")
.displayName("Cache size")
@ -135,6 +146,7 @@ public class TransformXml extends AbstractProcessor {
final List<PropertyDescriptor> properties = new ArrayList<>();
properties.add(XSLT_FILE_NAME);
properties.add(INDENT_OUTPUT);
properties.add(SECURE_PROCESSING);
properties.add(CACHE_SIZE);
properties.add(CACHE_TTL_AFTER_LAST_ACCESS);
this.properties = Collections.unmodifiableList(properties);
@ -166,8 +178,17 @@ public class TransformXml extends AbstractProcessor {
.build();
}
private Templates newTemplates(String path) throws TransformerConfigurationException {
private Templates newTemplates(ProcessContext context, String path) throws TransformerConfigurationException {
final Boolean secureProcessing = context.getProperty(SECURE_PROCESSING).asBoolean();
TransformerFactory factory = TransformerFactory.newInstance();
if (secureProcessing) {
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
// don't be overly DTD-unfriendly forcing http://apache.org/xml/features/disallow-doctype-decl
factory.setFeature("http://saxon.sf.net/feature/parserFeature?uri=http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://saxon.sf.net/feature/parserFeature?uri=http://xml.org/sax/features/external-general-entities", false);
}
return factory.newTemplates(new StreamSource(path));
}
@ -186,7 +207,7 @@ public class TransformXml extends AbstractProcessor {
cache = cacheBuilder.build(
new CacheLoader<String, Templates>() {
public Templates load(String path) throws TransformerConfigurationException {
return newTemplates(path);
return newTemplates(context, path);
}
});
} else {
@ -218,7 +239,7 @@ public class TransformXml extends AbstractProcessor {
if (cache != null) {
templates = cache.get(xsltFileName);
} else {
templates = newTemplates(xsltFileName);
templates = newTemplates(context, xsltFileName);
}
final Transformer transformer = templates.newTransformer();