Skip to content

Commit 618de33

Browse files
committed
Fixed: Enhance XML processing security by disabling external entity resolution across multiple classes
1 parent 20f8f53 commit 618de33

13 files changed

Lines changed: 61 additions & 7 deletions

File tree

applications/accounting/src/main/java/org/apache/ofbiz/accounting/thirdparty/eway/GatewayResponse.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.math.RoundingMode;
2424
import java.util.Locale;
2525

26+
import javax.xml.XMLConstants;
2627
import javax.xml.parsers.DocumentBuilder;
2728
import javax.xml.parsers.DocumentBuilderFactory;
2829

@@ -165,14 +166,13 @@ public double getBeagleScore() {
165166
public GatewayResponse(InputStream xmlstream, GatewayRequest req) throws Exception {
166167

167168
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
168-
// Below is an answer to a codeQL action on GH reporting a possible XXE
169-
// I have a doubt about "load-external-dtd" feature because I did not test the changes.
170169
builderFactory.setValidating(true);
171170
builderFactory.setNamespaceAware(true);
172171

173172
builderFactory.setAttribute("http://xml.org/sax/features/validation", true);
174173
builderFactory.setAttribute("http://apache.org/xml/features/validation/schema", true);
175174

175+
builderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
176176
builderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
177177
builderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
178178
builderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

framework/base/src/main/java/org/apache/ofbiz/base/util/UtilHtml.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ public static List<ParseError> validateHtmlFragmentWithJSoup(String content) {
6969
*/
7070
public static List<String> hasUnclosedTag(String content) {
7171
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
72+
inputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
73+
inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
7274
XMLEventReader eventReader = null;
7375
List<String> errorList = new ArrayList<>();
7476
try {

framework/base/src/main/java/org/apache/ofbiz/base/util/UtilXml.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.util.regex.Matcher;
3838
import java.util.regex.Pattern;
3939

40+
import javax.xml.XMLConstants;
4041
import javax.xml.parsers.DocumentBuilder;
4142
import javax.xml.parsers.DocumentBuilderFactory;
4243
import javax.xml.parsers.ParserConfigurationException;
@@ -226,6 +227,9 @@ public static Transformer createOutputTransformer(String encoding, boolean omitX
226227
sb.append("</xsl:template>\n</xsl:stylesheet>\n");
227228
ByteArrayInputStream bis = new ByteArrayInputStream(sb.toString().getBytes());
228229
TransformerFactory transformerFactory = TransformerFactory.newInstance();
230+
transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
231+
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
232+
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
229233
return transformerFactory.newTransformer(new StreamSource(bis));
230234
}
231235

@@ -460,6 +464,7 @@ public static Document readXmlDocument(InputStream is, boolean validate, String
460464
factory.setAttribute("http://xml.org/sax/features/validation", validate);
461465
factory.setAttribute("http://apache.org/xml/features/validation/schema", validate);
462466

467+
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
463468
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
464469
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
465470
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
@@ -589,6 +594,9 @@ public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIEx
589594
parser.setFeature("http://xml.org/sax/features/validation", validate);
590595
parser.setFeature("http://apache.org/xml/features/validation/schema", validate);
591596
parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
597+
parser.setFeature("http://xml.org/sax/features/external-general-entities", false);
598+
parser.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
599+
parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
592600

593601
// with a SchemaUrl, a URL object
594602
if (validate) {
@@ -617,9 +625,9 @@ public static Document makeEmptyXmlDocument() {
617625
public static Document makeEmptyXmlDocument(String rootElementName) {
618626
Document document = null;
619627
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
620-
621628
factory.setValidating(true);
622629
try {
630+
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
623631
DocumentBuilder builder = factory.newDocumentBuilder();
624632

625633
document = builder.newDocument();
@@ -1273,6 +1281,9 @@ public static String convertDocumentToXmlString(Document document) {
12731281
TransformerFactory tf = TransformerFactory.newInstance();
12741282
Transformer transformer;
12751283
try {
1284+
tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
1285+
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
1286+
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
12761287
transformer = tf.newTransformer();
12771288
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
12781289
transformer.setOutputProperty(OutputKeys.INDENT, "yes");

framework/base/src/main/java/org/apache/ofbiz/base/util/string/UelFunctions.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
import jakarta.el.FunctionMapper;
3939

40+
import javax.xml.XMLConstants;
4041
import javax.xml.parsers.DocumentBuilder;
4142
import javax.xml.parsers.DocumentBuilderFactory;
4243
import javax.xml.parsers.ParserConfigurationException;
@@ -368,6 +369,7 @@ public static Document readHtmlDocument(String str) {
368369
URL url = FlexibleLocation.resolveLocation(str);
369370
if (url != null) {
370371
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
372+
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
371373
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
372374
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
373375
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
@@ -443,6 +445,9 @@ public static String toHtmlString(Node node, String encoding, boolean indent, in
443445
sb.append("</xsl:template>\n</xsl:stylesheet>\n");
444446
ByteArrayInputStream bis = new ByteArrayInputStream(sb.toString().getBytes(StandardCharsets.UTF_8));
445447
TransformerFactory transformerFactory = TransformerFactory.newInstance();
448+
transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
449+
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
450+
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
446451
try (ByteArrayOutputStream os = new ByteArrayOutputStream();) {
447452
UtilXml.transformDomDocument(transformerFactory.newTransformer(new StreamSource(bis)), node, os);
448453
return os.toString();

framework/base/src/main/java/org/apache/ofbiz/base/util/template/XslTransform.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ public static String renderTemplate(String template, String data) throws Transfo
6060
pfactory.setXIncludeAware(true);
6161
XMLReader reader = null;
6262
try {
63+
pfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
64+
pfactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
65+
pfactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
66+
pfactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
6367
reader = pfactory.newSAXParser().getXMLReader();
6468
} catch (Exception e) {
6569
throw new TransformerException("Error creating SAX parser/reader", e);

framework/entity/src/main/java/org/apache/ofbiz/entity/util/EntitySaxReader.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.util.List;
3636
import java.util.Map;
3737

38+
import javax.xml.XMLConstants;
3839
import javax.xml.parsers.ParserConfigurationException;
3940
import javax.xml.parsers.SAXParser;
4041
import javax.xml.parsers.SAXParserFactory;
@@ -265,7 +266,13 @@ public long parse(URL location) throws SAXException, java.io.IOException {
265266
private long parse(InputStream is, String docDescription) throws SAXException, java.io.IOException {
266267
SAXParser parser;
267268
try {
268-
parser = SAXParserFactory.newInstance().newSAXParser();
269+
SAXParserFactory factory = SAXParserFactory.newInstance();
270+
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
271+
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
272+
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
273+
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
274+
factory.setXIncludeAware(false);
275+
parser = factory.newSAXParser();
269276
} catch (ParserConfigurationException pce) {
270277
throw new SAXException("Unable to create the SAX parser", pce);
271278
}

framework/minilang/src/main/java/org/apache/ofbiz/minilang/MiniLangUtil.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.Set;
3030
import java.util.TimeZone;
3131

32+
import javax.xml.XMLConstants;
3233
import javax.xml.transform.Transformer;
3334
import javax.xml.transform.TransformerFactory;
3435
import javax.xml.transform.stream.StreamSource;
@@ -282,6 +283,9 @@ public static void writeMiniLangDocument(URL xmlURL, Document document) {
282283
try {
283284
styleSheetURL = FlexibleLocation.resolveLocation("component://minilang/config/MiniLang.xslt");
284285
TransformerFactory transformerFactory = TransformerFactory.newInstance();
286+
transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
287+
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
288+
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
285289
try (InputStream styleSheetInStream = styleSheetURL.openStream()) {
286290
transformer = transformerFactory.newTransformer(new StreamSource(styleSheetInStream));
287291
}

framework/security/src/main/java/org/apache/ofbiz/security/SecuredUpload.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import javax.imageio.ImageIO;
6262
import javax.imageio.ImageReader;
6363
import javax.imageio.stream.ImageInputStream;
64+
import javax.xml.XMLConstants;
6465
import javax.xml.parsers.DocumentBuilder;
6566
import javax.xml.parsers.DocumentBuilderFactory;
6667
import javax.xml.parsers.ParserConfigurationException;
@@ -1332,9 +1333,12 @@ private static boolean isSafeSvgContent(String fileName) {
13321333
try {
13331334
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
13341335
// Harden against XXE and DOCTYPE-based injection attacks
1336+
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
13351337
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
13361338
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
13371339
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
1340+
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
1341+
dbf.setXIncludeAware(false);
13381342
dbf.setExpandEntityReferences(false);
13391343
dbf.setNamespaceAware(true);
13401344
DocumentBuilder db = dbf.newDocumentBuilder();

framework/service/src/main/java/org/apache/ofbiz/service/ModelService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import javax.wsdl.extensions.soap.SOAPBody;
6161
import javax.wsdl.extensions.soap.SOAPOperation;
6262
import javax.wsdl.factory.WSDLFactory;
63+
import javax.xml.XMLConstants;
6364
import javax.xml.namespace.QName;
6465
import javax.xml.parsers.DocumentBuilder;
6566
import javax.xml.parsers.DocumentBuilderFactory;
@@ -1993,6 +1994,7 @@ public void getWSDL(Definition def, String locationURI) throws WSDLException {
19931994
DocumentBuilder builder = null;
19941995
Document document = null;
19951996
try {
1997+
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
19961998
builder = factory.newDocumentBuilder();
19971999
document = builder.newDocument();
19982000
} catch (Exception e) {

framework/service/src/main/java/org/apache/ofbiz/service/engine/SOAPClientEngine.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,10 @@ private Map<String, Object> serviceInvoker(ModelService modelService, Map<String
136136

137137
try {
138138
String xmlParameters = SoapSerializer.serialize(parameterMap);
139-
XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(new StringReader(xmlParameters));
139+
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
140+
xmlInputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
141+
xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
142+
XMLStreamReader reader = xmlInputFactory.createXMLStreamReader(new StringReader(xmlParameters));
140143
OMXMLParserWrapper builder = OMXMLBuilderFactory.createStAXOMBuilder(reader);
141144
parameterSer = builder.getDocumentElement();
142145
} catch (Exception e) {

0 commit comments

Comments
 (0)