예제 #1
0
    def test_can_load_ciq_extension(self):
        from cybox.bindings.extensions.location import ciq_address_3_0
        addr = ciq_address_3_0.CIQAddress3_0InstanceType()

        # Really basic test to verify the extension works.
        s = StringIO()
        addr.export(s.write, 0)
        xml = s.getvalue()
        self.assertEqual(165, len(xml))
예제 #2
0
    def test_can_load_ciq_extension(self):
        from cybox.bindings.extensions.location import ciq_address_3_0
        addr = ciq_address_3_0.CIQAddress3_0InstanceType()

        # Really basic test to verify the extension works.
        s = StringIO()
        addr.export(s.write, 0)
        xml = s.getvalue()
        self.assertEqual(165, len(xml))
예제 #3
0
    def test_wrong_root_element(self):
        wrong_root = """
        <stix:NotAPackage xmlns:stix="http://stix.mitre.org/stix-1"
            version="1.2" id="example:Package-1">
        </stix:NotAPackage>
        """

        parser = EntityParser()
        self.assertRaises(UnsupportedRootElementError, parser.parse_xml,
                          StringIO(wrong_root))

        package = parser.parse_xml(StringIO(wrong_root), check_root=False)

        self.assertEqual("example:Package-1", package.id_)
        self.assertEqual("1.2", package.version)
예제 #4
0
    def test_missing_version(self):
        missing_version = """
        <stix:STIX_Package xmlns:stix="http://stix.mitre.org/stix-1"
            id="example:Package-1">
        </stix:STIX_Package>
        """

        parser = EntityParser()
        self.assertRaises(UnknownVersionError, parser.parse_xml,
                          StringIO(missing_version))

        package = parser.parse_xml(StringIO(missing_version),
                                   check_version=False)

        self.assertEqual("example:Package-1", package.id_)
예제 #5
0
 def test_get_etree_root_element(self):
     sio = StringIO(XML)
     tree = etree.parse(sio)
     newroot = tree.getroot()
     root = utils.get_etree_root(newroot)
     lname = etree.QName(root).localname
     self.assertEqual(lname, XML_ROOT_LOCALNAME)
    def test_duplicate_ns_prefix(self):
        """Test that duplicate namespace prefix mappings raise errors.

        """
        p = STIXPackage()
        bad = {'bad:ns': 'stix'}  # 'stix' is already default ns prefix

        self.assertRaises(mixbox.namespaces.DuplicatePrefixError,
                          p.to_xml,
                          ns_dict=bad)

        # Build a valid stix document that has a default namespace remapped
        # to another namespace. We remap 'stixCommon' to a bogus ns here.
        xml = ("""<stix:STIX_Package
                    xmlns:stixCommon="THISISGONNABEPROBLEM"
                    xmlns:stix="http://stix.mitre.org/stix-1"
                    xmlns:stixVocabs="http://stix.mitre.org/default_vocabularies-1"
                    version="1.2"
                    timestamp="2015-04-09T14:22:25.620831+00:00">
                <stix:STIX_Header>
                    <stix:Description>A unit test</stix:Description>
                </stix:STIX_Header>
            </stix:STIX_Package>""")

        sio = StringIO(xml)
        p = STIXPackage.from_xml(sio)

        # Exporting should raise an error.
        self.assertRaises(mixbox.namespaces.DuplicatePrefixError, p.to_xml)
예제 #7
0
 def test_invalid_version(self):
     xml = StringIO(STIX_NO_VERSION_XML)
     func = sdv.validate_best_practices
     self.assertRaises(errors.InvalidSTIXVersionError,
                       func,
                       xml,
                       version="INVALID")
