Commit 62c8b6ea1fcc173aeafd382461921a038107f303

Authored by Alan Davis
1 parent 50c21568c0
Exists in master

REPO-480 Platform XXE protection implements OWASP recommendations

- Added extra log4j
src/main/java/org/alfresco/xmlfactory/DocumentBuilderFactoryXercesImpl.java
... ... @@ -22,7 +22,9 @@ import java.util.List;
22 22  
23 23 import org.apache.xerces.jaxp.DocumentBuilderFactoryImpl;
24 24  
  25 +import javax.xml.parsers.DocumentBuilder;
25 26 import javax.xml.parsers.DocumentBuilderFactory;
  27 +import javax.xml.parsers.ParserConfigurationException;
26 28  
27 29 public class DocumentBuilderFactoryXercesImpl extends DocumentBuilderFactoryImpl
28 30 {
... ... @@ -39,4 +41,11 @@ public class DocumentBuilderFactoryXercesImpl extends DocumentBuilderFactoryImpl
39 41 {
40 42 factoryHelper.configureFactory(this, FEATURES_TO_ENABLE, FEATURES_TO_DISABLE, WHITE_LIST_CALLERS);
41 43 }
42   -}
  44 +
  45 + @Override
  46 + public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {
  47 + DocumentBuilder documentBuilder = super.newDocumentBuilder();
  48 + factoryHelper.debugNewParser(documentBuilder);
  49 + return documentBuilder;
  50 + }
  51 +}
43 52 \ No newline at end of file
... ...
src/main/java/org/alfresco/xmlfactory/FactoryHelper.java
... ... @@ -24,8 +24,10 @@ import java.net.URL;
24 24 import java.util.*;
25 25  
26 26 import javax.xml.XMLConstants;
  27 +import javax.xml.parsers.DocumentBuilder;
27 28 import javax.xml.parsers.DocumentBuilderFactory;
28 29 import javax.xml.parsers.ParserConfigurationException;
  30 +import javax.xml.parsers.SAXParser;
29 31 import javax.xml.parsers.SAXParserFactory;
30 32  
31 33 import org.apache.commons.logging.Log;
... ... @@ -59,8 +61,8 @@ class FactoryHelper
59 61 FEATURE_USE_ENTITY_RESOLVER2,
60 62 FEATURE_LOAD_EXTERNAL_DTD,
61 63  
62   - ADDITIONAL_FEATURE_X_INCLUDE_AWARE
63   - , ADDITIONAL_FEATURE_EXPAND_ENTITY_REFERENCES
  64 + ADDITIONAL_FEATURE_X_INCLUDE_AWARE,
  65 + ADDITIONAL_FEATURE_EXPAND_ENTITY_REFERENCES
