View | Details | Raw Unified | Return to bug 43393
Collapse All | Expand All

(-)file_not_specified_in_diff (-14 / +102 lines)
Line     Link Here 
This fixes XXE issues on anything where pysaml2 parses XML directly as part of
This fixes XXE issues on anything where pysaml2 parses XML directly as part of
1
issue #366. It doesn't address the xmlsec issues discussed on that ticket as
1
issue #366. It doesn't address the xmlsec issues discussed on that ticket as
2
they are out of reach of a direct fix and need the underlying library to fix
2
they are out of reach of a direct fix and need the underlying library to fix
3
this issue.
3
this issue.
4
.
4
.
5
The patch has been backported form the 3.0 branch to 2.0 by zigo@debian.org.
5
The patch has been backported form the 3.0 branch to 2.0 by zigo@debian.org.
6
-- python-pysaml2-2.0.0.orig/setup.py
6
++ python-pysaml2-2.0.0/setup.py
 Lines 46-52   install_requires = [ Link Here 
46
    'pycrypto',  # 'Crypto'
46
    'pycrypto',  # 'Crypto'
47
    'pytz',
47
    'pytz',
48
    'pyOpenSSL',
48
    'pyOpenSSL',
49
    'python-dateutil'
49
    'python-dateutil',
50
    'defusedxml'
50
]
51
]
51
52
52
tests_require = [
53
tests_require = [
53
-- python-pysaml2-2.0.0.orig/src/saml2/__init__.py
54
++ python-pysaml2-2.0.0/src/saml2/__init__.py
 Lines 33-38   except ImportError: Link Here 
33
        import cElementTree as ElementTree
33
        import cElementTree as ElementTree
34
    except ImportError:
34
    except ImportError:
35
        from elementtree import ElementTree
35
        from elementtree import ElementTree
36
import defusedxml.ElementTree
36
37
37
root_logger = logging.getLogger(__name__)
38
root_logger = logging.getLogger(__name__)
38
root_logger.level = logging.NOTSET
39
root_logger.level = logging.NOTSET
 Lines 82-88   def create_class_from_xml_string(target_ Link Here 
82
        the contents of the XML - or None if the root XML tag and namespace did 
83
        the contents of the XML - or None if the root XML tag and namespace did 
83
        not match those of the target class.
84
        not match those of the target class.
84
    """
85
    """
85
    tree = ElementTree.fromstring(xml_string)
86
    tree = defusedxml.ElementTree.fromstring(xml_string)
86
    return create_class_from_element_tree(target_class, tree)
87
    return create_class_from_element_tree(target_class, tree)
87
88
88
89
 Lines 264-270   class ExtensionElement(object): Link Here 
264
        
265
        
265
266
266
def extension_element_from_string(xml_string):
267
def extension_element_from_string(xml_string):
267
    element_tree = ElementTree.fromstring(xml_string)
268
    element_tree = defusedxml.ElementTree.fromstring(xml_string)
268
    return _extension_element_from_element_tree(element_tree)
269
    return _extension_element_from_element_tree(element_tree)
269
270
270
271
271
-- python-pysaml2-2.0.0.orig/src/saml2/pack.py
272
++ python-pysaml2-2.0.0/src/saml2/pack.py
 Lines 48-53   except ImportError: Link Here 
48
        import cElementTree as ElementTree
48
        import cElementTree as ElementTree
49
    except ImportError:
49
    except ImportError:
50
        from elementtree import ElementTree
50
        from elementtree import ElementTree
51
import defusedxml.ElementTree
51
52
52
NAMESPACE = "http://schemas.xmlsoap.org/soap/envelope/"
53
NAMESPACE = "http://schemas.xmlsoap.org/soap/envelope/"
53
FORM_SPEC = """<form method="post" action="%s">
54
FORM_SPEC = """<form method="post" action="%s">
 Lines 218-224   def parse_soap_enveloped_saml(text, body Link Here 
218
    :param text: The SOAP object as XML 
219
    :param text: The SOAP object as XML 
219
    :return: header parts and body as saml.samlbase instances
220
    :return: header parts and body as saml.samlbase instances
220
    """
221
    """
221
    envelope = ElementTree.fromstring(text)
222
    envelope = defusedxml.ElementTree.fromstring(text)
222
    assert envelope.tag == '{%s}Envelope' % NAMESPACE
223
    assert envelope.tag == '{%s}Envelope' % NAMESPACE
223
224
224
    #print len(envelope)
225
    #print len(envelope)
225
-- python-pysaml2-2.0.0.orig/src/saml2/soap.py
226
++ python-pysaml2-2.0.0/src/saml2/soap.py
 Lines 32-37   except ImportError: Link Here 
32
    except ImportError:
32
    except ImportError:
33
        #noinspection PyUnresolvedReferences
33
        #noinspection PyUnresolvedReferences
34
        from elementtree import ElementTree
34
        from elementtree import ElementTree
35
import defusedxml.ElementTree
35
36
36
37
37
logger = logging.getLogger(__name__)
38
logger = logging.getLogger(__name__)
 Lines 146-152   def parse_soap_enveloped_saml_thingy(tex Link Here 
146
    :param expected_tags: What the tag of the SAML thingy is expected to be.
147
    :param expected_tags: What the tag of the SAML thingy is expected to be.
147
    :return: SAML thingy as a string
148
    :return: SAML thingy as a string
148
    """
149
    """
149
    envelope = ElementTree.fromstring(text)
150
    envelope = defusedxml.ElementTree.fromstring(text)
150
151
151
    # Make sure it's a SOAP message
152
    # Make sure it's a SOAP message
152
    assert envelope.tag == '{%s}Envelope' % soapenv.NAMESPACE
153
    assert envelope.tag == '{%s}Envelope' % soapenv.NAMESPACE
 Lines 196-202   def class_instances_from_soap_enveloped_ Link Here 
196
    :return: The body and headers as class instances
197
    :return: The body and headers as class instances
197
    """
198
    """
198
    try:
199
    try:
199
        envelope = ElementTree.fromstring(text)
200
        envelope = defusedxml.ElementTree.fromstring(text)
200
    except Exception, exc:
201
    except Exception, exc:
201
        raise XmlParseError("%s" % exc)
202
        raise XmlParseError("%s" % exc)
202
203
 Lines 222-228   def open_soap_envelope(text): Link Here 
222
    :return: dictionary with two keys "body"/"header"
223
    :return: dictionary with two keys "body"/"header"
223
    """
224
    """
224
    try:
225
    try:
225
        envelope = ElementTree.fromstring(text)
226
        envelope = defusedxml.ElementTree.fromstring(text)
226
    except Exception, exc:
227
    except Exception, exc:
227
        raise XmlParseError("%s" % exc)
228
        raise XmlParseError("%s" % exc)
228
229
229
-- python-pysaml2-2.0.0.orig/tests/test_03_saml2.py
230
++ python-pysaml2-2.0.0/tests/test_03_saml2.py
 Lines 17-22   except ImportError: Link Here 
17
        import cElementTree as ElementTree
17
        import cElementTree as ElementTree
18
    except ImportError:
18
    except ImportError:
19
        from elementtree import ElementTree
19
        from elementtree import ElementTree
20
from defusedxml.common import EntitiesForbidden
20
21
21
ITEMS = {
22
ITEMS = {
22
    NameID: ["""<?xml version="1.0" encoding="utf-8"?>
23
    NameID: ["""<?xml version="1.0" encoding="utf-8"?>
 Lines 166-171   def test_create_class_from_xml_string_wr Link Here 
166
    assert kl == None
167
    assert kl == None
167
168
168
169
170
def test_create_class_from_xml_string_xxe():
171
    xml = """<?xml version="1.0"?>
172
    <!DOCTYPE lolz [
173
    <!ENTITY lol "lol">
174
    <!ELEMENT lolz (#PCDATA)>
175
    <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
176
    ]>
177
    <lolz>&lol1;</lolz>
178
    """
179
    with raises(EntitiesForbidden) as err:
180
        create_class_from_xml_string(NameID, xml)
181
182
169
def test_ee_1():
183
def test_ee_1():
170
    ee = saml2.extension_element_from_string(
184
    ee = saml2.extension_element_from_string(
171
        """<?xml version='1.0' encoding='UTF-8'?><foo>bar</foo>""")
185
        """<?xml version='1.0' encoding='UTF-8'?><foo>bar</foo>""")
 Lines 454-459   def test_ee_7(): Link Here 
454
    assert nid.text.strip() == "http://federationX.org"
468
    assert nid.text.strip() == "http://federationX.org"
455
469
456
470
471
def test_ee_xxe():
472
    xml = """<?xml version="1.0"?>
473
    <!DOCTYPE lolz [
474
    <!ENTITY lol "lol">
475
    <!ELEMENT lolz (#PCDATA)>
476
    <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
477
    ]>
478
    <lolz>&lol1;</lolz>
479
    """
480
    with raises(EntitiesForbidden):
481
        saml2.extension_element_from_string(xml)
482
483
457
def test_extension_element_loadd():
484
def test_extension_element_loadd():
458
    ava = {'attributes': {},
485
    ava = {'attributes': {},
459
           'tag': 'ExternalEntityAttributeAuthority',
486
           'tag': 'ExternalEntityAttributeAuthority',
460
-- python-pysaml2-2.0.0.orig/tests/test_43_soap.py
487
++ python-pysaml2-2.0.0/tests/test_43_soap.py
 Lines 12-20   except ImportError: Link Here 
12
        import cElementTree as ElementTree
12
        import cElementTree as ElementTree
13
    except ImportError:
13
    except ImportError:
14
        from elementtree import ElementTree
14
        from elementtree import ElementTree
15
from defusedxml.common import EntitiesForbidden
16
17
from pytest import raises
15
18
16
import saml2.samlp as samlp
19
import saml2.samlp as samlp
17
from saml2.samlp import NAMESPACE as SAMLP_NAMESPACE
20
from saml2.samlp import NAMESPACE as SAMLP_NAMESPACE
21
from saml2 import soap
18
22
19
NAMESPACE = "http://schemas.xmlsoap.org/soap/envelope/"
23
NAMESPACE = "http://schemas.xmlsoap.org/soap/envelope/"
20
24
 Lines 66-68   def test_make_soap_envelope(): Link Here 
66
    assert len(body) == 1
70
    assert len(body) == 1
67
    saml_part = body[0]
71
    saml_part = body[0]
68
    assert saml_part.tag == '{%s}AuthnRequest' % SAMLP_NAMESPACE
72
    assert saml_part.tag == '{%s}AuthnRequest' % SAMLP_NAMESPACE
69
-- python-pysaml2-2.0.0.orig/tests/test_51_client.py
73
74
75
def test_parse_soap_enveloped_saml_thingy_xxe():
76
    xml = """<?xml version="1.0"?>
77
    <!DOCTYPE lolz [
78
    <!ENTITY lol "lol">
79
    <!ELEMENT lolz (#PCDATA)>
80
    <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
81
    ]>
82
    <lolz>&lol1;</lolz>
83
    """
84
    with raises(EntitiesForbidden):
85
        soap.parse_soap_enveloped_saml_thingy(xml, None)
86
87
88
def test_class_instances_from_soap_enveloped_saml_thingies_xxe():
89
    xml = """<?xml version="1.0"?>
90
    <!DOCTYPE lolz [
91
    <!ENTITY lol "lol">
92
    <!ELEMENT lolz (#PCDATA)>
93
    <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
94
    ]>
95
    <lolz>&lol1;</lolz>
96
    """
97
    with raises(soap.XmlParseError):
98
        soap.class_instances_from_soap_enveloped_saml_thingies(xml, None)
99
100
101
def test_open_soap_envelope_xxe():
102
    xml = """<?xml version="1.0"?>
103
    <!DOCTYPE lolz [
104
    <!ENTITY lol "lol">
105
    <!ELEMENT lolz (#PCDATA)>
106
    <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
107
    ]>
108
    <lolz>&lol1;</lolz>
109
    """
110
    with raises(soap.XmlParseError):
111
        soap.open_soap_envelope(xml)
112
++ python-pysaml2-2.0.0/tests/test_51_client.py
 Lines 4-9    Link Here 
4
import base64
4
import base64
5
import urllib
5
import urllib
6
import urlparse
6
import urlparse
7
7
from saml2.authn_context import INTERNETPROTOCOLPASSWORD
8
from saml2.authn_context import INTERNETPROTOCOLPASSWORD
8
from saml2.response import LogoutResponse
9
from saml2.response import LogoutResponse
9
10
 Lines 11-16   from saml2.client import Saml2Client Link Here 
11
from saml2 import samlp, BINDING_HTTP_POST, BINDING_HTTP_REDIRECT
12
from saml2 import samlp, BINDING_HTTP_POST, BINDING_HTTP_REDIRECT
12
from saml2 import saml, config, class_name
13
from saml2 import saml, config, class_name
13
from saml2.config import SPConfig
14
from saml2.config import SPConfig
15
from saml2.pack import parse_soap_enveloped_saml
14
from saml2.saml import NAMEID_FORMAT_PERSISTENT
16
from saml2.saml import NAMEID_FORMAT_PERSISTENT
15
from saml2.saml import NAMEID_FORMAT_TRANSIENT
17
from saml2.saml import NAMEID_FORMAT_TRANSIENT
16
from saml2.saml import NameID
18
from saml2.saml import NameID
 Lines 18-23   from saml2.server import Server Link Here 
18
from saml2.time_util import in_a_while
20
from saml2.time_util import in_a_while
19
21
20
from py.test import raises
22
from py.test import raises
23
from defusedxml.common import EntitiesForbidden
21
from fakeIDP import FakeIDP, unpack_form
24
from fakeIDP import FakeIDP, unpack_form
22
25
23
26
 Lines 439-444   class TestClientWithDummy(): Link Here 
439
               'http://www.example.com/login'
442
               'http://www.example.com/login'
440
        assert ac.authn_context_class_ref.text == INTERNETPROTOCOLPASSWORD
443
        assert ac.authn_context_class_ref.text == INTERNETPROTOCOLPASSWORD
441
444
445
def test_parse_soap_enveloped_saml_xxe():
446
    xml = """<?xml version="1.0"?>
447
    <!DOCTYPE lolz [
448
    <!ENTITY lol "lol">
449
    <!ELEMENT lolz (#PCDATA)>
450
    <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
451
    ]>
452
    <lolz>&lol1;</lolz>
453
    """
454
    with raises(EntitiesForbidden):
455
        parse_soap_enveloped_saml(xml, None)
442
456
443
# if __name__ == "__main__":
457
# if __name__ == "__main__":
444
#     tc = TestClient()
458
#     tc = TestClient()

Return to bug 43393