Created
January 11, 2017 02:57
-
-
Save anonymous/1ea1da1375d31005e174f7e6df4037c1 to your computer and use it in GitHub Desktop.
files/xxe-4.0.2-2.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -Naur pysaml2/setup.py pysaml2.new/setup.py | |
--- pysaml2/setup.py 2015-12-06 00:46:33.000000000 -0600 | |
+++ pysaml2.new/setup.py 2017-01-10 20:31:43.387413477 -0600 | |
@@ -17,6 +17,7 @@ | |
'pytz', | |
'pyOpenSSL', | |
'python-dateutil', | |
+ 'defusedxml', | |
'six' | |
] | |
diff -Naur pysaml2/src/saml2/__init__.py pysaml2.new/src/saml2/__init__.py | |
--- pysaml2/src/saml2/__init__.py 2016-01-07 05:53:57.000000000 -0600 | |
+++ pysaml2.new/src/saml2/__init__.py 2017-01-10 20:34:04.171641116 -0600 | |
@@ -35,6 +35,7 @@ | |
import cElementTree as ElementTree | |
except ImportError: | |
from elementtree import ElementTree | |
+import defusedxml.ElementTree | |
root_logger = logging.getLogger(__name__) | |
root_logger.level = logging.NOTSET | |
@@ -86,7 +87,7 @@ | |
""" | |
if not isinstance(xml_string, six.binary_type): | |
xml_string = xml_string.encode('utf-8') | |
- tree = ElementTree.fromstring(xml_string) | |
+ tree = defusedxml.ElementTree.fromstring(xml_string) | |
return create_class_from_element_tree(target_class, tree) | |
@@ -268,7 +269,7 @@ | |
def extension_element_from_string(xml_string): | |
- element_tree = ElementTree.fromstring(xml_string) | |
+ element_tree = defusedxml.ElementTree.fromstring(xml_string) | |
return _extension_element_from_element_tree(element_tree) | |
diff -Naur pysaml2/src/saml2/pack.py pysaml2.new/src/saml2/pack.py | |
--- pysaml2/src/saml2/pack.py 2015-12-11 07:31:39.000000000 -0600 | |
+++ pysaml2.new/src/saml2/pack.py 2017-01-10 20:35:35.382435020 -0600 | |
@@ -37,6 +37,7 @@ | |
import cElementTree as ElementTree | |
except ImportError: | |
from elementtree import ElementTree | |
+import defusedxml.ElementTree | |
NAMESPACE = "http://schemas.xmlsoap.org/soap/envelope/" | |
FORM_SPEC = """<form method="post" action="%s"> | |
@@ -235,7 +236,7 @@ | |
:param text: The SOAP object as XML | |
:return: header parts and body as saml.samlbase instances | |
""" | |
- envelope = ElementTree.fromstring(text) | |
+ envelope = defusedxml.ElementTree.fromstring(text) | |
assert envelope.tag == '{%s}Envelope' % NAMESPACE | |
# print(len(envelope)) | |
diff -Naur pysaml2/src/saml2/soap.py pysaml2.new/src/saml2/soap.py | |
--- pysaml2/src/saml2/soap.py 2015-05-18 02:54:05.000000000 -0500 | |
+++ pysaml2.new/src/saml2/soap.py 2017-01-10 20:36:16.163808770 -0600 | |
@@ -19,6 +19,7 @@ | |
except ImportError: | |
#noinspection PyUnresolvedReferences | |
from elementtree import ElementTree | |
+import defusedxml.ElementTree | |
logger = logging.getLogger(__name__) | |
@@ -133,7 +134,7 @@ | |
:param expected_tags: What the tag of the SAML thingy is expected to be. | |
:return: SAML thingy as a string | |
""" | |
- envelope = ElementTree.fromstring(text) | |
+ envelope = defusedxml.ElementTree.fromstring(text) | |
# Make sure it's a SOAP message | |
assert envelope.tag == '{%s}Envelope' % soapenv.NAMESPACE | |
@@ -183,7 +184,7 @@ | |
:return: The body and headers as class instances | |
""" | |
try: | |
- envelope = ElementTree.fromstring(text) | |
+ envelope = defusedxml.ElementTree.fromstring(text) | |
except Exception as exc: | |
raise XmlParseError("%s" % exc) | |
@@ -209,7 +210,7 @@ | |
:return: dictionary with two keys "body"/"header" | |
""" | |
try: | |
- envelope = ElementTree.fromstring(text) | |
+ envelope = defusedxml.ElementTree.fromstring(text) | |
except Exception as exc: | |
raise XmlParseError("%s" % exc) | |
diff -Naur pysaml2/tests/test_03_saml2.py pysaml2.new/tests/test_03_saml2.py | |
--- pysaml2/tests/test_03_saml2.py 2015-06-06 02:15:20.000000000 -0500 | |
+++ pysaml2.new/tests/test_03_saml2.py 2017-01-10 20:38:32.541728380 -0600 | |
@@ -17,6 +17,7 @@ | |
import cElementTree as ElementTree | |
except ImportError: | |
from elementtree import ElementTree | |
+from defusedxml.common import EntitiesForbidden | |
ITEMS = { | |
NameID: ["""<?xml version="1.0" encoding="utf-8"?> | |
@@ -27,7 +28,7 @@ | |
</NameID> | |
""", """<?xml version="1.0" encoding="utf-8"?> | |
<NameID xmlns="urn:oasis:names:tc:SAML:2.0:assertion" | |
- SPNameQualifier="https://foo.example.com/sp" | |
+ SPNameQualifier="https://foo.example.com/sp" | |
Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">_1632879f09d08ea5ede2dc667cbed7e429ebc4335c</NameID> | |
""", """<?xml version="1.0" encoding="utf-8"?> | |
<NameID xmlns="urn:oasis:names:tc:SAML:2.0:assertion" | |
@@ -47,9 +48,9 @@ | |
SubjectConfirmationData: | |
"""<?xml version="1.0" encoding="utf-8"?> | |
<SubjectConfirmationData xmlns="urn:oasis:names:tc:SAML:2.0:assertion" | |
-InResponseTo="_1683146e27983964fbe7bf8f08961108d166a652e5" | |
-NotOnOrAfter="2010-02-18T13:52:13.959Z" | |
-NotBefore="2010-01-16T12:00:00Z" | |
+InResponseTo="_1683146e27983964fbe7bf8f08961108d166a652e5" | |
+NotOnOrAfter="2010-02-18T13:52:13.959Z" | |
+NotBefore="2010-01-16T12:00:00Z" | |
Recipient="http://192.168.0.10/saml/sp" />""", | |
SubjectConfirmation: | |
"""<?xml version="1.0" encoding="utf-8"?> | |
@@ -166,6 +167,19 @@ | |
assert kl == None | |
+def test_create_class_from_xml_string_xxe(): | |
+ xml = """<?xml version="1.0"?> | |
+ <!DOCTYPE lolz [ | |
+ <!ENTITY lol "lol"> | |
+ <!ELEMENT lolz (#PCDATA)> | |
+ <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> | |
+ ]> | |
+ <lolz>&lol1;</lolz> | |
+ """ | |
+ with raises(EntitiesForbidden) as err: | |
+ create_class_from_xml_string(NameID, xml) | |
+ | |
+ | |
def test_ee_1(): | |
ee = saml2.extension_element_from_string( | |
"""<?xml version='1.0' encoding='UTF-8'?><foo>bar</foo>""") | |
@@ -193,7 +207,7 @@ | |
def test_ee_3(): | |
ee = saml2.extension_element_from_string( | |
"""<?xml version='1.0' encoding='UTF-8'?> | |
- <foo xmlns="urn:mace:example.com:saml:ns" | |
+ <foo xmlns="urn:mace:example.com:saml:ns" | |
id="xyz">bar</foo>""") | |
assert ee != None | |
print(ee.__dict__) | |
@@ -454,6 +468,19 @@ | |
assert nid.text.strip() == "http://federationX.org" | |
+def test_ee_xxe(): | |
+ xml = """<?xml version="1.0"?> | |
+ <!DOCTYPE lolz [ | |
+ <!ENTITY lol "lol"> | |
+ <!ELEMENT lolz (#PCDATA)> | |
+ <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> | |
+ ]> | |
+ <lolz>&lol1;</lolz> | |
+ """ | |
+ with raises(EntitiesForbidden): | |
+ saml2.extension_element_from_string(xml) | |
+ | |
+ | |
def test_extension_element_loadd(): | |
ava = {'attributes': {}, | |
'tag': 'ExternalEntityAttributeAuthority', | |
diff -Naur pysaml2/tests/test_43_soap.py pysaml2.new/tests/test_43_soap.py | |
--- pysaml2/tests/test_43_soap.py 2013-04-28 09:38:07.000000000 -0500 | |
+++ pysaml2.new/tests/test_43_soap.py 2017-01-10 20:39:53.730364008 -0600 | |
@@ -12,16 +12,20 @@ | |
import cElementTree as ElementTree | |
except ImportError: | |
from elementtree import ElementTree | |
+from defusedxml.common import EntitiesForbidden | |
+ | |
+from pytest import raises | |
import saml2.samlp as samlp | |
from saml2.samlp import NAMESPACE as SAMLP_NAMESPACE | |
+from saml2 import soap | |
NAMESPACE = "http://schemas.xmlsoap.org/soap/envelope/" | |
example = """<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"> | |
<Body> | |
- <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" | |
- xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" | |
+ <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" | |
+ xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" | |
ID="_6c3a4f8b9c2d" Version="2.0" IssueInstant="2004-03-27T08:42:00Z"> | |
<saml:Issuer>https://www.example.com/SAML</saml:Issuer> | |
<Status> | |
@@ -55,7 +59,7 @@ | |
envelope.tag = '{%s}Envelope' % NAMESPACE | |
body = ElementTree.Element('') | |
body.tag = '{%s}Body' % NAMESPACE | |
- envelope.append(body) | |
+ envelope.append(body) | |
request = samlp.AuthnRequest() | |
request.become_child_element_of(body) | |
@@ -66,3 +70,42 @@ | |
assert len(body) == 1 | |
saml_part = body[0] | |
assert saml_part.tag == '{%s}AuthnRequest' % SAMLP_NAMESPACE | |
+ | |
+ | |
+def test_parse_soap_enveloped_saml_thingy_xxe(): | |
+ xml = """<?xml version="1.0"?> | |
+ <!DOCTYPE lolz [ | |
+ <!ENTITY lol "lol"> | |
+ <!ELEMENT lolz (#PCDATA)> | |
+ <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> | |
+ ]> | |
+ <lolz>&lol1;</lolz> | |
+ """ | |
+ with raises(EntitiesForbidden): | |
+ soap.parse_soap_enveloped_saml_thingy(xml, None) | |
+ | |
+ | |
+def test_class_instances_from_soap_enveloped_saml_thingies_xxe(): | |
+ xml = """<?xml version="1.0"?> | |
+ <!DOCTYPE lolz [ | |
+ <!ENTITY lol "lol"> | |
+ <!ELEMENT lolz (#PCDATA)> | |
+ <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> | |
+ ]> | |
+ <lolz>&lol1;</lolz> | |
+ """ | |
+ with raises(soap.XmlParseError): | |
+ soap.class_instances_from_soap_enveloped_saml_thingies(xml, None) | |
+ | |
+ | |
+def test_open_soap_envelope_xxe(): | |
+ xml = """<?xml version="1.0"?> | |
+ <!DOCTYPE lolz [ | |
+ <!ENTITY lol "lol"> | |
+ <!ELEMENT lolz (#PCDATA)> | |
+ <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> | |
+ ]> | |
+ <lolz>&lol1;</lolz> | |
+ """ | |
+ with raises(soap.XmlParseError): | |
+ soap.open_soap_envelope(xml) | |
diff -Naur pysaml2/tests/test_51_client.py pysaml2.new/tests/test_51_client.py | |
--- pysaml2/tests/test_51_client.py 2015-12-11 05:10:01.000000000 -0600 | |
+++ pysaml2.new/tests/test_51_client.py 2017-01-10 20:42:12.819280442 -0600 | |
@@ -5,6 +5,7 @@ | |
import uuid | |
import six | |
from six.moves.urllib.parse import parse_qs, urlencode, urlparse | |
+from pytest import raises | |
from saml2.cert import OpenSSLWrapper | |
from saml2.xmldsig import SIG_RSA_SHA256 | |
from saml2 import BINDING_HTTP_POST | |
@@ -21,6 +22,7 @@ | |
from saml2.authn_context import INTERNETPROTOCOLPASSWORD | |
from saml2.client import Saml2Client | |
from saml2.config import SPConfig | |
+from saml2.pack import parse_soap_enveloped_saml | |
from saml2.response import LogoutResponse | |
from saml2.saml import NAMEID_FORMAT_PERSISTENT, EncryptedAssertion, Advice | |
from saml2.saml import NAMEID_FORMAT_TRANSIENT | |
@@ -34,6 +36,8 @@ | |
from saml2.s_utils import factory | |
from saml2.time_util import in_a_while, a_while_ago | |
+from defusedxml.common import EntitiesForbidden | |
+ | |
from fakeIDP import FakeIDP | |
from fakeIDP import unpack_form | |
from pathutils import full_path | |
@@ -1445,6 +1449,18 @@ | |
'http://www.example.com/login' | |
assert ac.authn_context_class_ref.text == INTERNETPROTOCOLPASSWORD | |
+def test_parse_soap_enveloped_saml_xxe(): | |
+ xml = """<?xml version="1.0"?> | |
+ <!DOCTYPE lolz [ | |
+ <!ENTITY lol "lol"> | |
+ <!ELEMENT lolz (#PCDATA)> | |
+ <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> | |
+ ]> | |
+ <lolz>&lol1;</lolz> | |
+ """ | |
+ with raises(EntitiesForbidden): | |
+ parse_soap_enveloped_saml(xml, None) | |
+ | |
# if __name__ == "__main__": | |
# tc = TestClient() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment