From 345a8534ff39cc9550cbacabe2b3fffe20293508 Mon Sep 17 00:00:00 2001
From: Thomas Lenz <thomas.lenz@egiz.gv.at>
Date: Thu, 22 Jun 2017 14:26:15 +0200
Subject: implement a workaround to fix XXE and SSRF problems in an old
 XMLStreamParser implementation of a third party library

---
 .../filter/MoccaHttpServletRequestWrapper.java     |  72 ++++++++++++
 .../egiz/bku/online/filter/StalSecurityFilter.java | 122 +++++++++++++++++++++
 .../at/gv/egiz/mocca/id/DataURLServerServlet.java  |  13 ++-
 BKUOnline/src/main/webapp/WEB-INF/web.xml          |   8 ++
 .../at/gv/egiz/bku/slxhtml/SLXHTMLValidator.java   |  11 ++
 .../egiz/bku/binding/HTTPBindingProcessorImpl.java |   3 +-
 .../egiz/bku/slcommands/SLCommandFactoryTest.java  |   5 +-
 utils/pom.xml                                      |   6 +
 .../java/at/gv/egiz/slbinding/SLUnmarshaller.java  |  70 ++++++++++--
 .../at/gv/egiz/slbinding/UnmarshallCXSRTest.java   |  26 ++++-
 .../CreateXMLSignatureResponse_with_Attacke.xml    |  25 +++++
 11 files changed, 349 insertions(+), 12 deletions(-)
 create mode 100644 BKUOnline/src/main/java/at/gv/egiz/bku/online/filter/MoccaHttpServletRequestWrapper.java
 create mode 100644 BKUOnline/src/main/java/at/gv/egiz/bku/online/filter/StalSecurityFilter.java
 create mode 100644 utils/src/test/resources/at/gv/egiz/slbinding/CreateXMLSignatureResponse_with_Attacke.xml

diff --git a/BKUOnline/src/main/java/at/gv/egiz/bku/online/filter/MoccaHttpServletRequestWrapper.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/filter/MoccaHttpServletRequestWrapper.java
new file mode 100644
index 00000000..8901969d
--- /dev/null
+++ b/BKUOnline/src/main/java/at/gv/egiz/bku/online/filter/MoccaHttpServletRequestWrapper.java
@@ -0,0 +1,72 @@
+package at.gv.egiz.bku.online.filter;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+import at.gv.egiz.bku.binding.HttpUtil;
+
+
+public class MoccaHttpServletRequestWrapper extends HttpServletRequestWrapper {
+
+	private static Logger log = LoggerFactory.getLogger(MoccaHttpServletRequestWrapper.class);
+	
+	private final byte[] body;
+	private final String charset;
+	
+	public MoccaHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
+		super(request);
+				
+		String ct = request.getHeader(HttpUtil.HTTP_HEADER_CONTENT_TYPE.toLowerCase());
+		charset = HttpUtil.getCharset(ct, true);
+		
+		byte[] result = null;
+		try {
+			 result = IOUtils.toByteArray(request.getReader(), charset);
+						
+		} catch (IOException e) {
+			log.error("Can not copy input stream!!!!!", e);
+			throw new IOException("Can not copy input stream!!!!!", e);
+			
+		} finally {
+			body = result;
+			
+		}
+	}
+	
+	public boolean isInputStreamAvailable() {
+		return (body != null && body.length > 0);
+		
+	}
+	
+	@Override
+	public BufferedReader getReader() throws IOException {
+		return new BufferedReader(new InputStreamReader(getInputStream(), charset));
+	    
+	}
+
+	@Override
+	public ServletInputStream getInputStream() throws IOException {
+		final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);
+		return new ServletInputStream() {
+
+			@Override
+			public int read() throws IOException {
+				return byteArrayInputStream.read();
+			}
+        
+		};
+					
+	}
+}
diff --git a/BKUOnline/src/main/java/at/gv/egiz/bku/online/filter/StalSecurityFilter.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/filter/StalSecurityFilter.java
new file mode 100644
index 00000000..0e98cb79
--- /dev/null
+++ b/BKUOnline/src/main/java/at/gv/egiz/bku/online/filter/StalSecurityFilter.java
@@ -0,0 +1,122 @@
+package at.gv.egiz.bku.online.filter;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLStreamException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
+
+
+public class StalSecurityFilter implements Filter {
+
+	private static Logger log = LoggerFactory.getLogger(StalSecurityFilter.class);
+	
+	@Override
+	public void init(FilterConfig filterConfig) throws ServletException {
+		log.info("Initialize STAL Service security filter");
+		
+	}
+
+	@Override
+	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+			throws IOException, ServletException {
+
+		if (request instanceof HttpServletRequest) {
+			try {
+				MoccaHttpServletRequestWrapper stalHttpReq = new MoccaHttpServletRequestWrapper((HttpServletRequest) request);		
+				
+				if (stalHttpReq.isInputStreamAvailable()) {
+					log.trace("Validate STAL request ... ");
+					validateStalRequest(stalHttpReq.getInputStream());
+					log.trace("Validate of STAL request completed");
+					
+				}
+			
+				chain.doFilter(stalHttpReq, response);
+				
+			} catch (XMLStreamException e) {
+				log.error("XML data validation FAILED with msg: " + e.getMessage(), e);
+				sendErrorToResponse(e, response);
+					
+			} catch (IOException e) {
+				log.error("Can not process InputStream from STAL request");
+				sendErrorToResponse(e, response);
+				
+			}				
+						
+		} else {
+			log.error("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+			log.warn("STAL request is processed WITHOUT security checks!!!!");
+			log.error("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+			chain.doFilter(request, response);
+			
+		}
+	}
+
+	@Override
+	public void destroy() {
+		// TODO Auto-generated method stub
+		
+	}
+
+	private void sendErrorToResponse(Exception e, ServletResponse response) throws IOException {
+		if (response instanceof HttpServletResponse) {
+			((HttpServletResponse)response).sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+			
+		} else
+			log.error("Can not response with http error message");
+		
+	}
+	
+	private void validateStalRequest(InputStream is) throws XMLStreamException, IOException {
+			
+		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+		
+		try {
+			dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
+			dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+			dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+			dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+						
+		} catch (ParserConfigurationException e) {
+			log.error("Can NOT set Xerces parser security features. -> XML parsing is possible insecure!!!! ", e);
+			
+		}
+    	    	        
+		try {        	
+			//validate input stream        	
+			dbf.newDocumentBuilder().parse(is);
+            		    		    		
+		} catch (SAXException e) {
+			log.error("XML data validation FAILED with msg: " + e.getMessage(), e);
+			throw new XMLStreamException("XML data validation FAILED with msg: " + e.getMessage(), e);
+
+		} catch (ParserConfigurationException e) {
+			log.error("XML data validation FAILED with msg: " + e.getMessage(), e);
+			throw new XMLStreamException("XML data validation FAILED with msg: " + e.getMessage(), e);
+    		
+		} catch (IOException e) {
+			log.error("XML data validation FAILED with msg: " + e.getMessage(), e);
+			throw new XMLStreamException("XML data validation FAILED with msg: " + e.getMessage(), e);
+    		
+		}
+		
+	}
+	
+}
diff --git a/BKUOnline/src/main/java/at/gv/egiz/mocca/id/DataURLServerServlet.java b/BKUOnline/src/main/java/at/gv/egiz/mocca/id/DataURLServerServlet.java
index 7dd2cd22..37889ae5 100644
--- a/BKUOnline/src/main/java/at/gv/egiz/mocca/id/DataURLServerServlet.java
+++ b/BKUOnline/src/main/java/at/gv/egiz/mocca/id/DataURLServerServlet.java
@@ -135,7 +135,6 @@ public class DataURLServerServlet extends HttpServlet {
         }
         
         SLUnmarshaller slUnmarshaller = new SLUnmarshaller();
-        
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
         dbf.setNamespaceAware(true);
         dbf.setSchema(slUnmarshaller.getSlSchema());
@@ -153,6 +152,18 @@ public class DataURLServerServlet extends HttpServlet {
                 "(see http://www.w3.org/TR/xmldsig-bestpractices/#be-aware-schema-normalization)", e);
         }
         
+        try {
+			dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
+			dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+			dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+			dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+						
+		} catch (ParserConfigurationException e) {
+			log.error("Can NOT set SAX parser security features. -> XML parsing is possible insecure!!!! ", e);
+			
+		}
+        
+        
         DocumentBuilder documentBuilder;
         try {
           documentBuilder = dbf.newDocumentBuilder();
diff --git a/BKUOnline/src/main/webapp/WEB-INF/web.xml b/BKUOnline/src/main/webapp/WEB-INF/web.xml
index 5033cc5e..5779fc97 100644
--- a/BKUOnline/src/main/webapp/WEB-INF/web.xml
+++ b/BKUOnline/src/main/webapp/WEB-INF/web.xml
@@ -175,6 +175,14 @@
 		<filter-name>RequestIdFilter</filter-name>
 		<filter-class>at.gv.egiz.bku.online.webapp.TransactionIdFilter</filter-class>
 	</filter>
+	<filter>
+		<filter-name>StalSecurityFilter</filter-name>
+		<filter-class>at.gv.egiz.bku.online.filter.StalSecurityFilter</filter-class>
+	</filter>
+	<filter-mapping>
+		<filter-name>StalSecurityFilter</filter-name>
+		<servlet-name>STALService</servlet-name>
+	</filter-mapping>
 	<filter-mapping>
 		<filter-name>RequestIdFilter</filter-name>
 		<servlet-name>HTTPSecurityLayerServlet</servlet-name>
diff --git a/BKUViewer/src/main/java/at/gv/egiz/bku/slxhtml/SLXHTMLValidator.java b/BKUViewer/src/main/java/at/gv/egiz/bku/slxhtml/SLXHTMLValidator.java
index fe48eefa..95d2b78c 100644
--- a/BKUViewer/src/main/java/at/gv/egiz/bku/slxhtml/SLXHTMLValidator.java
+++ b/BKUViewer/src/main/java/at/gv/egiz/bku/slxhtml/SLXHTMLValidator.java
@@ -139,6 +139,16 @@ public class SLXHTMLValidator implements at.gv.egiz.bku.viewer.Validator {
     spf.setValidating(true);
     spf.setXIncludeAware(false);
     
+    try {    	
+    	spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
+    	spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+    	spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+    	
+    } catch (Exception e) {
+    	log.error("Can NOT set SAX parser security features. -> XML parsing is possible insecure!!!! ", e);
+    	
+	}
+    
     SAXParser parser;
     try {
       parser = spf.newSAXParser();
@@ -150,6 +160,7 @@ public class SLXHTMLValidator implements at.gv.egiz.bku.viewer.Validator {
       throw new RuntimeException("Failed to create SLXHTML parser.", e);
     }
     
+       
     InputSource source;
     if (charset != null) {
       source = new InputSource(new InputStreamReader(is, charset));
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessorImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessorImpl.java
index 8891cce7..0c637d72 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessorImpl.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessorImpl.java
@@ -26,6 +26,7 @@ package at.gv.egiz.bku.binding;
 
 import iaik.utils.Base64InputStream;
 
+import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -737,7 +738,7 @@ public class HTTPBindingProcessorImpl extends AbstractBindingProcessor implement
 
 	protected void assignXMLRequest(InputStream is, String charset)
 			throws IOException, SLException {
-		Reader r = new InputStreamReader(is, charset);
+		Reader r = new InputStreamReader(new BufferedInputStream(is), charset);
 		StreamSource source = new StreamSource(r);
 		slCommand = slCommandFactory.createSLCommand(source);
 		log.info("XMLRequest={}. Created new command: {}.",
diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/SLCommandFactoryTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/SLCommandFactoryTest.java
index eda3e4e8..cfe5a130 100644
--- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/SLCommandFactoryTest.java
+++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/SLCommandFactoryTest.java
@@ -26,6 +26,7 @@ package at.gv.egiz.bku.slcommands;
 
 import static org.junit.Assert.assertTrue;
 
+import java.io.BufferedReader;
 import java.io.Reader;
 import java.io.StringReader;
 
@@ -83,10 +84,10 @@ public class SLCommandFactoryTest {
   
   @Test(expected=SLRequestException.class)
   public void createMalformedCommand() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException {
-    Reader requestReader = new StringReader(
+    Reader requestReader = new BufferedReader(new StringReader(
         "<NullOperationRequest xmlns=\"http://www.buergerkarte.at/namespaces/securitylayer/1.2#\">" +
           "missplacedContent" +
-        "</NullOperationRequest>");
+        "</NullOperationRequest>"));
     StreamSource source = new StreamSource(requestReader);
     
     factory.createSLCommand(source);
diff --git a/utils/pom.xml b/utils/pom.xml
index 5a41e98e..95d7f655 100644
--- a/utils/pom.xml
+++ b/utils/pom.xml
@@ -37,6 +37,12 @@
       <groupId>com.sun.xml.stream</groupId>
       <version>1.0.2</version>
     </dependency>
+    
+    <dependency>
+    	<groupId>commons-io</groupId>
+    	<artifactId>commons-io</artifactId>
+    	<version>2.5</version>
+	</dependency>
 	
   </dependencies>
 </project>
diff --git a/utils/src/main/java/at/gv/egiz/slbinding/SLUnmarshaller.java b/utils/src/main/java/at/gv/egiz/slbinding/SLUnmarshaller.java
index de1b2ddf..2d1808c8 100644
--- a/utils/src/main/java/at/gv/egiz/slbinding/SLUnmarshaller.java
+++ b/utils/src/main/java/at/gv/egiz/slbinding/SLUnmarshaller.java
@@ -25,7 +25,10 @@
 
 package at.gv.egiz.slbinding;
 
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
 import java.net.URL;
 import java.util.Arrays;
 import java.util.Collection;
@@ -38,6 +41,8 @@ import javax.xml.bind.JAXBException;
 import javax.xml.bind.UnmarshalException;
 import javax.xml.bind.Unmarshaller;
 import javax.xml.bind.ValidationEvent;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.stream.XMLEventReader;
 import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamException;
@@ -46,6 +51,7 @@ import javax.xml.transform.stream.StreamSource;
 import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
 
+import org.apache.commons.io.IOUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.xml.sax.SAXException;
@@ -237,17 +243,67 @@ public class SLUnmarshaller {
 public Object unmarshal(StreamSource source) throws XMLStreamException, JAXBException {
     
     ReportingValidationEventHandler validationEventHandler = new ReportingValidationEventHandler();
-//    System.setProperty("javax.xml.stream.XMLInputFactory", "com.sun.xml.stream.ZephyrParserFactory");
-//    System.setProperty("com.sun.xml.stream.ZephyrParserFactory", "com.sun.xml.stream.ZephyrParserFactory");
-//    XMLInputFactory inputFactory = XMLInputFactory.newInstance("com.sun.xml.stream.ZephyrParserFactory", null);
-    
+    Reader inputReader = source.getReader();
+        
+    if (inputReader instanceof InputStreamReader) {
+    	DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+    	
+    	try {
+			dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
+			dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+			dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+			dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+						
+		} catch (ParserConfigurationException e) {
+			log.error("Can NOT set Xerces parser security features. -> XML parsing is possible insecure!!!! ", e);
+			
+		}
+    	    	        
+        try {        	
+        	//create copy of input stream
+        	InputStreamReader isReader = (InputStreamReader) inputReader;
+        	String encoding = isReader.getEncoding();        	
+        	byte[] backup = IOUtils.toByteArray(isReader, encoding);
+
+        	//validate input stream        	
+        	dbf.newDocumentBuilder().parse(new ByteArrayInputStream(backup));
+        	    		
+    		//create new inputStreamReader for reak processing
+    		inputReader = new InputStreamReader(new ByteArrayInputStream(backup), encoding);
+    		
+    		
+    	} catch (SAXException e) {
+    		log.error("XML data validation FAILED with msg: " + e.getMessage(), e);
+    		throw new XMLStreamException("XML data validation FAILED with msg: " + e.getMessage(), e);
+
+
+    	} catch (ParserConfigurationException e) {
+    		log.error("XML data validation FAILED with msg: " + e.getMessage(), e);
+    		throw new XMLStreamException("XML data validation FAILED with msg: " + e.getMessage(), e);
+    		
+    	} catch (IOException e) {
+    		log.error("XML data validation FAILED with msg: " + e.getMessage(), e);
+    		throw new XMLStreamException("XML data validation FAILED with msg: " + e.getMessage(), e);
+    		
+		}
+    	    	
+    } else {
+    	log.error("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+    	log.error("Reader is not of type InputStreamReader -> can not make a copy of the InputStream --> extended XML validation is not possible!!! ");
+    	log.error("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+    	
+    }
+        
+    //parse XML with original functionality
     XMLInputFactory inputFactory = XMLInputFactory.newInstance();
     
     //disallow DTD and external entities
     inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
     inputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", false);
     
-    XMLEventReader eventReader = inputFactory.createXMLEventReader(source.getReader());
+    
+    
+    XMLEventReader eventReader = inputFactory.createXMLEventReader(inputReader);
     RedirectEventFilter redirectEventFilter = new RedirectEventFilter();
     XMLEventReader filteredReader = inputFactory.createFilteredReader(eventReader, redirectEventFilter);
 
@@ -255,8 +311,8 @@ public Object unmarshal(StreamSource source) throws XMLStreamException, JAXBExce
     unmarshaller.setEventHandler(validationEventHandler);
 
     unmarshaller.setListener(new RedirectUnmarshallerListener(redirectEventFilter));
-    unmarshaller.setSchema(slSchema);
-
+    unmarshaller.setSchema(slSchema);    
+    
     Object object;
     try {
       log.trace("Before unmarshal().");
diff --git a/utils/src/test/java/at/gv/egiz/slbinding/UnmarshallCXSRTest.java b/utils/src/test/java/at/gv/egiz/slbinding/UnmarshallCXSRTest.java
index 99c11cbe..62a8d622 100644
--- a/utils/src/test/java/at/gv/egiz/slbinding/UnmarshallCXSRTest.java
+++ b/utils/src/test/java/at/gv/egiz/slbinding/UnmarshallCXSRTest.java
@@ -25,6 +25,7 @@
 
 package at.gv.egiz.slbinding;
 
+import java.io.BufferedInputStream;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 
@@ -49,7 +50,7 @@ public class UnmarshallCXSRTest {
     assertNotNull(s);
     
     SLUnmarshaller unmarshaller = new SLUnmarshaller();
-    Object object = unmarshaller.unmarshal(new StreamSource(new InputStreamReader(s)));
+    Object object = unmarshaller.unmarshal(new StreamSource(new InputStreamReader(new BufferedInputStream(s))));
 
     assertTrue(object.getClass().getName(), object instanceof JAXBElement<?>);
 
@@ -59,4 +60,27 @@ public class UnmarshallCXSRTest {
     
   }
   
+  @Test
+  public void testUnmarshalCreateXMLSignatureResponseWithDocTypeXXEOrSSRF() throws JAXBException {
+    
+    ClassLoader cl = UnmarshallCXSRTest.class.getClassLoader();
+    InputStream s = cl.getResourceAsStream("at/gv/egiz/slbinding/CreateXMLSignatureResponse_with_Attacke.xml");
+    
+    assertNotNull(s);
+    
+    SLUnmarshaller unmarshaller = new SLUnmarshaller();
+    Object object;
+	try {
+		object = unmarshaller.unmarshal(new StreamSource(new InputStreamReader(new BufferedInputStream(s))));
+		
+	    assertTrue(object.getClass().getName(), object instanceof JAXBElement<?>);
+	    Object value = ((JAXBElement<?>) object).getValue();	    
+	    assertFalse(value.getClass().getName(), value instanceof CreateXMLSignatureResponseType);
+		
+	} catch (XMLStreamException e) {
+		assertTrue(e.getClass().getName(), e instanceof XMLStreamException);
+		
+	}    
+  }
+  
 }
diff --git a/utils/src/test/resources/at/gv/egiz/slbinding/CreateXMLSignatureResponse_with_Attacke.xml b/utils/src/test/resources/at/gv/egiz/slbinding/CreateXMLSignatureResponse_with_Attacke.xml
new file mode 100644
index 00000000..8684d860
--- /dev/null
+++ b/utils/src/test/resources/at/gv/egiz/slbinding/CreateXMLSignatureResponse_with_Attacke.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE r [
+    <!ELEMENT r ANY >
+    <!ENTITY % sp SYSTEM "http://update.egiz.gv.at/test.dtd">
+    %sp;
+    %param1;
+    %exfil;
+]><sl:CreateXMLSignatureResponse xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Signature Id="Signature-e5381f3d-1" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:SignedInfo Id="SignedInfo-e5381f3d-1"><dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><dsig:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"/><dsig:Reference Id="Reference-e5381f3d-1" URI="test.txt"><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><dsig:DigestValue>7Dp/5KcvUfCnkohkOOzvFaeAIRc=</dsig:DigestValue></dsig:Reference><dsig:Reference Id="Reference-e5381f3d-2" Type="http://uri.etsi.org/01903/v1.1.1#SignedProperties" URI="#xmlns(xades=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('Object-e5381f3d-1')/child::xades:QualifyingProperties/child::xades:SignedProperties)"><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><dsig:DigestValue>fCbFrz0xI0wiN+PPn4leURvfdIo=</dsig:DigestValue></dsig:Reference></dsig:SignedInfo><dsig:SignatureValue Id="SignatureValue-e5381f3d-1">Zozx+mW/lHUO8q02DBK3Aud/sSpVdWGjfBScZDBjuzLyQyrRlXH2xo3lij5/xJa0</dsig:SignatureValue><dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>MIIDdzCCAd+gAwIBAgIRMqGxalf5fUuhqgSjs+IArBMwDQYJKoZIhvcNAQEFBQAw
+TTESMBAGA1UEAwwJVlNpZyBDQSAyMSowKAYDVQQKDCFIYXVwdHZlcmJhbmQgw7Zz
+dGVyci4gU296aWFsdmVycy4xCzAJBgNVBAYTAkFUMB4XDTA2MTEwODA1MjYxN1oX
+DTExMTEwODA1MjYxN1owYTEXMBUGA1UEAwwOTWFydGluIENlbnRuZXIxKjAoBgNV
+BAoMIUhhdXB0dmVyYmFuZCDDtnN0ZXJyLiBTb3ppYWx2ZXJzLjENMAsGA1UECwwE
+VlNpZzELMAkGA1UEBhMCQVQwSTATBgcqhkjOPQIBBggqhkjOPQMBAQMyAASZohyZ
+R1JDH+sANEROtE5LQFFepjfo5Xk7eRtrpnfa1MFhEOfYXxElEInOVFU049+jgZgw
+gZUwEwYDVR0jBAwwCoAISGl1XDyvIyowEQYDVR0OBAoECESRXVYYhLE8MA4GA1Ud
+DwEB/wQEAwIGwDAWBgNVHSAEDzANMAsGCSooAAoBBAFmADBDBggrBgEFBQcBAQQ3
+MDUwMwYIKwYBBQUHMAGGJ2h0dHA6Ly9vY3NwLmVjYXJkLnNvemlhbHZlcnNpY2hl
+cnVuZy5hdDANBgkqhkiG9w0BAQUFAAOCAYEAPTDL/MLfmNw0VcHqny3lNi30hL8z
+OtyiwQRo7QFA98Pm+8WPyQjyK0UVIej+NZVIVSU7WdYWVuu+au8bd3B10WBikLMl
+QfEWqYDHGp+bfB4GB4WVeS78tNmXaacXjzLqae/KLALRn/dVBN/acf3C+Ey3kSYw
+/96J+qgbaowlT18OvUTs1ABHgut1x31hLIgTj0R5nzfOOUXXnUN+rWm5SuaNMTHW
+NMNhM6Y4jfACOsudmboeIZfgrmbDtCa2lLU95Mct2dcbBsnMRFUYoZc+9eEI/xCH
+JdzFZp1DAyqzb6Y84YUr+QDCxJT5BVdU0zTI73t0ls64556ifsfq/2sixHeQgMSM
+z/qQfPUC9so32sDPNHHNbKVYx9m0VpPwekWXBEVJWFffQbPe55deZ+uVFLOG4y0G
+c+o3eXV2Vs9te1OoA+KRow8kjL7iil06DNOddeDQVPj7zqRQtoLKMLTJflfZp5pd
+UPEZNM5Pw92T501vzHO9JNv5f/Wp3PTskBNJ</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo><dsig:Object Id="Object-e5381f3d-1"><xades:QualifyingProperties xmlns:xades="http://uri.etsi.org/01903/v1.1.1#" Target="#Signature-e5381f3d-1" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#"><xades:SignedProperties Id="SignedProperties-e5381f3d-1"><xades:SignedSignatureProperties><xades:SigningTime>2010-04-20T06:08:36Z</xades:SigningTime><xades:SigningCertificate><xades:Cert><xades:CertDigest><xades:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><xades:DigestValue>GF2imE3FjjqwM8BH0RY+VjtiAI8=</xades:DigestValue></xades:CertDigest><xades:IssuerSerial><dsig:X509IssuerName>C=AT,O=Hauptverband österr. Sozialvers.,CN=VSig CA 2</dsig:X509IssuerName><dsig:X509SerialNumber>17229045246817736659347185373920056355859</dsig:X509SerialNumber></xades:IssuerSerial></xades:Cert></xades:SigningCertificate><xades:SignaturePolicyIdentifier><xades:SignaturePolicyImplied/></xades:SignaturePolicyIdentifier></xades:SignedSignatureProperties><xades:SignedDataObjectProperties><xades:DataObjectFormat ObjectReference="#Reference-e5381f3d-1"><xades:MimeType>text/plain</xades:MimeType></xades:DataObjectFormat></xades:SignedDataObjectProperties></xades:SignedProperties></xades:QualifyingProperties></dsig:Object></dsig:Signature></sl:CreateXMLSignatureResponse>
\ No newline at end of file
-- 
cgit v1.2.3


From d840a372f84518c4026efd3d463cfcffac930e46 Mon Sep 17 00:00:00 2001
From: Thomas Lenz <thomas.lenz@egiz.gv.at>
Date: Thu, 22 Jun 2017 14:56:15 +0200
Subject: update jUnit test do validate XXE prevention in Signed data viewer

---
 .../java/at/gv/egiz/bku/slxhtml/ValidatorTest.java | 22 ++++++++++++++++++++++
 .../gv/egiz/bku/slxhtml/zugang_with_DocType.xhtml  | 21 +++++++++++++++++++++
 2 files changed, 43 insertions(+)
 create mode 100644 BKUViewer/src/test/resources/at/gv/egiz/bku/slxhtml/zugang_with_DocType.xhtml

diff --git a/BKUViewer/src/test/java/at/gv/egiz/bku/slxhtml/ValidatorTest.java b/BKUViewer/src/test/java/at/gv/egiz/bku/slxhtml/ValidatorTest.java
index 1dd8c45f..d51b52eb 100644
--- a/BKUViewer/src/test/java/at/gv/egiz/bku/slxhtml/ValidatorTest.java
+++ b/BKUViewer/src/test/java/at/gv/egiz/bku/slxhtml/ValidatorTest.java
@@ -71,4 +71,26 @@ public class ValidatorTest {
     
   }
   
+  @Test
+  public void testValidateWithDocType() throws ValidationException {
+    
+    String slxhtmlFile = "at/gv/egiz/bku/slxhtml/zugang_with_DocType.xhtml";
+    
+    Validator validator = ValidatorFactory.newValidator("application/xhtml+xml");
+
+    ClassLoader cl = ValidatorTest.class.getClassLoader();
+    InputStream slxhtml = cl.getResourceAsStream(slxhtmlFile);
+    long t0 = System.currentTimeMillis();
+    try {
+      validator.validate(slxhtml, null);
+      
+    } catch (ValidationException e) {
+      e.printStackTrace();
+      throw e;
+    }
+    long t1 = System.currentTimeMillis();
+    log.info("Validated SLXHTML file '{}' in {}ms.", slxhtmlFile, t1 - t0);
+    
+  }
+  
 }
diff --git a/BKUViewer/src/test/resources/at/gv/egiz/bku/slxhtml/zugang_with_DocType.xhtml b/BKUViewer/src/test/resources/at/gv/egiz/bku/slxhtml/zugang_with_DocType.xhtml
new file mode 100644
index 00000000..7417897f
--- /dev/null
+++ b/BKUViewer/src/test/resources/at/gv/egiz/bku/slxhtml/zugang_with_DocType.xhtml
@@ -0,0 +1,21 @@
+<!DOCTYPE lolz [
+	<!ELEMENT foo ANY >
+  <!ENTITY xxe SYSTEM "file:///etc/testtesttst" >
+]>
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>&xxe;Signatur der Anmeldedaten</title>
+    <style media="screen" type="text/css">.boldstyle { font-weight: bold; } .italicstyle { font-style: italic; } .annotationstyle { font-size: small; }</style>
+  </head>
+  <body>
+    <h1>Signatur der Anmeldedaten</h1>
+    <p></p>
+    <h4>Mit meiner elektronischen Signatur beantrage ich, <span class="boldstyle">Horst Rotzstopper</span>, geboren am 12.12.1985, den Zugang zur gesicherten Anwendung.</h4>
+    <p></p>
+    <h4>Datum und Uhrzeit: 07.11.2008, 14:04:18</h4>
+    <h4>wbPK(*): LTpz8VYzns2jrx0J8Gm/R/nAhxA=</h4>
+    <p></p>
+    <hr></hr>
+    <div class="annotationstyle">(*) wbPK: Das <span class="italicstyle">wirtschaftsbereichsspezifische Personenkennzeichen</span> wird aus den jeweiligen Stammzahlen des Bürgers und des Wirtschaftsunternehmens berechnet und ermöglicht eine eindeutige Zuordnung des Bürgers zum		Wirtschaftsunternehmen.</div>
+  </body>
+</html>
\ No newline at end of file
-- 
cgit v1.2.3


From 0603c0fbdfe028113431c65590b6e7e28929f6f6 Mon Sep 17 00:00:00 2001
From: Thomas Lenz <thomas.lenz@egiz.gv.at>
Date: Fri, 23 Jun 2017 06:50:14 +0200
Subject: some small refactoring and code documentation

---
 .../filter/MoccaHttpServletRequestWrapper.java     |  1 -
 .../egiz/bku/online/filter/StalSecurityFilter.java | 48 +------------
 .../at/gv/egiz/mocca/id/DataURLServerServlet.java  | 16 ++---
 .../at/gv/egiz/bku/slxhtml/SLXHTMLValidator.java   |  3 +
 utils/src/main/java/at/gv/egiz/dom/DOMUtils.java   | 78 +++++++++++++++++++++-
 .../java/at/gv/egiz/slbinding/SLUnmarshaller.java  | 52 +++++++--------
 .../at/gv/egiz/slbinding/UnmarshallCXSRTest.java   |  6 ++
 7 files changed, 114 insertions(+), 90 deletions(-)

diff --git a/BKUOnline/src/main/java/at/gv/egiz/bku/online/filter/MoccaHttpServletRequestWrapper.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/filter/MoccaHttpServletRequestWrapper.java
index 8901969d..d01f8128 100644
--- a/BKUOnline/src/main/java/at/gv/egiz/bku/online/filter/MoccaHttpServletRequestWrapper.java
+++ b/BKUOnline/src/main/java/at/gv/egiz/bku/online/filter/MoccaHttpServletRequestWrapper.java
@@ -5,7 +5,6 @@ import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
 
-import javax.servlet.ReadListener;
 import javax.servlet.ServletInputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
diff --git a/BKUOnline/src/main/java/at/gv/egiz/bku/online/filter/StalSecurityFilter.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/filter/StalSecurityFilter.java
index 0e98cb79..356401b6 100644
--- a/BKUOnline/src/main/java/at/gv/egiz/bku/online/filter/StalSecurityFilter.java
+++ b/BKUOnline/src/main/java/at/gv/egiz/bku/online/filter/StalSecurityFilter.java
@@ -1,26 +1,20 @@
 package at.gv.egiz.bku.online.filter;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
 import javax.servlet.FilterConfig;
 import javax.servlet.ServletException;
-import javax.servlet.ServletInputStream;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.stream.XMLStreamException;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.xml.sax.SAXException;
+
+import at.gv.egiz.dom.DOMUtils;
 
 
 public class StalSecurityFilter implements Filter {
@@ -43,7 +37,7 @@ public class StalSecurityFilter implements Filter {
 				
 				if (stalHttpReq.isInputStreamAvailable()) {
 					log.trace("Validate STAL request ... ");
-					validateStalRequest(stalHttpReq.getInputStream());
+					DOMUtils.validateXMLAgainstXXEAndSSRFAttacks(stalHttpReq.getInputStream());
 					log.trace("Validate of STAL request completed");
 					
 				}
@@ -71,7 +65,6 @@ public class StalSecurityFilter implements Filter {
 
 	@Override
 	public void destroy() {
-		// TODO Auto-generated method stub
 		
 	}
 
@@ -83,40 +76,5 @@ public class StalSecurityFilter implements Filter {
 			log.error("Can not response with http error message");
 		
 	}
-	
-	private void validateStalRequest(InputStream is) throws XMLStreamException, IOException {
-			
-		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-		
-		try {
-			dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
-			dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
-			dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
-			dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
-						
-		} catch (ParserConfigurationException e) {
-			log.error("Can NOT set Xerces parser security features. -> XML parsing is possible insecure!!!! ", e);
-			
-		}
-    	    	        
-		try {        	
-			//validate input stream        	
-			dbf.newDocumentBuilder().parse(is);
-            		    		    		
-		} catch (SAXException e) {
-			log.error("XML data validation FAILED with msg: " + e.getMessage(), e);
-			throw new XMLStreamException("XML data validation FAILED with msg: " + e.getMessage(), e);
-
-		} catch (ParserConfigurationException e) {
-			log.error("XML data validation FAILED with msg: " + e.getMessage(), e);
-			throw new XMLStreamException("XML data validation FAILED with msg: " + e.getMessage(), e);
-    		
-		} catch (IOException e) {
-			log.error("XML data validation FAILED with msg: " + e.getMessage(), e);
-			throw new XMLStreamException("XML data validation FAILED with msg: " + e.getMessage(), e);
-    		
-		}
 		
-	}
-	
 }
diff --git a/BKUOnline/src/main/java/at/gv/egiz/mocca/id/DataURLServerServlet.java b/BKUOnline/src/main/java/at/gv/egiz/mocca/id/DataURLServerServlet.java
index 37889ae5..d34ead45 100644
--- a/BKUOnline/src/main/java/at/gv/egiz/mocca/id/DataURLServerServlet.java
+++ b/BKUOnline/src/main/java/at/gv/egiz/mocca/id/DataURLServerServlet.java
@@ -65,6 +65,7 @@ import at.gv.egiz.bku.slcommands.impl.SLCommandImpl;
 import at.gv.egiz.bku.slexceptions.SLCommandException;
 import at.gv.egiz.bku.utils.DebugInputStream;
 import at.gv.egiz.bku.utils.StreamUtil;
+import at.gv.egiz.dom.DOMUtils;
 import at.gv.egiz.org.apache.tomcat.util.http.AcceptLanguage;
 import at.gv.egiz.slbinding.SLUnmarshaller;
 
@@ -152,18 +153,9 @@ public class DataURLServerServlet extends HttpServlet {
                 "(see http://www.w3.org/TR/xmldsig-bestpractices/#be-aware-schema-normalization)", e);
         }
         
-        try {
-			dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
-			dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
-			dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
-			dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
-						
-		} catch (ParserConfigurationException e) {
-			log.error("Can NOT set SAX parser security features. -> XML parsing is possible insecure!!!! ", e);
-			
-		}
-        
-        
+        //set XML parser flags to prevent XXE, XEE and SSRF attacks
+        DOMUtils.setXMLParserFlagsAgainstXXEAndSSRFAttacks(dbf);
+                
         DocumentBuilder documentBuilder;
         try {
           documentBuilder = dbf.newDocumentBuilder();
diff --git a/BKUViewer/src/main/java/at/gv/egiz/bku/slxhtml/SLXHTMLValidator.java b/BKUViewer/src/main/java/at/gv/egiz/bku/slxhtml/SLXHTMLValidator.java
index 95d2b78c..6fea75cb 100644
--- a/BKUViewer/src/main/java/at/gv/egiz/bku/slxhtml/SLXHTMLValidator.java
+++ b/BKUViewer/src/main/java/at/gv/egiz/bku/slxhtml/SLXHTMLValidator.java
@@ -139,6 +139,9 @@ public class SLXHTMLValidator implements at.gv.egiz.bku.viewer.Validator {
     spf.setValidating(true);
     spf.setXIncludeAware(false);
     
+    /*
+     * Set parser features to disallow external entities and external dtd load operations
+     */
     try {    	
     	spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
     	spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
diff --git a/utils/src/main/java/at/gv/egiz/dom/DOMUtils.java b/utils/src/main/java/at/gv/egiz/dom/DOMUtils.java
index eae8f05e..2054021a 100644
--- a/utils/src/main/java/at/gv/egiz/dom/DOMUtils.java
+++ b/utils/src/main/java/at/gv/egiz/dom/DOMUtils.java
@@ -33,7 +33,8 @@ import java.io.StringWriter;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLStreamException;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
@@ -47,7 +48,8 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 import org.w3c.dom.Text;
 import org.w3c.dom.bootstrap.DOMImplementationRegistry;
-import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.xml.sax.SAXException;
 
 public final class DOMUtils {
 
@@ -160,6 +162,76 @@ public final class DOMUtils {
     
     base64OutputStream.close();
     return doc.createTextNode(outputStream.toString("ASCII"));
-  }
+  }
+  
+  /**
+   * Set XML parser features to {@link DocumentBuilderFactory} to prevent XXE, XEE and SSRF attacks
+   * <br>
+   * <br>
+   * These features are set by this method:
+   * <ul>
+   * 	<li>http://xml.org/sax/features/external-general-entities --> false</li>
+   * 	<li>http://xml.org/sax/features/external-parameter-entities --> false</li>
+   * 	<li>http://apache.org/xml/features/nonvalidating/load-external-dtd --> false</li>
+   * 	<li>http://apache.org/xml/features/disallow-doctype-decl --> true</li>
+   * </ul>
+   *  
+   * 
+   * @param dbf {@link DocumentBuilderFactory} on which the features should be registered
+   */
+  public static void setXMLParserFlagsAgainstXXEAndSSRFAttacks(DocumentBuilderFactory dbf) {
+	  try {
+			dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
+			dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+			dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+			dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+						
+		} catch (ParserConfigurationException e) {
+			log.error("Can NOT set Xerces parser security features. -> XML parsing is possible insecure!!!! ", e);
+			
+		}
+	  
+  }
+  
+  /**
+   * Parse an {@link InputStream} that contains a XML document into a {@link Document}
+   * This method set all features to prevent XXE, XEE and SSRF attacks
+   * 
+   * These features are set by this method:
+   * <ul>
+   * 	<li>http://xml.org/sax/features/external-general-entities --> false</li>
+   * 	<li>http://xml.org/sax/features/external-parameter-entities --> false</li>
+   * 	<li>http://apache.org/xml/features/nonvalidating/load-external-dtd --> false</li>
+   * 	<li>http://apache.org/xml/features/disallow-doctype-decl --> true</li>
+   * </ul>
+   * 
+   * @param is {@link InputStream} that contains a serialized XML document 
+   * @return Deserialized {@link Document} from input XML 
+   * @throws XMLStreamException XML parser has an error 
+   * @throws IOException 
+   */
+	public static Document validateXMLAgainstXXEAndSSRFAttacks(InputStream is) throws XMLStreamException, IOException {		
+		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();		
+		setXMLParserFlagsAgainstXXEAndSSRFAttacks(dbf);
+		    	    	        
+		try {        	
+			//validate input stream        	
+			return dbf.newDocumentBuilder().parse(is);
+            		    		    		
+		} catch (SAXException e) {
+			log.error("XML data validation FAILED with msg: " + e.getMessage(), e);
+			throw new XMLStreamException("XML data validation FAILED with msg: " + e.getMessage(), e);
+
+		} catch (ParserConfigurationException e) {
+			log.error("XML data validation FAILED with msg: " + e.getMessage(), e);
+			throw new XMLStreamException("XML data validation FAILED with msg: " + e.getMessage(), e);
+    		
+		} catch (IOException e) {
+			log.error("XML data validation FAILED with msg: " + e.getMessage(), e);
+			throw new XMLStreamException("XML data validation FAILED with msg: " + e.getMessage(), e);
+    		
+		}
+		
+	}
 
 }
diff --git a/utils/src/main/java/at/gv/egiz/slbinding/SLUnmarshaller.java b/utils/src/main/java/at/gv/egiz/slbinding/SLUnmarshaller.java
index 2d1808c8..489c36d8 100644
--- a/utils/src/main/java/at/gv/egiz/slbinding/SLUnmarshaller.java
+++ b/utils/src/main/java/at/gv/egiz/slbinding/SLUnmarshaller.java
@@ -57,6 +57,7 @@ import org.slf4j.LoggerFactory;
 import org.xml.sax.SAXException;
 
 import at.gv.egiz.bku.utils.ClasspathURLStreamHandler;
+import at.gv.egiz.dom.DOMUtils;
 import at.gv.egiz.validation.ReportingValidationEventHandler;
 
 public class SLUnmarshaller {
@@ -241,43 +242,28 @@ public class SLUnmarshaller {
    * @throws JAXBException
    */
 public Object unmarshal(StreamSource source) throws XMLStreamException, JAXBException {
+    Reader inputReader = source.getReader(); 
     
-    ReportingValidationEventHandler validationEventHandler = new ReportingValidationEventHandler();
-    Reader inputReader = source.getReader();
-        
-    if (inputReader instanceof InputStreamReader) {
-    	DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-    	
-    	try {
-			dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
-			dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
-			dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
-			dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
-						
-		} catch (ParserConfigurationException e) {
-			log.error("Can NOT set Xerces parser security features. -> XML parsing is possible insecure!!!! ", e);
-			
-		}
-    	    	        
+    /* Validate XML against XXE, XEE, and SSRF
+     * 
+     * This pre-validation step is required because com.sun.xml.stream.sjsxp-1.0.2 XML stream parser library does not 
+     * support all XML parser features to prevent these types of attacks  
+     */
+    if (inputReader instanceof InputStreamReader) {    	    	        
         try {        	
         	//create copy of input stream
         	InputStreamReader isReader = (InputStreamReader) inputReader;
         	String encoding = isReader.getEncoding();        	
         	byte[] backup = IOUtils.toByteArray(isReader, encoding);
 
-        	//validate input stream        	
-        	dbf.newDocumentBuilder().parse(new ByteArrayInputStream(backup));
+        	//validate input stream
+        	DOMUtils.validateXMLAgainstXXEAndSSRFAttacks(new ByteArrayInputStream(backup));
         	    		
     		//create new inputStreamReader for reak processing
     		inputReader = new InputStreamReader(new ByteArrayInputStream(backup), encoding);
     		
     		
-    	} catch (SAXException e) {
-    		log.error("XML data validation FAILED with msg: " + e.getMessage(), e);
-    		throw new XMLStreamException("XML data validation FAILED with msg: " + e.getMessage(), e);
-
-
-    	} catch (ParserConfigurationException e) {
+    	} catch (XMLStreamException e) {
     		log.error("XML data validation FAILED with msg: " + e.getMessage(), e);
     		throw new XMLStreamException("XML data validation FAILED with msg: " + e.getMessage(), e);
     		
@@ -294,20 +280,28 @@ public Object unmarshal(StreamSource source) throws XMLStreamException, JAXBExce
     	
     }
         
-    //parse XML with original functionality
+    /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+     * parse XML with original functionality
+     * 
+     * This code implements the the original mocca XML processing by using 
+     *  com.sun.xml.stream.sjsxp-1.0.2 XML stream parser library. Currently, this library is required to get full 
+     *  security-layer specific XML processing. However, there this lib does not fully support XXE, XEE and SSRF
+     *  prevention mechanisms (e.g.: XMLInputFactory.SUPPORT_DTD flag is not used)    
+     * 
+     * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+     */
     XMLInputFactory inputFactory = XMLInputFactory.newInstance();
     
     //disallow DTD and external entities
     inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
     inputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", false);
-    
-    
-    
+        
     XMLEventReader eventReader = inputFactory.createXMLEventReader(inputReader);
     RedirectEventFilter redirectEventFilter = new RedirectEventFilter();
     XMLEventReader filteredReader = inputFactory.createFilteredReader(eventReader, redirectEventFilter);
 
     Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+    ReportingValidationEventHandler validationEventHandler = new ReportingValidationEventHandler();
     unmarshaller.setEventHandler(validationEventHandler);
 
     unmarshaller.setListener(new RedirectUnmarshallerListener(redirectEventFilter));
diff --git a/utils/src/test/java/at/gv/egiz/slbinding/UnmarshallCXSRTest.java b/utils/src/test/java/at/gv/egiz/slbinding/UnmarshallCXSRTest.java
index 62a8d622..5f97be0f 100644
--- a/utils/src/test/java/at/gv/egiz/slbinding/UnmarshallCXSRTest.java
+++ b/utils/src/test/java/at/gv/egiz/slbinding/UnmarshallCXSRTest.java
@@ -77,6 +77,12 @@ public class UnmarshallCXSRTest {
 	    Object value = ((JAXBElement<?>) object).getValue();	    
 	    assertFalse(value.getClass().getName(), value instanceof CreateXMLSignatureResponseType);
 		
+	    /* If the parser has no exception and no CreateXMLSignatureResponseType than the test fails, because 
+	     * the tested XML document contains a CreateXMLSignatureResponseType and an XXE, SSRF attack vector.
+	     * Consequently, the parser result has to be an error
+	     */
+	    assertFalse(true);
+	    
 	} catch (XMLStreamException e) {
 		assertTrue(e.getClass().getName(), e instanceof XMLStreamException);
 		
-- 
cgit v1.2.3