Exemplo n.º 1
0
 def test_wrapping_attack(self):
     """
     Test resistance to attempted wrapping attack
     """
     case = self.cases['SAML_assertion1']
     print("XML input :\n{}\n\n".format(case.as_buf('in.xml')))
     tbs = case.as_etree('in.xml')
     signed = xmlsec.sign(tbs,
                          key_spec=self.private_keyspec,
                          cert_spec=self.public_keyspec)
     attack = case.as_etree('evil.xml')
     attack.append(signed)
     refs = xmlsec.verified(attack, self.public_keyspec)
     self.assertTrue(len(refs) == 1)
     print("verified XML: %s" % etree.tostring(refs[0]))
     seen_foo = False
     seen_bar = False
     for av in refs[0].findall(".//{%s}AttributeValue" %
                               'urn:oasis:names:tc:SAML:2.0:assertion'):
         print(etree.tostring(av))
         print(av.text)
         if av.text == 'Foo':
             seen_foo = True
         elif av.text == 'Bar':
             seen_bar = True
         self.assertTrue(av.text != 'admin')
     self.assertTrue(seen_foo and seen_bar)
Exemplo n.º 2
0
 def test_sign_alert_signed(self):
     """Tests alert signature creation."""
     plain_alert = etree.fromstring(self.valid_alert_content)
     signed_alert = utils.SignAlert(plain_alert, self.TEST_USER_NAME)
     cert_path = os.path.join(settings.CREDENTIALS_DIR,
                              self.TEST_USER_NAME + ".cert")
     self.assertTrue(xmlsec.verified(signed_alert, cert_path))
Exemplo n.º 3
0
 def test_wrapping_attack(self):
     """
     Test resistance to attempted wrapping attack
     """
     case = self.cases['SAML_assertion1']
     print("XML input :\n{}\n\n".format(case.as_buf('in.xml')))
     tbs = case.as_etree('in.xml')
     signed = xmlsec.sign(tbs,
                          key_spec=self.private_keyspec,
                          cert_spec=self.public_keyspec)
     attack = case.as_etree('evil.xml')
     attack.append(signed)
     refs = xmlsec.verified(attack, self.public_keyspec)
     self.assertTrue(len(refs) == 1)
     print("verified XML: %s" % etree.tostring(refs[0]))
     seen_foo = False
     seen_bar = False
     for av in refs[0].findall(".//{%s}AttributeValue" % 'urn:oasis:names:tc:SAML:2.0:assertion'):
         print(etree.tostring(av))
         print(av.text)
         if av.text == 'Foo':
             seen_foo = True
         elif av.text == 'Bar':
             seen_bar = True
         self.assertTrue(av.text != 'admin')
     self.assertTrue(seen_foo and seen_bar)
Exemplo n.º 4
0
 def test_sign_alert_signed(self):
   """Tests alert signature creation."""
   plain_alert = etree.fromstring(self.valid_alert_content)
   signed_alert = utils.SignAlert(plain_alert, self.TEST_USER_NAME)
   cert_path = os.path.join(settings.CREDENTIALS_DIR,
                            self.TEST_USER_NAME + ".cert")
   self.assertTrue(xmlsec.verified(signed_alert, cert_path))
Exemplo n.º 5
0
def check_signature(t, key, only_one_signature=False):
    if key is not None:
        log.debug("verifying signature using %s" % key)
        refs = xmlsec.verified(t, key, drop_signature=True)
        if only_one_signature and len(refs) != 1:
            raise MetadataException("XML metadata contains %d signatures - exactly 1 is required" % len(refs))
        t = refs[0]  # prevent wrapping attacks

    return t
Exemplo n.º 6
0
def check_signature(t, key, only_one_signature=False):
    if key is not None:
        log.debug("verifying signature using %s" % key)
        refs = xmlsec.verified(t, key, drop_signature=True)
        if only_one_signature and len(refs) != 1:
            raise MetadataException("XML metadata contains %d signatures - exactly 1 is required" % len(refs))
        t = refs[0]  # prevent wrapping attacks

    return t
