mirror of
https://github.com/gentoo-mirror/gentoo.git
synced 2026-07-30 10:38:07 -07:00
dev-python/pysaml2: fix xxe in pysaml2
Package-Manager: portage-2.3.0
This commit is contained in:
305
dev-python/pysaml2/files/xxe-4.0.2.patch
Normal file
305
dev-python/pysaml2/files/xxe-4.0.2.patch
Normal file
@@ -0,0 +1,305 @@
|
||||
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()
|
||||
37
dev-python/pysaml2/pysaml2-4.0.2-r1.ebuild
Normal file
37
dev-python/pysaml2/pysaml2-4.0.2-r1.ebuild
Normal file
@@ -0,0 +1,37 @@
|
||||
# Copyright 1999-2017 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Id$
|
||||
|
||||
EAPI=6
|
||||
PYTHON_COMPAT=( python2_7 python3_4 python3_5 )
|
||||
|
||||
inherit distutils-r1
|
||||
|
||||
DESCRIPTION="Python implementation of SAML Version 2 to be used in a WSGI environment"
|
||||
HOMEPAGE="https://github.com/rohe/pysaml2"
|
||||
SRC_URI="mirror://pypi/${PN:0:1}/${PN}/${P}.tar.gz"
|
||||
|
||||
LICENSE="Apache-2.0"
|
||||
SLOT="0"
|
||||
KEYWORDS="~amd64 ~arm64 ~x86"
|
||||
IUSE=""
|
||||
|
||||
PATCHES=( "${FILESDIR}/xxe-4.0.2.patch" )
|
||||
|
||||
DEPEND="
|
||||
dev-python/setuptools[${PYTHON_USEDEP}]
|
||||
"
|
||||
RDEPEND="
|
||||
dev-python/decorator[${PYTHON_USEDEP}]
|
||||
>=dev-python/requests-1.0.0[${PYTHON_USEDEP}]
|
||||
dev-python/future[${PYTHON_USEDEP}]
|
||||
dev-python/paste[${PYTHON_USEDEP}]
|
||||
dev-python/zope-interface[${PYTHON_USEDEP}]
|
||||
dev-python/repoze-who[${PYTHON_USEDEP}]
|
||||
>=dev-python/pycrypto-2.5[${PYTHON_USEDEP}]
|
||||
dev-python/pytz[${PYTHON_USEDEP}]
|
||||
dev-python/pyopenssl[${PYTHON_USEDEP}]
|
||||
dev-python/python-dateutil[${PYTHON_USEDEP}]
|
||||
dev-python/six[${PYTHON_USEDEP}]
|
||||
dev-python/defusedxml[${PYTHON_USEDEP}]
|
||||
"
|
||||
Reference in New Issue
Block a user