예제 #8
0
    def test_missing_version(self):
        missing_version = """
        <maecPackage:MAEC_Package
            xmlns:maecPackage="http://maec.mitre.org/XMLSchema/maec-package-2"
            id="example:package-1">
        </maecPackage:MAEC_Package>
        """

        parser = EntityParser()
        self.assertRaises(UnknownVersionError, parser.parse_xml,
                          StringIO(missing_version))

        package = parser.parse_xml(StringIO(missing_version),
                                   check_version=False)

        self.assertEqual("example:package-1", package.id_)
    def test_parsed_namespaces(self):
        """Test that non-default namespaces make it through the parse-serialize
        process.

        """
        xml = ("""<stix:STIX_Package
                    xmlns:TEST="a:test"
                    xmlns:FOO="a:foo"
                    xmlns:BAR="a:bar"
                    xmlns:cybox="http://cybox.mitre.org/cybox-2"
                    xmlns:cyboxCommon="http://cybox.mitre.org/common-2"
                    xmlns:cyboxVocabs="http://cybox.mitre.org/default_vocabularies-2"
                    xmlns:example="http://example.com"
                    xmlns:stix="http://stix.mitre.org/stix-1"
                    xmlns:stixCommon="http://stix.mitre.org/common-1"
                    xmlns:stixVocabs="http://stix.mitre.org/default_vocabularies-1"
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    id="example:Package-e2454ee8-e59c-43ac-a085-46ae4516fd6e"
                    version="1.2"
                    timestamp="2015-04-09T14:22:25.620831+00:00"/>""")

        sio = StringIO(xml)
        p = STIXPackage.from_xml(sio)

        serialized = p.to_xml()
        e = lxml.etree.XML(serialized)
        self.assertEqual(e.nsmap.get('TEST'), 'a:test')
        self.assertEqual(e.nsmap.get('FOO'), 'a:foo')
        self.assertEqual(e.nsmap.get('BAR'), 'a:bar')
예제 #10
0
    def schematron(self):
        """Returns an lxml.etree._ElementTree representation of the
        ISO Schematron translation of a STIX profile.

        The STIXProfileValidator uses the extension function
        saxon:line-number() for reporting line numbers. This function is
        stripped along with any references to the Saxon namespace from the
        exported XSLT. This is due to compatibility issues between
        Schematron/XSLT processing libraries. For example, SaxonPE/EE expects
        the Saxon namespace to be "http://saxon.sf.net/" while libxslt expects
        it to be "http://icl.com/saxon". The freely distributed SaxonHE
        library does not support Saxon extension functions at all.

        Returns:
            An ``etree._ElementTree`` Schematron document.

        """
        to_replace = ' %s' % SAXON_LINENO

        s = etree.tostring(self._schematron.schematron)
        s = s.replace(to_replace, '')
        s = s.replace('<ns prefix="saxon" uri="http://icl.com/saxon"/>', '')

        parser = utils.get_xml_parser()
        return etree.parse(StringIO(s), parser=parser)
예제 #11
0
 def test_invalid_version(self):
     xml = StringIO(STIX_1_1_1_XML)
     func = sdv.validate_xml
     self.assertRaises(errors.InvalidSTIXVersionError,
                       func,
                       xml,
                       version="INVALID")
예제 #12
0
    def test_etree(self):
        parser = mixbox.xml.get_xml_parser()
        tree = lxml.etree.parse(StringIO(self.XML), parser=parser)

        ext = OpenIOCTestMechanism()
        ext.ioc = tree
        self._test_xml(ext)
예제 #13
0
    def test_etree(self):
        parser = mixbox.xml.get_xml_parser()
        tree = etree.parse(StringIO(self.XML), parser=parser)

        ext = MAECInstance()
        ext.maec = tree
        self._test_xml(ext)
예제 #14
0
    def xslt(self):
        """Returns an lxml.etree._ElementTree representation of the ISO
        Schematron skeleton generated XSLT translation of a STIX profile.

        The STIXProfileValidator uses the extension function
        saxon:line-number() for reporting line numbers. This function is
        stripped along with any references to the Saxon namespace from the
        exported XSLT. This is due to compatibility issues between
        Schematron/XSLT processing libraries. For example, SaxonPE/EE expects
        the Saxon namespace to be "http://saxon.sf.net/" while libxslt expects
        it to be "http://icl.com/saxon". The freely distributed SaxonHE
        library does not support Saxon extension functions at all.

        Returns:
            An ``etree._ElementTree`` XSLT document.

        """
        if not self._schematron:
            return None

        s = etree.tostring(self._schematron.validator_xslt)
        s = s.replace(
            ' [<axsl:text/><axsl:value-of select="saxon:line-number()"/><axsl:text/>]',
            '')
        s = s.replace('xmlns:saxon="http://icl.com/saxon"', '')
        s = s.replace(
            '<svrl:ns-prefix-in-attribute-values uri="http://icl.com/saxon" prefix="saxon"/>',
            '')

        parser = utils.get_xml_parser()
        return etree.parse(StringIO(s), parser=parser)
예제 #15
0
    def test_wrong_version(self):
        wrong_version = """
        <stix:STIX_Package xmlns:stix="http://stix.mitre.org/stix-1"
            version="17.8.9" id="example:Package-1">
        </stix:STIX_Package>
        """

        parser = EntityParser()
        self.assertRaises(UnsupportedVersionError, parser.parse_xml,
                          StringIO(wrong_version))

        package = parser.parse_xml(StringIO(wrong_version),
                                   check_version=False)

        self.assertEqual("example:Package-1", package.id_)
        self.assertEqual("17.8.9", package.version)
예제 #16
0
    def test_description_output(self):
        incident = incident_binding.IncidentType()

        assets = incident_binding.AffectedAssetsType()
        asset = incident_binding.AffectedAssetType()

        description = StructuredText("A Description")
        asset.Structured_Description = description.to_obj()

        assets.add_Affected_Asset(asset)
        incident.Affected_Assets = assets

        s = StringIO()

        incident.export(s.write, 0, {'http://stix.mitre.org/Incident-1': 'incident'})
        xml = s.getvalue()
        self.assertTrue("A Description" in xml, "Description not exported")
예제 #17
0
    def test_wrong_version(self):
        wrong_version = """
        <maecPackage:MAEC_Package
            xmlns:maecPackage="http://maec.mitre.org/XMLSchema/maec-package-2"
            id="example:package-1" schema_version="10.1.8">
        </maecPackage:MAEC_Package>
        """

        parser = EntityParser()
        self.assertRaises(UnsupportedVersionError, parser.parse_xml,
                          StringIO(wrong_version))

        package = parser.parse_xml(StringIO(wrong_version),
                                   check_version=False)

        self.assertEqual("example:package-1", package.id_)
        self.assertEqual("10.1.8", package.schema_version)
예제 #18
0
 def test_multiple_values_in_same_location(self):
     sio = StringIO(MULTIVALUE_INSTANCE_XML)
     parse_obj = parser.MarkingParser(sio)
     package = parse_obj.parse()
     o = package.observables[0]
     ip_address = o.object_.properties
     self.assertTrue(hasattr(ip_address, "__datamarkings__"))
     self.assertEqual(len(ip_address.__datamarkings__), 1)
예제 #19
0
    def test_etree_dict(self):
        parser = mixbox.xml.get_xml_parser()
        tree = etree.parse(StringIO(self.XML), parser=parser)
        ext = MAECInstance()
        ext.maec = tree

        d = ext.to_dict()
        ext2 = MAECInstance.from_dict(d)
        self._test_xml(ext2)
예제 #20
0
    def test_wrong_root_element(self):
        wrong_root = """
        <maecPackage:NotAPackage
            xmlns:maecPackage="http://maec.mitre.org/XMLSchema/maec-package-2"
            id="example:package-1" schema_version="2.1">
        </maecPackage:NotAPackage>
        """

        parser = EntityParser()
        self.assertRaises(UnsupportedRootElementError, parser.parse_xml,
                          StringIO(wrong_root))

        # If there's not a valid root element, there's no way to check the
        # version number.
        self.assertRaises(UnsupportedVersionError,
                          parser.parse_xml,
                          StringIO(wrong_root),
                          check_root=False)
    def test_invalid(self):
        xml = StringIO(CYBOX_INVALID)
        results = sdv.validate_xml(xml)

        # Assert that the document is identified as being invalid
        self.assertFalse(results.is_valid)

        # Assert that the badAttr attribute is the only error recorded
        self.assertEqual(len(results.errors), 1)
예제 #22
0
    def test_description_output(self):
        incident = incident_binding.IncidentType()

        assets = incident_binding.AffectedAssetsType()
        asset = incident_binding.AffectedAssetType()

        description = StructuredText("A Description")
        asset.Structured_Description = description.to_obj()

        assets.add_Affected_Asset(asset)
        incident.Affected_Assets = assets

        s = StringIO()

        incident.export(s.write, 0,
                        {'http://stix.mitre.org/Incident-1': 'incident'})
        xml = s.getvalue()
        self.assertTrue("A Description" in xml, "Description not exported")
예제 #23
0
    def test_etree_dict(self):
        parser = mixbox.xml.get_xml_parser()
        tree = lxml.etree.parse(StringIO(self.XML), parser=parser)
        ext = OpenIOCTestMechanism()
        ext.ioc = tree

        d = ext.to_dict()
        ext2 = OpenIOCTestMechanism.from_dict(d)
        self._test_xml(ext2)