Exemplo n.º 7
0
    def check_signature(self, t, key):
        if key is not None:
            if log.isDebugEnabled():
                log.debug("verifying signature using %s" % key)
            refs = xmlsec.verified(t, key)
            if len(refs) != 1:
                raise MetadataException("XML metadata contains %d signatures - exactly 1 is required" % len(refs))
            t = refs[0]  # prevent wrapping attacks

        return t
Exemplo n.º 8
0
    def check_signature(self, t, key):
        if key is not None:
            if log.isDebugEnabled():
                log.debug("verifying signature using %s" % key)
            refs = xmlsec.verified(t, key)
            if len(refs) != 1:
                raise MetadataException(
                    "XML metadata contains %d signatures - exactly 1 is required"
                    % len(refs))
            t = refs[0]  # prevent wrapping attacks

        return t
Exemplo n.º 9
0
    def parse_metadata(self,
                       fn,
                       key=None,
                       base_url=None,
                       fail_on_error=False,
                       filter_invalid=True,
                       validate=True,
                       post=None):
        """Parse a piece of XML and split it up into EntityDescriptor elements. Each such element
        is stored in the MDRepository instance.

:param fn: a file-like object containing SAML metadata
:param key: a certificate (file) or a SHA1 fingerprint to use for signature verification
:param base_url: use this base url to resolve relative URLs for XInclude processing
:param fail_on_error: (default: False)
:param filter_invalid: (default True) remove invalid EntityDescriptor elements rather than raise an errror
:param validate: (default: True) set to False to turn off all XML schema validation
:param post: A callable that will be called to modify the parse-tree before any validation
(but after xinclude processing)
        """
        try:
            t = etree.parse(fn, base_url=base_url, parser=etree.XMLParser(resolve_entities=False))
            t.xinclude()

            if key is not None:
                try:
                    log.debug("verifying signature using %s" % key)
                    refs = xmlsec.verified(t, key)
                    if len(refs) != 1:
                        raise MetadataException("XML metadata contains %d signatures - exactly 1 is required" % len(refs))
                    t = refs[0]  # prevent wrapping attacks
                except Exception, ex:
                    tb = traceback.format_exc()
                    print tb
                    log.error(ex)
                    return None

            if post is not None:
                t = post(t)

            if validate:
                if filter_invalid:
                    for e in t.findall('{%s}EntityDescriptor' % NS['md']):
                        if not schema().validate(e):
                            error = _e(schema().error_log, m=base_url)
                            log.debug("removing '%s': schema validation failed (%s)" % (e.get('entityID'), error))
                            e.getparent().remove(e)
                            self.fire(type=EVENT_DROP_ENTITY, url=base_url, entityID=e.get('entityID'), error=error)
                else:
                    # Having removed the invalid entities this should now never happen...
                    schema().assertValid(t)
Exemplo n.º 10
0
    def test_duo_vuln_attack(self):
        """
        Test https://duo.com/blog/duo-finds-saml-vulnerabilities-affecting-multiple-implementations
        """
        case = self.cases['SAML_assertion_sha256']
        print("XML input :\n{}\n\n".format(case.as_buf('in.xml')))

        signed = xmlsec.sign(case.as_etree('in.xml'),
                             key_spec=self.private_keyspec,
                             cert_spec=self.public_keyspec)
        refs = xmlsec.verified(signed, self.public_keyspec)
        self.assertTrue(len(refs) == 1)
        print("verified XML: %s" % etree.tostring(refs[0]))
        assert('evil' not in [x.text for x in refs[0].findall(".//{%s}AttributeValue" % 'urn:oasis:names:tc:SAML:2.0:assertion')])
Exemplo n.º 11
0
    def test_duo_vuln_attack(self):
        """
        Test https://duo.com/blog/duo-finds-saml-vulnerabilities-affecting-multiple-implementations
        """
        case = self.cases['SAML_assertion_sha256']
        print("XML input :\n{}\n\n".format(case.as_buf('in.xml')))

        signed = xmlsec.sign(case.as_etree('in.xml'),
                             key_spec=self.private_keyspec,
                             cert_spec=self.public_keyspec)
        refs = xmlsec.verified(signed, self.public_keyspec)
        self.assertTrue(len(refs) == 1)
        print("verified XML: %s" % etree.tostring(refs[0]))
        assert('evil' not in [x.text for x in refs[0].findall(".//{%s}AttributeValue" % 'urn:oasis:names:tc:SAML:2.0:assertion')])