64 66 )));
65 67  
66 68 final static List<String> DEFAULT_FEATURES_TO_ENABLE = Collections.unmodifiableList(new ArrayList<>(
... ... @@ -88,9 +90,15 @@ class FactoryHelper
88 90 static final String FEATURES_TO_DISABLE = "features.to.disable";
89 91 static final String WHITE_LIST_CALLERS = "white.list.callers";
90 92  
  93 + private static volatile int counter = 1;
  94 + private int debugCounter = counter++;
  95 +
  96 + private final int STACK_DEPTH = 30;
  97 +
91 98 void configureFactory(DocumentBuilderFactory factory, List<String> featuresToEnable,
92 99 List<String> featuresToDisable, List<String> whiteListCallers)
93 100 {
  101 + debugStack("DocumentBuilderFactory newInstance", 3, STACK_DEPTH);
94 102 if (!isCallInWhiteList(whiteListCallers))
95 103 {
96 104 if (featuresToEnable != null)
... ... @@ -113,6 +121,7 @@ class FactoryHelper
113 121 void configureFactory(SAXParserFactory factory, List<String> featuresToEnable,
114 122 List<String> featuresToDisable, List<String> whiteListCallers)
115 123 {
  124 + debugStack("SAXParserFactory newInstance", 3, STACK_DEPTH);
116 125 if (!isCallInWhiteList(whiteListCallers))
117 126 {
118 127 if (featuresToEnable != null)
... ... @@ -142,7 +151,7 @@ class FactoryHelper
142 151 {
143 152 if (currentClassName.equals(className))
144 153 {
145   - logger.debug("Found " + className + " in white list.");
  154 + debug(debugCounter+" Found " + className + " in white list.");
146 155 return true;
147 156 }
148 157 }
... ... @@ -150,6 +159,22 @@ class FactoryHelper
150 159 return false;
151 160 }
152 161  
  162 + private void debugStack(String message, int fromStackDepth, int maxStackDepth) {
  163 + if (logger.isDebugEnabled())
  164 + {
  165 + debug(debugCounter+" "+message);
  166 +
  167 + StackTraceElement[] currentStackTrace = (new Exception()).getStackTrace();
  168 + StringJoiner stackDebug = new StringJoiner("\n");
  169 + for (int i=fromStackDepth; i<currentStackTrace.length && i<maxStackDepth+fromStackDepth; i++)
  170 + {
  171 + StackTraceElement frame = currentStackTrace[i];
  172 + stackDebug.add(debugCounter+" "+frame);
  173 + }
  174 + debug(stackDebug.toString());
  175 + }
  176 + }
  177 +
153 178 private void setFeature(DocumentBuilderFactory factory, String feature, boolean enable)
154 179 {
155 180 try
... ... @@ -166,6 +191,7 @@ class FactoryHelper
166 191 {
167 192 factory.setFeature(feature, enable);
168 193 }
  194 + debug(debugCounter+" DocumentBuilderFactory "+feature+" "+enable);
169 195 }
170 196 catch (ParserConfigurationException pce)
171 197 {
... ... @@ -185,6 +211,7 @@ class FactoryHelper
185 211 {
186 212 factory.setFeature(feature, enable);
187 213 }
  214 + debug(debugCounter+" SAXParserFactory "+feature+" "+enable);
188 215 }
189 216 catch (ParserConfigurationException | SAXNotSupportedException | SAXNotRecognizedException e)
190 217 {
... ... @@ -192,6 +219,16 @@ class FactoryHelper
192 219 }
193 220 }
194 221  
  222 + public void debugNewParser(DocumentBuilder parser)
  223 + {
  224 + debugStack("New DocumentBuilder", 3, STACK_DEPTH);
  225 + }
  226 +
  227 + public void debugNewParser(SAXParser parser)
  228 + {
  229 + debugStack("New SAXParser", 3, STACK_DEPTH);
  230 + }
  231 +
195 232 private void logConfigurationFailure(String factoryName, String feature, Exception e)
196 233 {
197 234 if (logger.isWarnEnabled())
... ... @@ -228,10 +265,11 @@ class FactoryHelper
228 265 try
229 266 {
230 267 value = getSystemProperty(extendedPropertyName);
  268 + debugPropertyFrom(propertyName, value, "-D"+extendedPropertyName);
231 269 }
232 270 catch (SecurityException e)
233 271 {
234   - logger.debug("Error reading system property:"+extendedPropertyName, e);
  272 + debug(debugCounter+" Error reading system property:"+extendedPropertyName, e);
235 273 }
236 274  
237 275 // Look for values in $JAVA_HOME/jre/lib/<factoryName>.properties.
... ... @@ -245,10 +283,11 @@ class FactoryHelper
245 283 {
246 284 URL url = file.toURI().toURL();
247 285 value = getProperty(url, propertyName);
  286 + debugPropertyFrom(propertyName, value, file);
248 287 }
249 288 catch (MalformedURLException e)
250 289 {
251   - logger.debug("Error creating URL for:"+file, e);
  290 + debug(debugCounter+" Error creating URL for:"+file, e);
252 291 }
253 292 }
254 293 }
... ... @@ -259,6 +298,7 @@ class FactoryHelper
259 298 String resourceName = "META-INF/services/" + factoryName+".properties";
260 299 URL url = getResource(null, resourceName);
261 300 value = getProperty(url, propertyName);
  301 + debugPropertyFrom(propertyName, value, resourceName);
262 302 }
263 303  
264 304 // Add features to a new List
... ... @@ -278,6 +318,16 @@ class FactoryHelper
278 318 return features;
279 319 }
280 320  
  321 + private void debugPropertyFrom(String propertyName, String value, Object source) {
  322 + if (logger.isDebugEnabled())
  323 + {
  324 + if (value != null)
  325 + {
  326 + debug(debugCounter+" "+propertyName+" "+value+" loaded from "+ source);
  327 + }
  328 + }
  329 + }
  330 +
281 331 String getJavaHome()
282 332 {
283 333 return System.getProperty("java.home");
... ... @@ -319,7 +369,7 @@ class FactoryHelper
319 369 }
320 370 catch (IOException e)
321 371 {
322   - logger.debug("Error reading :"+url, e);
  372 + debug(debugCounter+" Error reading :"+url, e);
323 373 }
324 374 finally
325 375 {
... ... @@ -348,4 +398,16 @@ class FactoryHelper
348 398 }
349 399 return properties;
350 400 }
  401 +
  402 + private void debug(String message)
  403 + {
  404 + logger.debug(message);
  405 + // System.out.println(message);
  406 + }
  407 +
  408 + private void debug(String message, Exception e)
  409 + {
  410 + logger.debug(message, e);
  411 + // System.out.println(message);
  412 + }
351 413 }
... ...
src/main/java/org/alfresco/xmlfactory/SAXParserFactoryXercesImpl.java
... ... @@ -20,6 +20,8 @@ package org.alfresco.xmlfactory;
20 20  
21 21 import org.apache.xerces.jaxp.SAXParserFactoryImpl;
22 22  
  23 +import javax.xml.parsers.ParserConfigurationException;
  24 +import javax.xml.parsers.SAXParser;
23 25 import javax.xml.parsers.SAXParserFactory;
24 26 import java.util.List;
25 27  
... ... @@ -38,4 +40,12 @@ public class SAXParserFactoryXercesImpl extends SAXParserFactoryImpl
38 40 {
39 41 factoryHelper.configureFactory(this, FEATURES_TO_ENABLE, FEATURES_TO_DISABLE, WHITE_LIST_CALLERS);
40 42 }
  43 +
  44 + @Override
  45 + public SAXParser newSAXParser() throws ParserConfigurationException
  46 + {
  47 + SAXParser saxParser = super.newSAXParser();
  48 + factoryHelper.debugNewParser(saxParser);
  49 + return saxParser;
  50 + }
41 51 }
... ...