예제 #24
0
    def setUpClass(cls):
        # Parse the xml string and define the root
        ioc_xml = StringIO(OPENIOC_XML)
        tree = ET.parse(ioc_xml)
        cls.root = tree.getroot()

        # Use this search to get top indicators to call functions on
        xpath = "./openioc:definition/openioc:Indicator"
        namespace = {"openioc": "http://schemas.mandiant.com/2010/ioc"}
        cls.indicators = list(cls.root.xpath(xpath, namespaces=namespace))
예제 #25
0
    def test_invalid(self):
        xml = StringIO(STIX_INVALID)
        results = sdv.validate_xml(xml)

        # Assert that the document is identified as being invalid
        self.assertFalse(results.is_valid)

        # Assert that the badAttr attribute and stix:INVALID element are
        # errors are recorded.
        self.assertEqual(len(results.errors), 2)
예제 #26
0
    def test_valid(self):
        valid = """
        <stix:STIX_Package xmlns:stix="http://stix.mitre.org/stix-1"
            version="1.2" id="example:Package-1">
        </stix:STIX_Package>
        """

        parser = EntityParser()
        package = parser.parse_xml(StringIO(valid))

        self.assertEqual("example:Package-1", package.id_)
예제 #27
0
    def test_valid_bundle(self):
        valid_bundle = """
        <maecBundle:MAEC_Bundle
            xmlns:maecBundle="http://maec.mitre.org/XMLSchema/maec-bundle-4"
            id="example:bundle-1" schema_version="4.1">
        </maecBundle:MAEC_Bundle>
        """

        parser = EntityParser()
        package = parser.parse_xml(StringIO(valid_bundle))

        self.assertEqual("example:bundle-1", package.id_)
예제 #28
0
    def test_ts_not_resolves(self):
        sio = StringIO(TS_DOES_NOT_RESOLVE)

        idref = "example:campaign-1"
        timestamp = "2015-04-14T15:24:19.416203+00:00"

        resolves = common.idref_timestamp_resolves(
            root=sio,
            idref=idref,
            timestamp=timestamp,
            namespaces=common.get_stix_namespaces('1.1.1'))

        self.assertEqual(resolves, False)
예제 #29
0
def parseString(inString):
    from mixbox.vendor.six import StringIO
    doc = parsexml_(StringIO(inString))
    rootNode = doc.getroot()
    rootTag, rootClass = get_root_tag(rootNode)
    rootObj = rootClass.factory()
    rootObj.build(rootNode)
    # Enable Python to collect the space used by the DOM.
    doc = None
    #sys.stdout.write('<?xml version="1.0" ?>\n')
    #rootObj.export(sys.stdout, 0, name_="MAEC_Container",
    #    namespacedef_='')
    return rootObj
예제 #30
0
    def test_valid_package(self):
        valid_package = """
        <maecPackage:MAEC_Package
            xmlns:maecPackage="http://maec.mitre.org/XMLSchema/maec-package-2"
            id="example:package-1" schema_version="2.1">
        </maecPackage:MAEC_Package>
        """

        parser = EntityParser()
        package = parser.parse_xml(StringIO(valid_package))

        self.assertEqual(Package, type(package))
        self.assertEqual("example:package-1", package.id_)
예제 #31
0
    def test_marking_path_parsing_for_observable(self):
        """Test that parsed paths are applied correctly to Observable"""

        # paths to attempt for a component RED marking
        observable_xpaths = [{
            "path":
            "../../../indicator:Observable[1]/descendant-or-self::node() | ../../../indicator:Observable[1]/descendant-or-self::node()/@*",
            "should_pass": True
        }, {
            "path": "this is not a real xpath",
            "should_pass": False
        }]
        # paths to attempt for a component AMBER marking
        component_xpaths = [{
            "path":
            "../../../descendant-or-self::node() | ../../../descendant-or-self::node()/@*",
            "should_pass": True
        }, {
            "path": "this is not a real xpath",
            "should_pass": False
        }]

        for observable_path_dict in observable_xpaths:
            for component_path_dict in component_xpaths:
                # Format our STIX XML template
                xml = STIX_XML_TEMPLATE_EMBEDDED_OBSERVABLE.format(
                    observable_path_dict["path"], component_path_dict["path"])
                xml_readable = StringIO(xml)

                # Build and parse the MarkingContainer
                try:
                    container = stixmarx.parse(xml_readable)
                except etree.XPathEvalError:
                    self.assertTrue(
                        observable_path_dict["should_pass"] is False
                        or component_path_dict["should_pass"] is False)
                    continue

                package = container.package

                colors = [
                    marking_spec.marking_structures[0].color for marking_spec
                    in container.get_markings(package.indicators[0].observable)
                ]

                self.assertTrue(
                    ('RED' in colors) == observable_path_dict["should_pass"])
                self.assertTrue(
                    ('AMBER' in colors) == component_path_dict["should_pass"])