Exemplo n.º 12
0
    def test_sign_verify_SAML_assertion_unwrap2(self):
        """
        Test signing a SAML assertion, and return verified data.
        """
        case = self.cases['SAML_assertion1']
        print("XML input :\n{}\n\n".format(case.as_buf('in.xml')))

        tbs = case.as_etree('in.xml')
        signed = xmlsec.sign(tbs,
                             key_spec=self.private_keyspec,
                             cert_spec=self.public_keyspec)
        refs = xmlsec.verified(signed, self.public_keyspec)
        self.assertTrue(len(refs) == 1)
        print("verified XML: %s" % etree.tostring(refs[0]))
        self.assertTrue(tbs.tag == refs[0].tag)
        set1 = set(etree.tostring(i, method='c14n') for i in root(tbs))
        set2 = set(etree.tostring(i, method='c14n') for i in root(refs[0]))
        self.assertTrue(set1 == set2)
Exemplo n.º 13
0
    def test_sign_verify_SAML_assertion_unwrap2(self):
        """
        Test signing a SAML assertion, and return verified data.
        """
        case = self.cases['SAML_assertion1']
        print("XML input :\n{}\n\n".format(case.as_buf('in.xml')))

        tbs = case.as_etree('in.xml')
        signed = xmlsec.sign(tbs,
                             key_spec=self.private_keyspec,
                             cert_spec=self.public_keyspec)
        refs = xmlsec.verified(signed, self.public_keyspec)
        self.assertTrue(len(refs) == 1)
        print("verified XML: %s" % etree.tostring(refs[0]))
        self.assertTrue(tbs.tag == refs[0].tag)
        set1 = set(etree.tostring(i, method='c14n') for i in root(tbs))
        set2 = set(etree.tostring(i, method='c14n') for i in root(refs[0]))
        self.assertTrue(set1 == set2)
Exemplo n.º 14
0
Arquivo: mdrepo.py Projeto: GEANT/met
                schema().assertValid(t)
        except DocumentInvalid, ex:
            traceback.print_exc()
            log.debug("schema validation failed on '%s': %s" % (
                base_url, _e(ex.error_log, m=base_url)))
            raise MetadataException("schema validation failed")
        except Exception, ex:
            # log.debug(_e(schema().error_log))
            log.error(ex)
            if fail_on_error:
                raise ex
            return None
        if key is not None:
            try:
                log.debug("verifying signature using %s" % key)
                refs = xmlsec.verified(t, key)
                if len(refs) != 1:
                    raise MetadataException(
                        "XML metadata contains %d signatures - exactly 1 is required" % len(refs))
                t = refs[0]  # prevent wrapping attacks
            except Exception, ex:
                tb = traceback.format_exc()
                print tb
                log.error(ex)
                return None

        return t

    def _index_entity(self, e):
        #log.debug("adding %s to index" % e.get('entityID'))
        if 'ID' in e.attrib:
Exemplo n.º 15
0
            # Having removed the invalid entities this should now never happen...
                schema().assertValid(t)
        except DocumentInvalid, ex:
            traceback.print_exc()
            log.debug("schema validation failed on '%s': %s" % (base_url, _e(ex.error_log, m=base_url)))
            raise MetadataException("schema validation failed")
        except Exception, ex:
            #log.debug(_e(schema().error_log))
            log.error(ex)
            if fail_on_error:
                raise ex
            return None
        if key is not None:
            try:
                log.debug("verifying signature using %s" % key)
                refs = xmlsec.verified(t, key)
                if len(refs) != 1:
                    raise MetadataException("XML metadata contains %d signatures - exactly 1 is required" % len(refs))
                t = refs[0] # prevent wrapping attacks
            except Exception, ex:
                tb = traceback.format_exc()
                print tb
                log.error(ex)
                return None

        return t

    def _index_entity(self, e):
        #log.debug("adding %s to index" % e.get('entityID'))
        if 'ID' in e.attrib:
            del e.attrib['ID']