예제 #32
0
def parseString(inString):
    from mixbox.vendor.six import StringIO
    doc = parsexml_(StringIO(inString))
    rootNode = doc.getroot()
    rootTag, rootClass = get_root_tag(rootNode)
    if rootClass is None:
        rootTag = 'Windows_Pipe'
        rootClass = WindowsPipeObjectType
    rootObj = rootClass.factory()
    rootObj.build(rootNode)
    # Enable Python to collect the space used by the DOM.
    doc = None
    sys.stdout.write('<?xml version="1.0" ?>\n')
    rootObj.export(sys.stdout.write, 0, name_="Windows_Pipe", namespacedef_='')
    return rootObj
예제 #33
0
파일: base.py 프로젝트: shinsec/python-stix
    def to_xml(self, include_namespaces=True, include_schemalocs=False,
               ns_dict=None, schemaloc_dict=None, pretty=True,
               auto_namespace=True, encoding='utf-8'):
        """Serializes a :class:`Entity` instance to an XML string.

        The default character encoding is ``utf-8`` and can be set via the
        `encoding` parameter. If `encoding` is ``None``, a string (unicode in
        Python 2, str in Python 3) is returned.

        Args:
            auto_namespace: Automatically discover and export XML namespaces
                for a STIX :class:`Entity` instance.
            include_namespaces: Export namespace definitions in the output
                XML. Default is ``True``.
            include_schemalocs: Export ``xsi:schemaLocation`` attribute
                in the output document. This will attempt to associate
                namespaces declared in the STIX document with schema locations.
                If a namespace cannot be resolved to a schemaLocation, a
                Python warning will be raised. Schemalocations will only be
                exported if `include_namespaces` is also ``True``.
            ns_dict: Dictionary of XML definitions (namespace is key, alias is
                value) to include in the exported document. This must be
                passed in if `auto_namespace` is ``False``.
            schemaloc_dict: Dictionary of XML ``namespace: schema location``
                mappings to include in the exported document. These will
                only be included if `auto_namespace` is ``False``.
            pretty: Pretty-print the XML.
            encoding: The output character encoding. Default is ``utf-8``. If
                `encoding` is set to ``None``, a string (unicode in Python 2,
                str in Python 3) is returned.

        Returns:
            An XML string for this
            :class:`Entity` instance. Default character encoding is ``utf-8``.

        """

        from .utils import nsparser
        parser = nsparser.NamespaceParser()

        if auto_namespace:
            ns_info = nsparser.NamespaceInfo()
        else:
            ns_info = None

        obj = self.to_obj(ns_info=ns_info)

        if (not auto_namespace) and (not ns_dict):
            raise Exception(
                "Auto-namespacing was disabled but ns_dict was empty "
                "or missing."
            )

        if auto_namespace:
            ns_info.finalize(ns_dict=ns_dict, schemaloc_dict=schemaloc_dict)
            obj_ns_dict = ns_info.binding_namespaces
        else:
            ns_info = nsparser.NamespaceInfo()
            ns_info.finalized_namespaces = ns_dict or {}
            ns_info.finalized_schemalocs = schemaloc_dict or {}
            obj_ns_dict = dict(
                itertools.chain(
                    iteritems(ns_dict),
                    iteritems(nsparser.DEFAULT_STIX_NAMESPACES)
                )
            )

        namespace_def = ""
        if include_namespaces:
            xmlns = parser.get_xmlns_str(ns_info.finalized_namespaces)
            namespace_def += ("\n\t" + xmlns)

        if include_schemalocs and include_namespaces:
            schemaloc = parser.get_schemaloc_str(ns_info.finalized_schemalocs)
            namespace_def += ("\n\t" + schemaloc)

        if not pretty:
            namespace_def = namespace_def.replace('\n\t', ' ')

        with save_encoding(encoding):
            sio = StringIO()
            obj.export(
                sio.write,                    # output buffer
                0,                            # output level
                obj_ns_dict,                  # namespace dictionary
                pretty_print=pretty,          # pretty printing
                namespacedef_=namespace_def   # namespace/schemaloc def string
            )

        # Ensure that the StringIO buffer is unicode
        s = text_type(sio.getvalue())

        if encoding:
            return s.encode(encoding)

        return s