Removed everything in test/v21/stix2_data/
Bring back optional version parameter to datastores. Update documentation. Update v21 test suitemaster
parent
3d099bec91
commit
bfa49ce37a
|
@ -110,15 +110,15 @@ class MemoryStore(DataStoreMixin):
|
|||
sink (MemorySink): MemorySink
|
||||
|
||||
"""
|
||||
def __init__(self, stix_data=None, allow_custom=True):
|
||||
def __init__(self, stix_data=None, allow_custom=True, version=None):
|
||||
self._data = {}
|
||||
|
||||
if stix_data:
|
||||
_add(self, stix_data, allow_custom)
|
||||
_add(self, stix_data, allow_custom, version)
|
||||
|
||||
super(MemoryStore, self).__init__(
|
||||
source=MemorySource(stix_data=self._data, allow_custom=allow_custom, _store=True),
|
||||
sink=MemorySink(stix_data=self._data, allow_custom=allow_custom, _store=True),
|
||||
source=MemorySource(stix_data=self._data, allow_custom=allow_custom, version=version, _store=True),
|
||||
sink=MemorySink(stix_data=self._data, allow_custom=allow_custom, version=version, _store=True),
|
||||
)
|
||||
|
||||
def save_to_file(self, *args, **kwargs):
|
||||
|
@ -161,13 +161,16 @@ class MemorySink(DataSink):
|
|||
allow_custom (bool): whether to allow custom objects/properties
|
||||
when exporting STIX content to file.
|
||||
Default: True.
|
||||
version (str): If present, it forces the parser to use the version
|
||||
provided. Otherwise, the library will make the best effort based
|
||||
on checking the "spec_version" property.
|
||||
|
||||
Attributes:
|
||||
_data (dict): the in-memory dict that holds STIX objects.
|
||||
If part of a MemoryStore, the dict is shared with a MemorySource
|
||||
|
||||
"""
|
||||
def __init__(self, stix_data=None, allow_custom=True, _store=False):
|
||||
def __init__(self, stix_data=None, allow_custom=True, version=None, _store=False):
|
||||
super(MemorySink, self).__init__()
|
||||
self.allow_custom = allow_custom
|
||||
|
||||
|
@ -176,10 +179,10 @@ class MemorySink(DataSink):
|
|||
else:
|
||||
self._data = {}
|
||||
if stix_data:
|
||||
_add(self, stix_data, allow_custom)
|
||||
_add(self, stix_data, allow_custom, version)
|
||||
|
||||
def add(self, stix_data):
|
||||
_add(self, stix_data, self.allow_custom)
|
||||
def add(self, stix_data, version=None):
|
||||
_add(self, stix_data, self.allow_custom, version)
|
||||
add.__doc__ = _add.__doc__
|
||||
|
||||
def save_to_file(self, path, encoding="utf-8"):
|
||||
|
@ -230,13 +233,16 @@ class MemorySource(DataSource):
|
|||
allow_custom (bool): whether to allow custom objects/properties
|
||||
when importing STIX content from file.
|
||||
Default: True.
|
||||
version (str): If present, it forces the parser to use the version
|
||||
provided. Otherwise, the library will make the best effort based
|
||||
on checking the "spec_version" property.
|
||||
|
||||
Attributes:
|
||||
_data (dict): the in-memory dict that holds STIX objects.
|
||||
If part of a MemoryStore, the dict is shared with a MemorySink
|
||||
|
||||
"""
|
||||
def __init__(self, stix_data=None, allow_custom=True, _store=False):
|
||||
def __init__(self, stix_data=None, allow_custom=True, version=None, _store=False):
|
||||
super(MemorySource, self).__init__()
|
||||
self.allow_custom = allow_custom
|
||||
|
||||
|
@ -245,7 +251,7 @@ class MemorySource(DataSource):
|
|||
else:
|
||||
self._data = {}
|
||||
if stix_data:
|
||||
_add(self, stix_data, allow_custom)
|
||||
_add(self, stix_data, allow_custom, version)
|
||||
|
||||
def get(self, stix_id, _composite_filters=None):
|
||||
"""Retrieve STIX object from in-memory dict via STIX ID.
|
||||
|
@ -284,9 +290,6 @@ class MemorySource(DataSource):
|
|||
"""Retrieve STIX objects from in-memory dict via STIX ID, all versions
|
||||
of it.
|
||||
|
||||
Note: Since Memory sources/sinks don't handle multiple versions of a
|
||||
STIX object, this operation is unnecessary. Translate call to get().
|
||||
|
||||
Args:
|
||||
stix_id (str): The STIX ID of the STIX 2 object to retrieve.
|
||||
_composite_filters (FilterSet): collection of filters passed from
|
||||
|
@ -356,9 +359,9 @@ class MemorySource(DataSource):
|
|||
|
||||
return all_data
|
||||
|
||||
def load_from_file(self, file_path):
|
||||
with open(os.path.abspath(file_path), "r") as f:
|
||||
def load_from_file(self, file_path, version=None):
|
||||
with io.open(os.path.abspath(file_path), "r") as f:
|
||||
stix_data = json.load(f)
|
||||
|
||||
_add(self, stix_data, self.allow_custom)
|
||||
_add(self, stix_data, self.allow_custom, version)
|
||||
load_from_file.__doc__ = MemoryStore.load_from_file.__doc__
|
||||
|
|
|
@ -80,7 +80,7 @@ class TAXIICollectionSink(DataSink):
|
|||
|
||||
self.allow_custom = allow_custom
|
||||
|
||||
def add(self, stix_data):
|
||||
def add(self, stix_data, version=None):
|
||||
"""Add/push STIX content to TAXII Collection endpoint
|
||||
|
||||
Args:
|
||||
|
@ -88,6 +88,9 @@ class TAXIICollectionSink(DataSink):
|
|||
content in a STIX object (or Bundle), STIX object dict (or
|
||||
Bundle dict), or a STIX2 json encoded string, or list of
|
||||
any of the following.
|
||||
version (str): If present, it forces the parser to use the version
|
||||
provided. Otherwise, the library will make the best effort based
|
||||
on checking the "spec_version" property.
|
||||
|
||||
"""
|
||||
if isinstance(stix_data, _STIXBase):
|
||||
|
@ -103,7 +106,7 @@ class TAXIICollectionSink(DataSink):
|
|||
elif isinstance(stix_data, dict):
|
||||
# adding python dict (of either Bundle or STIX obj)
|
||||
if stix_data['type'] == 'bundle':
|
||||
bundle = parse(stix_data, allow_custom=self.allow_custom).serialize(encoding='utf-8', ensure_ascii=False)
|
||||
bundle = parse(stix_data, allow_custom=self.allow_custom, version=version).serialize(encoding='utf-8', ensure_ascii=False)
|
||||
elif 'spec_version' in stix_data:
|
||||
# If the spec_version is present, use new Bundle object...
|
||||
bundle = v21.Bundle(stix_data, allow_custom=self.allow_custom).serialize(encoding='utf-8', ensure_ascii=False)
|
||||
|
@ -113,12 +116,12 @@ class TAXIICollectionSink(DataSink):
|
|||
elif isinstance(stix_data, list):
|
||||
# adding list of something - recurse on each
|
||||
for obj in stix_data:
|
||||
self.add(obj)
|
||||
self.add(obj, version=version)
|
||||
return
|
||||
|
||||
elif isinstance(stix_data, str):
|
||||
# adding json encoded string of STIX content
|
||||
stix_data = parse(stix_data, allow_custom=self.allow_custom)
|
||||
stix_data = parse(stix_data, allow_custom=self.allow_custom, version=version)
|
||||
if stix_data['type'] == 'bundle':
|
||||
bundle = stix_data.serialize(encoding='utf-8', ensure_ascii=False)
|
||||
elif 'spec_version' in stix_data:
|
||||
|
@ -165,12 +168,15 @@ class TAXIICollectionSource(DataSource):
|
|||
|
||||
self.allow_custom = allow_custom
|
||||
|
||||
def get(self, stix_id, _composite_filters=None):
|
||||
def get(self, stix_id, version=None, _composite_filters=None):
|
||||
"""Retrieve STIX object from local/remote STIX Collection
|
||||
endpoint.
|
||||
|
||||
Args:
|
||||
stix_id (str): The STIX ID of the STIX object to be retrieved.
|
||||
version (str): If present, it forces the parser to use the version
|
||||
provided. Otherwise, the library will make the best effort based
|
||||
on checking the "spec_version" property.
|
||||
_composite_filters (FilterSet): collection of filters passed from
|
||||
the parent CompositeDataSource, not user supplied
|
||||
|
||||
|
@ -203,7 +209,7 @@ class TAXIICollectionSource(DataSource):
|
|||
raise DataSourceError("TAXII Collection resource returned error", e)
|
||||
|
||||
if len(stix_obj):
|
||||
stix_obj = parse(stix_obj[0], allow_custom=self.allow_custom)
|
||||
stix_obj = parse(stix_obj[0], allow_custom=self.allow_custom, version=version)
|
||||
if stix_obj.id != stix_id:
|
||||
# check - was added to handle erroneous TAXII servers
|
||||
stix_obj = None
|
||||
|
@ -212,12 +218,15 @@ class TAXIICollectionSource(DataSource):
|
|||
|
||||
return stix_obj
|
||||
|
||||
def all_versions(self, stix_id, _composite_filters=None):
|
||||
def all_versions(self, stix_id, version=None, _composite_filters=None):
|
||||
"""Retrieve STIX object from local/remote TAXII Collection
|
||||
endpoint, all versions of it
|
||||
|
||||
Args:
|
||||
stix_id (str): The STIX ID of the STIX objects to be retrieved.
|
||||
version (str): If present, it forces the parser to use the version
|
||||
provided. Otherwise, the library will make the best effort based
|
||||
on checking the "spec_version" property.
|
||||
_composite_filters (FilterSet): collection of filters passed from the parent
|
||||
CompositeDataSource, not user supplied
|
||||
|
||||
|
@ -234,14 +243,14 @@ class TAXIICollectionSource(DataSource):
|
|||
all_data = self.query(query=query, _composite_filters=_composite_filters)
|
||||
|
||||
# parse STIX objects from TAXII returned json
|
||||
all_data = [parse(stix_obj, allow_custom=self.allow_custom) for stix_obj in all_data]
|
||||
all_data = [parse(stix_obj, allow_custom=self.allow_custom, version=version) for stix_obj in all_data]
|
||||
|
||||
# check - was added to handle erroneous TAXII servers
|
||||
all_data_clean = [stix_obj for stix_obj in all_data if stix_obj.id == stix_id]
|
||||
|
||||
return all_data_clean
|
||||
|
||||
def query(self, query=None, _composite_filters=None):
|
||||
def query(self, query=None, version=None, _composite_filters=None):
|
||||
"""Search and retreive STIX objects based on the complete query
|
||||
|
||||
A "complete query" includes the filters from the query, the filters
|
||||
|
@ -250,6 +259,9 @@ class TAXIICollectionSource(DataSource):
|
|||
|
||||
Args:
|
||||
query (list): list of filters to search on
|
||||
version (str): If present, it forces the parser to use the version
|
||||
provided. Otherwise, the library will make the best effort based
|
||||
on checking the "spec_version" property.
|
||||
_composite_filters (FilterSet): collection of filters passed from
|
||||
the CompositeDataSource, not user supplied
|
||||
|
||||
|
@ -294,7 +306,7 @@ class TAXIICollectionSource(DataSource):
|
|||
)
|
||||
|
||||
# parse python STIX objects from the STIX object dicts
|
||||
stix_objs = [parse(stix_obj_dict, allow_custom=self.allow_custom) for stix_obj_dict in all_data]
|
||||
stix_objs = [parse(stix_obj_dict, allow_custom=self.allow_custom, version=version) for stix_obj_dict in all_data]
|
||||
|
||||
return stix_objs
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"type": "identity",
|
||||
"id": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"created": "2017-06-01T00:00:00.000Z",
|
||||
"modified": "2018-11-01T23:24:48.446Z",
|
||||
"name": "The MITRE Corporation",
|
||||
"identity_class": "organization",
|
||||
"labels": [
|
||||
"version two"
|
||||
]
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"id": "bundle--f64de948-7067-4534-8018-85f03d470625",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:32:58.226477Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"description": "Rover is malware suspected of being used for espionage purposes. It was used in 2015 in a targeted email sent to an Indian Ambassador to Afghanistan.[[Citation: Palo Alto Rover]]",
|
||||
"external_references": [
|
||||
{
|
||||
"external_id": "S0090",
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Software/S0090"
|
||||
},
|
||||
{
|
||||
"description": "Ray, V., Hayashi, K. (2016, February 29). New Malware \u2018Rover\u2019 Targets Indian Ambassador to Afghanistan. Retrieved February 29, 2016.",
|
||||
"source_name": "Palo Alto Rover",
|
||||
"url": "http://researchcenter.paloaltonetworks.com/2016/02/new-malware-rover-targets-indian-ambassador-to-afghanistan/"
|
||||
}
|
||||
],
|
||||
"id": "malware--6b616fc1-1505-48e3-8b2c-0d19337bff38",
|
||||
"labels": [
|
||||
"malware"
|
||||
],
|
||||
"modified": "2017-05-31T21:32:58.226477Z",
|
||||
"name": "Rover",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"type": "malware"
|
||||
}
|
||||
],
|
||||
"spec_version": "2.0",
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
{
|
||||
"type": "malware",
|
||||
"id": "malware--6b616fc1-1505-48e3-8b2c-0d19337bff38",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"created": "2017-05-31T21:32:58.226Z",
|
||||
"modified": "2018-11-01T23:24:48.456Z",
|
||||
"name": "Rover",
|
||||
"description": "Rover is malware suspected of being used for espionage purposes. It was used in 2015 in a targeted email sent to an Indian Ambassador to Afghanistan.[[Citation: Palo Alto Rover]]",
|
||||
"labels": [
|
||||
"version two"
|
||||
],
|
||||
"external_references": [
|
||||
{
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Software/S0090",
|
||||
"external_id": "S0090"
|
||||
},
|
||||
{
|
||||
"source_name": "Palo Alto Rover",
|
||||
"description": "Ray, V., Hayashi, K. (2016, February 29). New Malware \u2018Rover\u2019 Targets Indian Ambassador to Afghanistan. Retrieved February 29, 2016.",
|
||||
"url": "http://researchcenter.paloaltonetworks.com/2016/02/new-malware-rover-targets-indian-ambassador-to-afghanistan/"
|
||||
}
|
||||
],
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
]
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
{
|
||||
"type": "malware",
|
||||
"id": "malware--6b616fc1-1505-48e3-8b2c-0d19337bff38",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"created": "2017-05-31T21:32:58.226Z",
|
||||
"modified": "2018-11-01T23:24:48.457Z",
|
||||
"name": "Rover",
|
||||
"description": "Rover is malware suspected of being used for espionage purposes. It was used in 2015 in a targeted email sent to an Indian Ambassador to Afghanistan.[[Citation: Palo Alto Rover]]",
|
||||
"labels": [
|
||||
"version three"
|
||||
],
|
||||
"external_references": [
|
||||
{
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Software/S0090",
|
||||
"external_id": "S0090"
|
||||
},
|
||||
{
|
||||
"source_name": "Palo Alto Rover",
|
||||
"description": "Ray, V., Hayashi, K. (2016, February 29). New Malware \u2018Rover\u2019 Targets Indian Ambassador to Afghanistan. Retrieved February 29, 2016.",
|
||||
"url": "http://researchcenter.paloaltonetworks.com/2016/02/new-malware-rover-targets-indian-ambassador-to-afghanistan/"
|
||||
}
|
||||
],
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
]
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
{
|
||||
"id": "bundle--f68640b4-0cdc-42ae-b176-def1754a1ea0",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:30:19.73501Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"description": "Credential dumping is the process of obtaining account login and password information from the operating system and software. Credentials can be used to perform Windows Credential Editor, Mimikatz, and gsecdump. These tools are in use by both professional security testers and adversaries.\n\nPlaintext passwords can be obtained using tools such as Mimikatz to extract passwords stored by the Local Security Authority (LSA). If smart cards are used to authenticate to a domain using a personal identification number (PIN), then that PIN is also cached as a result and may be dumped.Mimikatz access the LSA Subsystem Service (LSASS) process by opening the process, locating the LSA secrets key, and decrypting the sections in memory where credential details are stored. Credential dumpers may also use methods for reflective DLL Injection to reduce potential indicators of malicious activity.\n\nNTLM hash dumpers open the Security Accounts Manager (SAM) on the local file system (%SystemRoot%/system32/config/SAM) or create a dump of the Registry SAM key to access stored account password hashes. Some hash dumpers will open the local file system as a device and parse to the SAM table to avoid file access defenses. Others will make an in-memory copy of the SAM table before reading hashes. Detection of compromised Legitimate Credentials in-use by adversaries may help as well. \n\nOn Windows 8.1 and Windows Server 2012 R2, monitor Windows Logs for LSASS.exe creation to verify that LSASS started as a protected process.\n\nMonitor processes and command-line arguments for program execution that may be indicative of credential dumping. Remote access tools may contain built-in features or incorporate existing tools like Mimikatz. PowerShell scripts also exist that contain credential dumping functionality, such as PowerSploit's Invoke-Mimikatz module,[[Citation: Powersploit]] which may require additional logging features to be configured in the operating system to collect necessary information for analysis.\n\nPlatforms: Windows Server 2003, Windows Server 2008, Windows Server 2012, Windows XP, Windows 7, Windows 8, Windows Server 2003 R2, Windows Server 2008 R2, Windows Server 2012 R2, Windows Vista, Windows 8.1\n\nData Sources: API monitoring, Process command-line parameters, Process monitoring, PowerShell logs",
|
||||
"external_references": [
|
||||
{
|
||||
"external_id": "T1003",
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Technique/T1003"
|
||||
},
|
||||
{
|
||||
"description": "Delpy, B. (2014, September 14). Mimikatz module ~ sekurlsa. Retrieved January 10, 2016.",
|
||||
"source_name": "Github Mimikatz Module sekurlsa",
|
||||
"url": "https://github.com/gentilkiwi/mimikatz/wiki/module-~-sekurlsa"
|
||||
},
|
||||
{
|
||||
"description": "PowerSploit. (n.d.). Retrieved December 4, 2014.",
|
||||
"source_name": "Powersploit",
|
||||
"url": "https://github.com/mattifestation/PowerSploit"
|
||||
}
|
||||
],
|
||||
"id": "attack-pattern--0a3ead4e-6d47-4ccb-854c-a6a4f9d96b22",
|
||||
"kill_chain_phases": [
|
||||
{
|
||||
"kill_chain_name": "mitre-attack",
|
||||
"phase_name": "credential-access"
|
||||
}
|
||||
],
|
||||
"modified": "2017-05-31T21:30:19.73501Z",
|
||||
"name": "Credential Dumping",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"spec_version": "2.1",
|
||||
"type": "attack-pattern"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
{
|
||||
"id": "bundle--b07d6fd6-7cc5-492d-a1eb-9ba956b329d5",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:30:26.496201Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"description": "Rootkits are programs that hide the existence of malware by intercepting and modifying operating system API calls that supply system information. Rootkits or rootkit enabling functionality may reside at the user or kernel level in the operating system or lower, to include a Hypervisor, Master Boot Record, or the Basic Input/Output System.[[Citation: Wikipedia Rootkit]]\n\nAdversaries may use rootkits to hide the presence of programs, files, network connections, services, drivers, and other system components.\n\nDetection: Some rootkit protections may be built into anti-virus or operating system software. There are dedicated rootkit detection tools that look for specific types of rootkit behavior. Monitor for the existence of unrecognized DLLs, devices, services, and changes to the MBR.[[Citation: Wikipedia Rootkit]]\n\nPlatforms: Windows Server 2003, Windows Server 2008, Windows Server 2012, Windows XP, Windows 7, Windows 8, Windows Server 2003 R2, Windows Server 2008 R2, Windows Server 2012 R2, Windows Vista, Windows 8.1\n\nData Sources: BIOS, MBR, System calls",
|
||||
"external_references": [
|
||||
{
|
||||
"external_id": "T1014",
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Technique/T1014"
|
||||
},
|
||||
{
|
||||
"description": "Wikipedia. (2016, June 1). Rootkit. Retrieved June 2, 2016.",
|
||||
"source_name": "Wikipedia Rootkit",
|
||||
"url": "https://en.wikipedia.org/wiki/Rootkit"
|
||||
}
|
||||
],
|
||||
"id": "attack-pattern--0f20e3cb-245b-4a61-8a91-2d93f7cb0e9b",
|
||||
"kill_chain_phases": [
|
||||
{
|
||||
"kill_chain_name": "mitre-attack",
|
||||
"phase_name": "defense-evasion"
|
||||
}
|
||||
],
|
||||
"modified": "2017-05-31T21:30:26.496201Z",
|
||||
"name": "Rootkit",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"spec_version": "2.1",
|
||||
"type": "attack-pattern"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
{
|
||||
"id": "bundle--1a854c96-639e-4771-befb-e7b960a65974",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:30:29.45894Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"description": "Data, such as sensitive documents, may be exfiltrated through the use of automated processing or Scripting after being gathered during Exfiltration Over Command and Control Channel and Exfiltration Over Alternative Protocol.\n\nDetection: Monitor process file access patterns and network behavior. Unrecognized processes or scripts that appear to be traversing file systems and sending network traffic may be suspicious.\n\nPlatforms: Windows Server 2003, Windows Server 2008, Windows Server 2012, Windows XP, Windows 7, Windows 8, Windows Server 2003 R2, Windows Server 2008 R2, Windows Server 2012 R2, Windows Vista, Windows 8.1\n\nData Sources: File monitoring, Process monitoring, Process use of network",
|
||||
"external_references": [
|
||||
{
|
||||
"external_id": "T1020",
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Technique/T1020"
|
||||
}
|
||||
],
|
||||
"id": "attack-pattern--774a3188-6ba9-4dc4-879d-d54ee48a5ce9",
|
||||
"kill_chain_phases": [
|
||||
{
|
||||
"kill_chain_name": "mitre-attack",
|
||||
"phase_name": "exfiltration"
|
||||
}
|
||||
],
|
||||
"modified": "2017-05-31T21:30:29.45894Z",
|
||||
"name": "Automated Exfiltration",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"spec_version": "2.1",
|
||||
"type": "attack-pattern"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
{
|
||||
"id": "bundle--33e3e33a-38b8-4a37-9455-5b8c82d3b10a",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:30:45.139269Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"description": "Adversaries may attempt to get a listing of network connections to or from the compromised system.\nUtilities and commands that acquire this information include netstat, \"net use,\" and \"net session\" with Net.\n\nDetection: System and network discovery techniques normally occur throughout an operation as an adversary learns the environment. Data and events should not be viewed in isolation, but as part of a chain of behavior that could lead to other activities, such as Windows Management Instrumentation and PowerShell.\n\nPlatforms: Windows Server 2003, Windows Server 2008, Windows Server 2012, Windows XP, Windows 7, Windows 8, Windows Server 2003 R2, Windows Server 2008 R2, Windows Server 2012 R2, Windows Vista, Windows 8.1\n\nData Sources: Process command-line parameters, Process monitoring",
|
||||
"external_references": [
|
||||
{
|
||||
"external_id": "T1049",
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Technique/T1049"
|
||||
}
|
||||
],
|
||||
"id": "attack-pattern--7e150503-88e7-4861-866b-ff1ac82c4475",
|
||||
"kill_chain_phases": [
|
||||
{
|
||||
"kill_chain_name": "mitre-attack",
|
||||
"phase_name": "discovery"
|
||||
}
|
||||
],
|
||||
"modified": "2017-05-31T21:30:45.139269Z",
|
||||
"name": "Local Network Connections Discovery",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"spec_version": "2.1",
|
||||
"type": "attack-pattern"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
{
|
||||
"id": "bundle--a87938c5-cc1e-4e06-a8a3-b10243ae397d",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:30:41.022897Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"description": "Sensitive data can be collected from remote systems via shared network drives (host shared directory, network file server, etc.) that are accessible from the current system prior to cmd may be used to gather information.\n\nDetection: Monitor processes and command-line arguments for actions that could be taken to collect files from a network share. Remote access tools with built-in features may interact directly with the Windows API to gather data. Data may also be acquired through Windows system management tools such as Windows Management Instrumentation and PowerShell.\n\nPlatforms: Windows Server 2003, Windows Server 2008, Windows Server 2012, Windows XP, Windows 7, Windows 8, Windows Server 2003 R2, Windows Server 2008 R2, Windows Server 2012 R2, Windows Vista, Windows 8.1\n\nData Sources: File monitoring, Process monitoring, Process command-line parameters",
|
||||
"external_references": [
|
||||
{
|
||||
"external_id": "T1039",
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Technique/T1039"
|
||||
}
|
||||
],
|
||||
"id": "attack-pattern--ae676644-d2d2-41b7-af7e-9bed1b55898c",
|
||||
"kill_chain_phases": [
|
||||
{
|
||||
"kill_chain_name": "mitre-attack",
|
||||
"phase_name": "collection"
|
||||
}
|
||||
],
|
||||
"modified": "2017-05-31T21:30:41.022897Z",
|
||||
"name": "Data from Network Shared Drive",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"spec_version": "2.1",
|
||||
"type": "attack-pattern"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
{
|
||||
"id": "bundle--5ddaeff9-eca7-4094-9e65-4f53da21a444",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:30:32.662702Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"description": "Adversaries may attempt to make an executable or file difficult to discover or analyze by encrypting, encoding, or otherwise obfuscating its contents on the system.\n\nDetection: Detection of file obfuscation is difficult unless artifacts are left behind by the obfuscation process that are uniquely detectable with a signature. If detection of the obfuscation itself is not possible, it may be possible to detect the malicious activity that caused the obfuscated file (for example, the method that was used to write, read, or modify the file on the file system).\n\nPlatforms: Windows Server 2003, Windows Server 2008, Windows Server 2012, Windows XP, Windows 7, Windows 8, Windows Server 2003 R2, Windows Server 2008 R2, Windows Server 2012 R2, Windows Vista, Windows 8.1\n\nData Sources: Network protocol analysis, Process use of network, Binary file metadata, File monitoring, Malware reverse engineering",
|
||||
"external_references": [
|
||||
{
|
||||
"external_id": "T1027",
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Technique/T1027"
|
||||
}
|
||||
],
|
||||
"id": "attack-pattern--b3d682b6-98f2-4fb0-aa3b-b4df007ca70a",
|
||||
"kill_chain_phases": [
|
||||
{
|
||||
"kill_chain_name": "mitre-attack",
|
||||
"phase_name": "defense-evasion"
|
||||
}
|
||||
],
|
||||
"modified": "2017-05-31T21:30:32.662702Z",
|
||||
"name": "Obfuscated Files or Information",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"spec_version": "2.1",
|
||||
"type": "attack-pattern"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"id": "bundle--a42d26fe-c938-4074-a1b3-50d852e6f0bd",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:30:26.495974Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"description": "Identify potentially malicious software that may contain rootkit functionality, and audit and/or block it by using whitelisting[[CiteRef::Beechey 2010]] tools, like AppLocker,[[CiteRef::Windows Commands JPCERT]][[CiteRef::NSA MS AppLocker]] or Software Restriction Policies[[CiteRef::Corio 2008]] where appropriate.[[CiteRef::TechNet Applocker vs SRP]]",
|
||||
"id": "course-of-action--95ddb356-7ba0-4bd9-a889-247262b8946f",
|
||||
"modified": "2017-05-31T21:30:26.495974Z",
|
||||
"name": "Rootkit Mitigation",
|
||||
"spec_version": "2.1",
|
||||
"type": "course-of-action"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"created": "2017-05-31T21:30:41.022744Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"description": "Identify unnecessary system utilities or potentially malicious software that may be used to collect data from a network share, and audit and/or block them by using whitelisting[[CiteRef::Beechey 2010]] tools, like AppLocker,[[CiteRef::Windows Commands JPCERT]][[CiteRef::NSA MS AppLocker]] or Software Restriction Policies[[CiteRef::Corio 2008]] where appropriate.[[CiteRef::TechNet Applocker vs SRP]]",
|
||||
"id": "course-of-action--d9727aee-48b8-4fdb-89e2-4c49746ba4dd",
|
||||
"modified": "2017-05-31T21:30:41.022744Z",
|
||||
"name": "Data from Network Shared Drive Mitigation",
|
||||
"spec_version": "2.1",
|
||||
"type": "course-of-action"
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"id": "bundle--81884287-2548-47fc-a997-39489ddd5462",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-06-01T00:00:00Z",
|
||||
"id": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"identity_class": "organization",
|
||||
"modified": "2017-06-01T00:00:00Z",
|
||||
"name": "The MITRE Corporation",
|
||||
"spec_version": "2.1",
|
||||
"type": "identity"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
{
|
||||
"id": "bundle--7790ee4c-2d57-419a-bc9d-8805b5bb4118",
|
||||
"objects": [
|
||||
{
|
||||
"aliases": [
|
||||
"Deep Panda",
|
||||
"Shell Crew",
|
||||
"WebMasters",
|
||||
"KungFu Kittens",
|
||||
"PinkPanther",
|
||||
"Black Vine"
|
||||
],
|
||||
"created": "2017-05-31T21:31:49.412497Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"description": "Deep Panda is a suspected Chinese threat group known to target many industries, including government, defense, financial, and telecommunications.Deep Panda.Deep Panda also appears to be known as Black Vine based on the attribution of both group names to the Anthem intrusion.[[Citation: Symantec Black Vine]]",
|
||||
"external_references": [
|
||||
{
|
||||
"external_id": "G0009",
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Group/G0009"
|
||||
},
|
||||
{
|
||||
"description": "Alperovitch, D. (2014, July 7). Deep in Thought: Chinese Targeting of National Security Think Tanks. Retrieved November 12, 2014.",
|
||||
"source_name": "Alperovitch 2014",
|
||||
"url": "http://blog.crowdstrike.com/deep-thought-chinese-targeting-national-security-think-tanks/"
|
||||
},
|
||||
{
|
||||
"description": "DiMaggio, J.. (2015, August 6). The Black Vine cyberespionage group. Retrieved January 26, 2016.",
|
||||
"source_name": "Symantec Black Vine",
|
||||
"url": "http://www.symantec.com/content/en/us/enterprise/media/security%20response/whitepapers/the-black-vine-cyberespionage-group.pdf"
|
||||
},
|
||||
{
|
||||
"description": "RSA Incident Response. (2014, January). RSA Incident Response Emerging Threat Profile: Shell Crew. Retrieved January 14, 2016.",
|
||||
"source_name": "RSA Shell Crew",
|
||||
"url": "https://www.emc.com/collateral/white-papers/h12756-wp-shell-crew.pdf"
|
||||
},
|
||||
{
|
||||
"description": "ThreatConnect Research Team. (2015, February 27). The Anthem Hack: All Roads Lead to China. Retrieved January 26, 2016.",
|
||||
"source_name": "ThreatConnect Anthem",
|
||||
"url": "https://www.threatconnect.com/the-anthem-hack-all-roads-lead-to-china/"
|
||||
}
|
||||
],
|
||||
"id": "intrusion-set--a653431d-6a5e-4600-8ad3-609b5af57064",
|
||||
"modified": "2017-05-31T21:31:49.412497Z",
|
||||
"name": "Deep Panda",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"spec_version": "2.1",
|
||||
"type": "intrusion-set"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
{
|
||||
"id": "bundle--96a6ea7a-fcff-4aab-925b-a494bcdf0480",
|
||||
"objects": [
|
||||
{
|
||||
"aliases": [
|
||||
"DragonOK"
|
||||
],
|
||||
"created": "2017-05-31T21:31:53.197755Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"description": "DragonOK is a threat group that has targeted Japanese organizations with phishing emails. Due to overlapping TTPs, including similar custom tools, DragonOK is thought to have a direct or indirect relationship with the threat group Moafee. [[Citation: Operation Quantum Entanglement]][[Citation: Symbiotic APT Groups]] It is known to use a variety of malware, including Sysget/HelloBridge, PlugX, PoisonIvy, FormerFirstRat, NFlog, and NewCT. [[Citation: New DragonOK]]",
|
||||
"external_references": [
|
||||
{
|
||||
"external_id": "G0017",
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Group/G0017"
|
||||
},
|
||||
{
|
||||
"description": "Haq, T., Moran, N., Vashisht, S., Scott, M. (2014, September). OPERATION QUANTUM ENTANGLEMENT. Retrieved November 4, 2015.",
|
||||
"source_name": "Operation Quantum Entanglement",
|
||||
"url": "https://www.fireeye.com/content/dam/fireeye-www/global/en/current-threats/pdfs/wp-operation-quantum-entanglement.pdf"
|
||||
},
|
||||
{
|
||||
"description": "Haq, T. (2014, October). An Insight into Symbiotic APT Groups. Retrieved November 4, 2015.",
|
||||
"source_name": "Symbiotic APT Groups",
|
||||
"url": "https://dl.mandiant.com/EE/library/MIRcon2014/MIRcon%202014%20R&D%20Track%20Insight%20into%20Symbiotic%20APT.pdf"
|
||||
},
|
||||
{
|
||||
"description": "Miller-Osborn, J., Grunzweig, J.. (2015, April). Unit 42 Identifies New DragonOK Backdoor Malware Deployed Against Japanese Targets. Retrieved November 4, 2015.",
|
||||
"source_name": "New DragonOK",
|
||||
"url": "http://researchcenter.paloaltonetworks.com/2015/04/unit-42-identifies-new-dragonok-backdoor-malware-deployed-against-japanese-targets/"
|
||||
}
|
||||
],
|
||||
"id": "intrusion-set--f3bdec95-3d62-42d9-a840-29630f6cdc1a",
|
||||
"modified": "2017-05-31T21:31:53.197755Z",
|
||||
"name": "DragonOK",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"spec_version": "2.1",
|
||||
"type": "intrusion-set"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,35 +1,28 @@
|
|||
{
|
||||
"id": "bundle--f64de948-7067-4534-8018-85f03d470625",
|
||||
"objects": [
|
||||
"type": "malware",
|
||||
"spec_version": "2.1",
|
||||
"id": "malware--6b616fc1-1505-48e3-8b2c-0d19337bff38",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"created": "2017-05-31T21:32:58.226Z",
|
||||
"modified": "2018-11-16T22:54:20.390Z",
|
||||
"name": "Rover",
|
||||
"malware_types": [
|
||||
"version four"
|
||||
],
|
||||
"description": "Rover is malware suspected of being used for espionage purposes. It was used in 2015 in a targeted email sent to an Indian Ambassador to Afghanistan.[[Citation: Palo Alto Rover]]",
|
||||
"external_references": [
|
||||
{
|
||||
"created": "2017-05-31T21:32:58.226477Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"description": "Rover is malware suspected of being used for espionage purposes. It was used in 2015 in a targeted email sent to an Indian Ambassador to Afghanistan.[[Citation: Palo Alto Rover]]",
|
||||
"external_references": [
|
||||
{
|
||||
"external_id": "S0090",
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Software/S0090"
|
||||
},
|
||||
{
|
||||
"description": "Ray, V., Hayashi, K. (2016, February 29). New Malware \u2018Rover\u2019 Targets Indian Ambassador to Afghanistan. Retrieved February 29, 2016.",
|
||||
"source_name": "Palo Alto Rover",
|
||||
"url": "http://researchcenter.paloaltonetworks.com/2016/02/new-malware-rover-targets-indian-ambassador-to-afghanistan/"
|
||||
}
|
||||
],
|
||||
"id": "malware--6b616fc1-1505-48e3-8b2c-0d19337bff38",
|
||||
"malware_types": [
|
||||
"malware"
|
||||
],
|
||||
"modified": "2017-05-31T21:32:58.226477Z",
|
||||
"name": "Rover",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"spec_version": "2.1",
|
||||
"type": "malware",
|
||||
"is_family": false
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Software/S0090",
|
||||
"external_id": "S0090"
|
||||
},
|
||||
{
|
||||
"source_name": "Palo Alto Rover",
|
||||
"description": "Ray, V., Hayashi, K. (2016, February 29). New Malware \u2018Rover\u2019 Targets Indian Ambassador to Afghanistan. Retrieved February 29, 2016.",
|
||||
"url": "http://researchcenter.paloaltonetworks.com/2016/02/new-malware-rover-targets-indian-ambassador-to-afghanistan/"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
"id": "bundle--c633942b-545c-4c87-91b7-9fe5740365e0",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:33:26.565056Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"description": "RTM is custom malware written in Delphi. It is used by the group of the same name (RTM).[[Citation: ESET RTM Feb 2017]]",
|
||||
"external_references": [
|
||||
{
|
||||
"external_id": "S0148",
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Software/S0148"
|
||||
},
|
||||
{
|
||||
"description": "Faou, M. and Boutin, J.. (2017, February). Read The Manual: A Guide to the RTM Banking Trojan. Retrieved March 9, 2017.",
|
||||
"source_name": "ESET RTM Feb 2017",
|
||||
"url": "https://www.welivesecurity.com/wp-content/uploads/2017/02/Read-The-Manual.pdf"
|
||||
}
|
||||
],
|
||||
"id": "malware--92ec0cbd-2c30-44a2-b270-73f4ec949841",
|
||||
"malware_types": [
|
||||
"malware"
|
||||
],
|
||||
"modified": "2017-05-31T21:33:26.565056Z",
|
||||
"name": "RTM",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"spec_version": "2.1",
|
||||
"type": "malware",
|
||||
"is_family": false
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
"id": "bundle--09ce4338-8741-4fcf-9738-d216c8e40974",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:32:48.482655Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"description": "Sakula is a remote access tool (RAT) that first surfaced in 2012 and was used in intrusions throughout 2015.[[Citation: Dell Sakula]]\n\nAliases: Sakula, Sakurel, VIPER",
|
||||
"external_references": [
|
||||
{
|
||||
"external_id": "S0074",
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Software/S0074"
|
||||
},
|
||||
{
|
||||
"description": "Dell SecureWorks Counter Threat Unit Threat Intelligence. (2015, July 30). Sakula Malware Family. Retrieved January 26, 2016.",
|
||||
"source_name": "Dell Sakula",
|
||||
"url": "http://www.secureworks.com/cyber-threat-intelligence/threats/sakula-malware-family/"
|
||||
}
|
||||
],
|
||||
"id": "malware--96b08451-b27a-4ff6-893f-790e26393a8e",
|
||||
"malware_types": [
|
||||
"malware"
|
||||
],
|
||||
"modified": "2017-05-31T21:32:48.482655Z",
|
||||
"name": "Sakula",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"spec_version": "2.1",
|
||||
"type": "malware",
|
||||
"is_family": false
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
"id": "bundle--611947ce-ae3b-4fdb-b297-aed8eab22e4f",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:32:15.263882Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"description": "PoisonIvy is a popular remote access tool (RAT) that has been used by many groups.[[Citation: FireEye Poison Ivy]]\n\nAliases: PoisonIvy, Poison Ivy",
|
||||
"external_references": [
|
||||
{
|
||||
"external_id": "S0012",
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Software/S0012"
|
||||
},
|
||||
{
|
||||
"description": "FireEye. (2014). POISON IVY: Assessing Damage and Extracting Intelligence. Retrieved November 12, 2014.",
|
||||
"source_name": "FireEye Poison Ivy",
|
||||
"url": "https://www.fireeye.com/content/dam/fireeye-www/global/en/current-threats/pdfs/rpt-poison-ivy.pdf"
|
||||
}
|
||||
],
|
||||
"id": "malware--b42378e0-f147-496f-992a-26a49705395b",
|
||||
"malware_types": [
|
||||
"malware"
|
||||
],
|
||||
"modified": "2017-05-31T21:32:15.263882Z",
|
||||
"name": "PoisonIvy",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"spec_version": "2.1",
|
||||
"type": "malware",
|
||||
"is_family": false
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -13,4 +13,4 @@
|
|||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"id": "bundle--7e715462-dd9d-40b9-968a-10ef0ecf126d",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:33:27.182784Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"id": "relationship--0d4a7788-7f3b-4df8-a498-31a38003c883",
|
||||
"modified": "2017-05-31T21:33:27.182784Z",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"relationship_type": "uses",
|
||||
"source_ref": "attack-pattern--b3d682b6-98f2-4fb0-aa3b-b4df007ca70a",
|
||||
"spec_version": "2.1",
|
||||
"target_ref": "malware--92ec0cbd-2c30-44a2-b270-73f4ec949841",
|
||||
"type": "relationship"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"id": "bundle--a53eef35-abfc-4bcd-b84e-a048f7b4a9bf",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:33:27.082801Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"id": "relationship--0e55ee98-0c6d-43d4-b424-b18a0036b227",
|
||||
"modified": "2017-05-31T21:33:27.082801Z",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"relationship_type": "uses",
|
||||
"source_ref": "attack-pattern--0a3ead4e-6d47-4ccb-854c-a6a4f9d96b22",
|
||||
"spec_version": "2.1",
|
||||
"target_ref": "malware--92ec0cbd-2c30-44a2-b270-73f4ec949841",
|
||||
"type": "relationship"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"id": "bundle--0b9f6412-314f-44e3-8779-9738c9578ef5",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:33:27.018782Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"id": "relationship--1e91cd45-a725-4965-abe3-700694374432",
|
||||
"modified": "2017-05-31T21:33:27.018782Z",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"relationship_type": "mitigates",
|
||||
"source_ref": "course-of-action--95ddb356-7ba0-4bd9-a889-247262b8946f",
|
||||
"spec_version": "2.1",
|
||||
"target_ref": "malware--92ec0cbd-2c30-44a2-b270-73f4ec949841",
|
||||
"type": "relationship"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"id": "bundle--6d5b04a8-efb2-4179-990e-74f1dcc76e0c",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:33:27.100701Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"id": "relationship--3a3084f9-0302-4fd5-9b8a-e0db10f5345e",
|
||||
"modified": "2017-05-31T21:33:27.100701Z",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"relationship_type": "uses",
|
||||
"source_ref": "attack-pattern--7e150503-88e7-4861-866b-ff1ac82c4475",
|
||||
"spec_version": "2.1",
|
||||
"target_ref": "malware--92ec0cbd-2c30-44a2-b270-73f4ec949841",
|
||||
"type": "relationship"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"id": "bundle--a7efc025-040d-49c7-bf97-e5a1120ecacc",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:33:27.143973Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"id": "relationship--3a3ed0b2-0c38-441f-ac40-53b873e545d1",
|
||||
"modified": "2017-05-31T21:33:27.143973Z",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"relationship_type": "uses",
|
||||
"source_ref": "attack-pattern--774a3188-6ba9-4dc4-879d-d54ee48a5ce9",
|
||||
"spec_version": "2.1",
|
||||
"target_ref": "malware--92ec0cbd-2c30-44a2-b270-73f4ec949841",
|
||||
"type": "relationship"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"id": "bundle--9f013d47-7704-41c2-9749-23d0d94af94d",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:33:27.021562Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"id": "relationship--592d0c31-e61f-495e-a60e-70d7be59a719",
|
||||
"modified": "2017-05-31T21:33:27.021562Z",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"relationship_type": "mitigates",
|
||||
"source_ref": "course-of-action--d9727aee-48b8-4fdb-89e2-4c49746ba4dd",
|
||||
"spec_version": "2.1",
|
||||
"target_ref": "malware--92ec0cbd-2c30-44a2-b270-73f4ec949841",
|
||||
"type": "relationship"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"id": "bundle--15167b24-4cee-4c96-a140-32a6c37df4b4",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:33:27.044387Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"id": "relationship--70dc6b5c-c524-429e-a6ab-0dd40f0482c1",
|
||||
"modified": "2017-05-31T21:33:27.044387Z",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"relationship_type": "uses",
|
||||
"source_ref": "intrusion-set--a653431d-6a5e-4600-8ad3-609b5af57064",
|
||||
"spec_version": "2.1",
|
||||
"target_ref": "malware--92ec0cbd-2c30-44a2-b270-73f4ec949841",
|
||||
"type": "relationship"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"id": "bundle--ff845dca-7036-416f-aae0-95030994c49f",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:33:27.051532Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"id": "relationship--8797579b-e3be-4209-a71b-255a4d08243d",
|
||||
"modified": "2017-05-31T21:33:27.051532Z",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"relationship_type": "uses",
|
||||
"source_ref": "intrusion-set--f3bdec95-3d62-42d9-a840-29630f6cdc1a",
|
||||
"spec_version": "2.1",
|
||||
"target_ref": "malware--92ec0cbd-2c30-44a2-b270-73f4ec949841",
|
||||
"type": "relationship"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
{
|
||||
"id": "bundle--d8826afc-1561-4362-a4e3-05a4c2c3ac3c",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:32:31.601148Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"description": "The Net utility is a component of the Windows operating system. It is used in command-line operations for control of users, groups, services, and network connections.Net has a great deal of functionality,[[Citation: Savill 1999]] much of which is useful for an adversary, such as gathering system and network information for [[Discovery]], moving laterally through [[Windows admin shares]] using <code>net use</code> commands, and interacting with services.\n\nAliases: Net, net.exe",
|
||||
"external_references": [
|
||||
{
|
||||
"external_id": "S0039",
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Software/S0039"
|
||||
},
|
||||
{
|
||||
"description": "Microsoft. (2006, October 18). Net.exe Utility. Retrieved September 22, 2015.",
|
||||
"source_name": "Microsoft Net Utility",
|
||||
"url": "https://msdn.microsoft.com/en-us/library/aa939914"
|
||||
},
|
||||
{
|
||||
"description": "Savill, J. (1999, March 4). Net.exe reference. Retrieved September 22, 2015.",
|
||||
"source_name": "Savill 1999",
|
||||
"url": "http://windowsitpro.com/windows/netexe-reference"
|
||||
}
|
||||
],
|
||||
"id": "tool--03342581-f790-4f03-ba41-e82e67392e23",
|
||||
"tool_types": [
|
||||
"tool"
|
||||
],
|
||||
"modified": "2017-05-31T21:32:31.601148Z",
|
||||
"name": "Net",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"spec_version": "2.1",
|
||||
"type": "tool"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"id": "bundle--7dbde18f-6f14-4bf0-8389-505c89d6d5a6",
|
||||
"objects": [
|
||||
{
|
||||
"created": "2017-05-31T21:32:12.684914Z",
|
||||
"created_by_ref": "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5",
|
||||
"description": "Windows Credential Editor is a password dumping tool.[[Citation: Amplia WCE]]\n\nAliases: Windows Credential Editor, WCE",
|
||||
"external_references": [
|
||||
{
|
||||
"external_id": "S0005",
|
||||
"source_name": "mitre-attack",
|
||||
"url": "https://attack.mitre.org/wiki/Software/S0005"
|
||||
},
|
||||
{
|
||||
"description": "Amplia Security. (n.d.). Windows Credentials Editor (WCE) F.A.Q.. Retrieved December 17, 2015.",
|
||||
"source_name": "Amplia WCE",
|
||||
"url": "http://www.ampliasecurity.com/research/wcefaq.html"
|
||||
}
|
||||
],
|
||||
"id": "tool--242f3da3-4425-4d11-8f5c-b842886da966",
|
||||
"tool_types": [
|
||||
"tool"
|
||||
],
|
||||
"modified": "2017-05-31T21:32:12.684914Z",
|
||||
"name": "Windows Credential Editor",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
|
||||
],
|
||||
"spec_version": "2.1",
|
||||
"type": "tool"
|
||||
}
|
||||
],
|
||||
"type": "bundle"
|
||||
}
|
|
@ -1,10 +1,18 @@
|
|||
import datetime
|
||||
import errno
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import stat
|
||||
|
||||
import pytest
|
||||
import pytz
|
||||
|
||||
import stix2
|
||||
from stix2.datastore.filesystem import (AuthSet, _find_search_optimizations,
|
||||
_get_matching_dir_entries,
|
||||
_timestamp2filename)
|
||||
from stix2.exceptions import STIXError
|
||||
|
||||
from .constants import (
|
||||
CAMPAIGN_ID, CAMPAIGN_KWARGS, IDENTITY_ID, IDENTITY_KWARGS, INDICATOR_ID,
|
||||
|
@ -96,7 +104,20 @@ def rel_fs_store():
|
|||
yield fs
|
||||
|
||||
for o in stix_objs:
|
||||
os.remove(os.path.join(FS_PATH, o.type, o.id + '.json'))
|
||||
filepath = os.path.join(FS_PATH, o.type, o.id,
|
||||
_timestamp2filename(o.modified) + '.json')
|
||||
|
||||
# Some test-scoped fixtures (e.g. fs_store) delete all campaigns, so by
|
||||
# the time this module-scoped fixture tears itself down, it may find
|
||||
# its campaigns already gone, which causes not-found errors.
|
||||
try:
|
||||
os.remove(filepath)
|
||||
except OSError as e:
|
||||
# 3 is the ERROR_PATH_NOT_FOUND windows error code. Which has an
|
||||
# errno symbolic value, but not the windows meaning...
|
||||
if e.errno in (errno.ENOENT, 3):
|
||||
continue
|
||||
raise
|
||||
|
||||
|
||||
def test_filesystem_source_nonexistent_folder():
|
||||
|
@ -126,32 +147,36 @@ def test_filesystem_source_bad_stix_file(fs_source, bad_stix_files):
|
|||
# this tests handling of bad STIX json object
|
||||
try:
|
||||
fs_source.get("intrusion-set--test-non-stix")
|
||||
except TypeError as e:
|
||||
assert "intrusion-set--test-non-stix" in str(e)
|
||||
assert "could either not be parsed to JSON or was not valid STIX JSON" in str(e)
|
||||
except STIXError as e:
|
||||
assert "Can't parse object with no 'type' property" in str(e)
|
||||
|
||||
|
||||
def test_filesytem_source_get_object(fs_source):
|
||||
# get object
|
||||
def test_filesystem_source_get_object(fs_source):
|
||||
# get (latest) object
|
||||
mal = fs_source.get("malware--6b616fc1-1505-48e3-8b2c-0d19337bff38")
|
||||
assert mal.id == "malware--6b616fc1-1505-48e3-8b2c-0d19337bff38"
|
||||
assert mal.name == "Rover"
|
||||
assert mal.modified == datetime.datetime(2018, 11, 16, 22, 54, 20, 390000,
|
||||
pytz.utc)
|
||||
|
||||
|
||||
def test_filesytem_source_get_nonexistent_object(fs_source):
|
||||
def test_filesystem_source_get_nonexistent_object(fs_source):
|
||||
ind = fs_source.get("indicator--6b616fc1-1505-48e3-8b2c-0d19337bff38")
|
||||
assert ind is None
|
||||
|
||||
|
||||
def test_filesytem_source_all_versions(fs_source):
|
||||
# all versions - (currently not a true all versions call as FileSystem cant have multiple versions)
|
||||
id_ = fs_source.get("identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5")
|
||||
assert id_.id == "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5"
|
||||
assert id_.name == "The MITRE Corporation"
|
||||
assert id_.type == "identity"
|
||||
def test_filesystem_source_all_versions(fs_source):
|
||||
ids = fs_source.all_versions(
|
||||
"identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5"
|
||||
)
|
||||
assert len(ids) == 2
|
||||
assert all(id_.id == "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5"
|
||||
for id_ in ids)
|
||||
assert all(id_.name == "The MITRE Corporation" for id_ in ids)
|
||||
assert all(id_.type == "identity" for id_ in ids)
|
||||
|
||||
|
||||
def test_filesytem_source_query_single(fs_source):
|
||||
def test_filesystem_source_query_single(fs_source):
|
||||
# query2
|
||||
is_2 = fs_source.query([stix2.Filter("external_references.external_id", '=', "T1027")])
|
||||
assert len(is_2) == 1
|
||||
|
@ -161,7 +186,7 @@ def test_filesytem_source_query_single(fs_source):
|
|||
assert is_2.type == "attack-pattern"
|
||||
|
||||
|
||||
def test_filesytem_source_query_multiple(fs_source):
|
||||
def test_filesystem_source_query_multiple(fs_source):
|
||||
# query
|
||||
intrusion_sets = fs_source.query([stix2.Filter("type", '=', "intrusion-set")])
|
||||
assert len(intrusion_sets) == 2
|
||||
|
@ -173,6 +198,24 @@ def test_filesytem_source_query_multiple(fs_source):
|
|||
assert len(is_1.external_references) == 4
|
||||
|
||||
|
||||
def test_filesystem_source_backward_compatible(fs_source):
|
||||
# this specific object is outside an "ID" directory; make sure we can get
|
||||
# it.
|
||||
modified = datetime.datetime(2018, 11, 16, 22, 54, 20, 390000, pytz.utc)
|
||||
results = fs_source.query([
|
||||
stix2.Filter("type", "=", "malware"),
|
||||
stix2.Filter("id", "=", "malware--6b616fc1-1505-48e3-8b2c-0d19337bff38"),
|
||||
stix2.Filter("modified", "=", modified)
|
||||
])
|
||||
|
||||
assert len(results) == 1
|
||||
result = results[0]
|
||||
assert result.type == "malware"
|
||||
assert result.id == "malware--6b616fc1-1505-48e3-8b2c-0d19337bff38"
|
||||
assert result.modified == modified
|
||||
assert result.malware_types == ["version four"]
|
||||
|
||||
|
||||
def test_filesystem_sink_add_python_stix_object(fs_sink, fs_source):
|
||||
# add python stix object
|
||||
camp1 = stix2.v21.Campaign(
|
||||
|
@ -183,14 +226,16 @@ def test_filesystem_sink_add_python_stix_object(fs_sink, fs_source):
|
|||
|
||||
fs_sink.add(camp1)
|
||||
|
||||
assert os.path.exists(os.path.join(FS_PATH, "campaign", camp1.id + ".json"))
|
||||
filepath = os.path.join(FS_PATH, "campaign", camp1.id,
|
||||
_timestamp2filename(camp1.modified) + ".json")
|
||||
assert os.path.exists(filepath)
|
||||
|
||||
camp1_r = fs_source.get(camp1.id)
|
||||
assert camp1_r.id == camp1.id
|
||||
assert camp1_r.name == "Hannibal"
|
||||
assert "War Elephant" in camp1_r.aliases
|
||||
|
||||
os.remove(os.path.join(FS_PATH, "campaign", camp1_r.id + ".json"))
|
||||
os.remove(filepath)
|
||||
|
||||
|
||||
def test_filesystem_sink_add_stix_object_dict(fs_sink, fs_source):
|
||||
|
@ -202,18 +247,29 @@ def test_filesystem_sink_add_stix_object_dict(fs_sink, fs_source):
|
|||
"aliases": ["Purple Robes"],
|
||||
"id": "campaign--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
|
||||
"created": "2017-05-31T21:31:53.197755Z",
|
||||
"modified": "2017-05-31T21:31:53.197755Z"
|
||||
}
|
||||
|
||||
fs_sink.add(camp2)
|
||||
|
||||
assert os.path.exists(os.path.join(FS_PATH, "campaign", camp2["id"] + ".json"))
|
||||
# Need to get the exact "modified" timestamp which would have been
|
||||
# in effect at the time the object was saved to the sink, which determines
|
||||
# the filename it would have been saved as. It may not be exactly the same
|
||||
# as what's in the dict, since the parsing process can enforce a precision
|
||||
# constraint (e.g. truncate to milliseconds), which results in a slightly
|
||||
# different name.
|
||||
camp2obj = stix2.parse(camp2)
|
||||
filepath = os.path.join(FS_PATH, "campaign", camp2obj["id"],
|
||||
_timestamp2filename(camp2obj["modified"]) + ".json")
|
||||
|
||||
assert os.path.exists(filepath)
|
||||
|
||||
camp2_r = fs_source.get(camp2["id"])
|
||||
assert camp2_r.id == camp2["id"]
|
||||
assert camp2_r.name == camp2["name"]
|
||||
assert "Purple Robes" in camp2_r.aliases
|
||||
|
||||
os.remove(os.path.join(FS_PATH, "campaign", camp2_r.id + ".json"))
|
||||
os.remove(filepath)
|
||||
|
||||
|
||||
def test_filesystem_sink_add_stix_bundle_dict(fs_sink, fs_source):
|
||||
|
@ -229,52 +285,73 @@ def test_filesystem_sink_add_stix_bundle_dict(fs_sink, fs_source):
|
|||
"aliases": ["Huns"],
|
||||
"id": "campaign--b8f86161-ccae-49de-973a-4ca320c62478",
|
||||
"created": "2017-05-31T21:31:53.197755Z",
|
||||
},
|
||||
],
|
||||
"modified": "2017-05-31T21:31:53.197755Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
fs_sink.add(bund)
|
||||
|
||||
assert os.path.exists(os.path.join(FS_PATH, "campaign", bund["objects"][0]["id"] + ".json"))
|
||||
camp_obj = stix2.parse(bund["objects"][0])
|
||||
filepath = os.path.join(FS_PATH, "campaign", camp_obj["id"],
|
||||
_timestamp2filename(camp_obj["modified"]) + ".json")
|
||||
|
||||
assert os.path.exists(filepath)
|
||||
|
||||
camp3_r = fs_source.get(bund["objects"][0]["id"])
|
||||
assert camp3_r.id == bund["objects"][0]["id"]
|
||||
assert camp3_r.name == bund["objects"][0]["name"]
|
||||
assert "Huns" in camp3_r.aliases
|
||||
|
||||
os.remove(os.path.join(FS_PATH, "campaign", camp3_r.id + ".json"))
|
||||
os.remove(filepath)
|
||||
|
||||
|
||||
def test_filesystem_sink_add_json_stix_object(fs_sink, fs_source):
|
||||
# add json-encoded stix obj
|
||||
camp4 = '{"type": "campaign", "id":"campaign--6a6ca372-ba07-42cc-81ef-9840fc1f963d",'\
|
||||
' "created":"2017-05-31T21:31:53.197755Z", "name": "Ghengis Khan", "objective": "China and Russian infrastructure"}'
|
||||
' "created":"2017-05-31T21:31:53.197755Z",'\
|
||||
' "modified":"2017-05-31T21:31:53.197755Z",'\
|
||||
' "name": "Ghengis Khan", "objective": "China and Russian infrastructure"}'
|
||||
|
||||
fs_sink.add(camp4)
|
||||
|
||||
assert os.path.exists(os.path.join(FS_PATH, "campaign", "campaign--6a6ca372-ba07-42cc-81ef-9840fc1f963d" + ".json"))
|
||||
camp4obj = stix2.parse(camp4)
|
||||
filepath = os.path.join(FS_PATH, "campaign",
|
||||
"campaign--6a6ca372-ba07-42cc-81ef-9840fc1f963d",
|
||||
_timestamp2filename(camp4obj["modified"]) + ".json")
|
||||
|
||||
assert os.path.exists(filepath)
|
||||
|
||||
camp4_r = fs_source.get("campaign--6a6ca372-ba07-42cc-81ef-9840fc1f963d")
|
||||
assert camp4_r.id == "campaign--6a6ca372-ba07-42cc-81ef-9840fc1f963d"
|
||||
assert camp4_r.name == "Ghengis Khan"
|
||||
|
||||
os.remove(os.path.join(FS_PATH, "campaign", camp4_r.id + ".json"))
|
||||
os.remove(filepath)
|
||||
|
||||
|
||||
def test_filesystem_sink_json_stix_bundle(fs_sink, fs_source):
|
||||
# add json-encoded stix bundle
|
||||
bund2 = '{"type": "bundle", "id": "bundle--3d267103-8475-4d8f-b321-35ec6eccfa37",' \
|
||||
' "objects": [{"type": "campaign", "spec_version": "2.1", "id": "campaign--2c03b8bf-82ee-433e-9918-ca2cb6e9534b",' \
|
||||
' "created":"2017-05-31T21:31:53.197755Z", "name": "Spartacus", "objective": "Oppressive regimes of Africa and Middle East"}]}'
|
||||
' "spec_version": "2.0", "objects": [{"type": "campaign", "id": "campaign--2c03b8bf-82ee-433e-9918-ca2cb6e9534b",' \
|
||||
' "created":"2017-05-31T21:31:53.197755Z",'\
|
||||
' "modified":"2017-05-31T21:31:53.197755Z",'\
|
||||
' "name": "Spartacus", "objective": "Oppressive regimes of Africa and Middle East"}]}'
|
||||
fs_sink.add(bund2)
|
||||
|
||||
assert os.path.exists(os.path.join(FS_PATH, "campaign", "campaign--2c03b8bf-82ee-433e-9918-ca2cb6e9534b" + ".json"))
|
||||
bund2obj = stix2.parse(bund2)
|
||||
camp_obj = bund2obj["objects"][0]
|
||||
|
||||
filepath = os.path.join(FS_PATH, "campaign",
|
||||
"campaign--2c03b8bf-82ee-433e-9918-ca2cb6e9534b",
|
||||
_timestamp2filename(camp_obj["modified"]) + ".json")
|
||||
|
||||
assert os.path.exists(filepath)
|
||||
|
||||
camp5_r = fs_source.get("campaign--2c03b8bf-82ee-433e-9918-ca2cb6e9534b")
|
||||
assert camp5_r.id == "campaign--2c03b8bf-82ee-433e-9918-ca2cb6e9534b"
|
||||
assert camp5_r.name == "Spartacus"
|
||||
|
||||
os.remove(os.path.join(FS_PATH, "campaign", camp5_r.id + ".json"))
|
||||
os.remove(filepath)
|
||||
|
||||
|
||||
def test_filesystem_sink_add_objects_list(fs_sink, fs_source):
|
||||
|
@ -288,17 +365,26 @@ def test_filesystem_sink_add_objects_list(fs_sink, fs_source):
|
|||
camp7 = {
|
||||
"name": "Napolean",
|
||||
"type": "campaign",
|
||||
"spec_version": "2.1",
|
||||
"objective": "Central and Eastern Europe military commands and departments",
|
||||
"aliases": ["The Frenchmen"],
|
||||
"id": "campaign--122818b6-1112-4fb0-b11b-b111107ca70a",
|
||||
"created": "2017-05-31T21:31:53.197755Z",
|
||||
"modified": "2017-05-31T21:31:53.197755Z"
|
||||
}
|
||||
|
||||
fs_sink.add([camp6, camp7])
|
||||
|
||||
assert os.path.exists(os.path.join(FS_PATH, "campaign", camp6.id + ".json"))
|
||||
assert os.path.exists(os.path.join(FS_PATH, "campaign", "campaign--122818b6-1112-4fb0-b11b-b111107ca70a" + ".json"))
|
||||
camp7obj = stix2.parse(camp7)
|
||||
|
||||
camp6filepath = os.path.join(FS_PATH, "campaign", camp6.id,
|
||||
_timestamp2filename(camp6["modified"]) +
|
||||
".json")
|
||||
camp7filepath = os.path.join(
|
||||
FS_PATH, "campaign", "campaign--122818b6-1112-4fb0-b11b-b111107ca70a",
|
||||
_timestamp2filename(camp7obj["modified"]) + ".json")
|
||||
|
||||
assert os.path.exists(camp6filepath)
|
||||
assert os.path.exists(camp7filepath)
|
||||
|
||||
camp6_r = fs_source.get(camp6.id)
|
||||
assert camp6_r.id == camp6.id
|
||||
|
@ -309,8 +395,24 @@ def test_filesystem_sink_add_objects_list(fs_sink, fs_source):
|
|||
assert "The Frenchmen" in camp7_r.aliases
|
||||
|
||||
# remove all added objects
|
||||
os.remove(os.path.join(FS_PATH, "campaign", camp6_r.id + ".json"))
|
||||
os.remove(os.path.join(FS_PATH, "campaign", camp7_r.id + ".json"))
|
||||
os.remove(camp6filepath)
|
||||
os.remove(camp7filepath)
|
||||
|
||||
|
||||
def test_filesystem_sink_marking(fs_sink):
|
||||
marking = stix2.v21.MarkingDefinition(
|
||||
definition_type="tlp",
|
||||
definition=stix2.v21.TLPMarking(tlp="green")
|
||||
)
|
||||
|
||||
fs_sink.add(marking)
|
||||
marking_filepath = os.path.join(
|
||||
FS_PATH, "marking-definition", marking["id"] + ".json"
|
||||
)
|
||||
|
||||
assert os.path.exists(marking_filepath)
|
||||
|
||||
os.remove(marking_filepath)
|
||||
|
||||
|
||||
def test_filesystem_store_get_stored_as_bundle(fs_store):
|
||||
|
@ -326,8 +428,9 @@ def test_filesystem_store_get_stored_as_object(fs_store):
|
|||
|
||||
|
||||
def test_filesystem_store_all_versions(fs_store):
|
||||
# all versions() - (note at this time, all_versions() is still not applicable to FileSystem, as only one version is ever stored)
|
||||
rel = fs_store.all_versions("relationship--70dc6b5c-c524-429e-a6ab-0dd40f0482c1")[0]
|
||||
rels = fs_store.all_versions("relationship--70dc6b5c-c524-429e-a6ab-0dd40f0482c1")
|
||||
assert len(rels) == 1
|
||||
rel = rels[0]
|
||||
assert rel.id == "relationship--70dc6b5c-c524-429e-a6ab-0dd40f0482c1"
|
||||
assert rel.type == "relationship"
|
||||
|
||||
|
@ -350,9 +453,9 @@ def test_filesystem_store_query_single_filter(fs_store):
|
|||
|
||||
def test_filesystem_store_empty_query(fs_store):
|
||||
results = fs_store.query() # returns all
|
||||
assert len(results) == 26
|
||||
assert "tool--242f3da3-4425-4d11-8f5c-b842886da966" in [obj["id"] for obj in results]
|
||||
assert "marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168" in [obj["id"] for obj in results]
|
||||
assert len(results) == 30
|
||||
assert "tool--242f3da3-4425-4d11-8f5c-b842886da966" in [obj.id for obj in results]
|
||||
assert "marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168" in [obj.id for obj in results]
|
||||
|
||||
|
||||
def test_filesystem_store_query_multiple_filters(fs_store):
|
||||
|
@ -364,7 +467,7 @@ def test_filesystem_store_query_multiple_filters(fs_store):
|
|||
|
||||
def test_filesystem_store_query_dont_include_type_folder(fs_store):
|
||||
results = fs_store.query(stix2.Filter("type", "!=", "tool"))
|
||||
assert len(results) == 24
|
||||
assert len(results) == 28
|
||||
|
||||
|
||||
def test_filesystem_store_add(fs_store):
|
||||
|
@ -380,8 +483,11 @@ def test_filesystem_store_add(fs_store):
|
|||
assert camp1_r.id == camp1.id
|
||||
assert camp1_r.name == camp1.name
|
||||
|
||||
filepath = os.path.join(FS_PATH, "campaign", camp1_r.id,
|
||||
_timestamp2filename(camp1_r.modified) + ".json")
|
||||
|
||||
# remove
|
||||
os.remove(os.path.join(FS_PATH, "campaign", camp1_r.id + ".json"))
|
||||
os.remove(filepath)
|
||||
|
||||
|
||||
def test_filesystem_store_add_as_bundle():
|
||||
|
@ -394,7 +500,10 @@ def test_filesystem_store_add_as_bundle():
|
|||
)
|
||||
fs_store.add(camp1)
|
||||
|
||||
with open(os.path.join(FS_PATH, "campaign", camp1.id + ".json")) as bundle_file:
|
||||
filepath = os.path.join(FS_PATH, "campaign", camp1.id,
|
||||
_timestamp2filename(camp1.modified) + ".json")
|
||||
|
||||
with open(filepath) as bundle_file:
|
||||
assert '"type": "bundle"' in bundle_file.read()
|
||||
|
||||
camp1_r = fs_store.get(camp1.id)
|
||||
|
@ -419,6 +528,26 @@ def test_filesystem_store_add_invalid_object(fs_store):
|
|||
assert 'JSON formatted STIX bundle' in str(excinfo.value)
|
||||
|
||||
|
||||
def test_filesystem_store_add_marking(fs_store):
|
||||
marking = stix2.v21.MarkingDefinition(
|
||||
definition_type="tlp",
|
||||
definition=stix2.v21.TLPMarking(tlp="green")
|
||||
)
|
||||
|
||||
fs_store.add(marking)
|
||||
marking_filepath = os.path.join(
|
||||
FS_PATH, "marking-definition", marking["id"] + ".json"
|
||||
)
|
||||
|
||||
assert os.path.exists(marking_filepath)
|
||||
|
||||
marking_r = fs_store.get(marking["id"])
|
||||
assert marking_r["id"] == marking["id"]
|
||||
assert marking_r["definition"]["tlp"] == "green"
|
||||
|
||||
os.remove(marking_filepath)
|
||||
|
||||
|
||||
def test_filesystem_object_with_custom_property(fs_store):
|
||||
camp = stix2.v21.Campaign(
|
||||
name="Scipio Africanus",
|
||||
|
@ -540,3 +669,357 @@ def test_related_to_by_target(rel_fs_store):
|
|||
assert len(resp) == 2
|
||||
assert any(x['id'] == CAMPAIGN_ID for x in resp)
|
||||
assert any(x['id'] == INDICATOR_ID for x in resp)
|
||||
|
||||
|
||||
def test_auth_set_white1():
|
||||
auth_set = AuthSet({"A"}, set())
|
||||
|
||||
assert auth_set.auth_type == AuthSet.WHITE
|
||||
assert auth_set.values == {"A"}
|
||||
|
||||
|
||||
def test_auth_set_white2():
|
||||
auth_set = AuthSet(set(), set())
|
||||
|
||||
assert auth_set.auth_type == AuthSet.WHITE
|
||||
assert len(auth_set.values) == 0
|
||||
|
||||
|
||||
def test_auth_set_white3():
|
||||
auth_set = AuthSet({"A", "B"}, {"B", "C"})
|
||||
|
||||
assert auth_set.auth_type == AuthSet.WHITE
|
||||
assert auth_set.values == {"A"}
|
||||
|
||||
|
||||
def test_auth_set_black1():
|
||||
auth_set = AuthSet(None, {"B", "C"})
|
||||
|
||||
assert auth_set.auth_type == AuthSet.BLACK
|
||||
assert auth_set.values == {"B", "C"}
|
||||
|
||||
|
||||
def test_optimize_types1():
|
||||
filters = [
|
||||
stix2.Filter("type", "=", "foo")
|
||||
]
|
||||
|
||||
auth_types, auth_ids = _find_search_optimizations(filters)
|
||||
|
||||
assert auth_types.auth_type == AuthSet.WHITE
|
||||
assert auth_types.values == {"foo"}
|
||||
assert auth_ids.auth_type == AuthSet.BLACK
|
||||
assert len(auth_ids.values) == 0
|
||||
|
||||
|
||||
def test_optimize_types2():
|
||||
filters = [
|
||||
stix2.Filter("type", "=", "foo"),
|
||||
stix2.Filter("type", "=", "bar")
|
||||
]
|
||||
|
||||
auth_types, auth_ids = _find_search_optimizations(filters)
|
||||
|
||||
assert auth_types.auth_type == AuthSet.WHITE
|
||||
assert len(auth_types.values) == 0
|
||||
assert auth_ids.auth_type == AuthSet.BLACK
|
||||
assert len(auth_ids.values) == 0
|
||||
|
||||
|
||||
def test_optimize_types3():
|
||||
filters = [
|
||||
stix2.Filter("type", "in", ["A", "B", "C"]),
|
||||
stix2.Filter("type", "in", ["B", "C", "D"])
|
||||
]
|
||||
|
||||
auth_types, auth_ids = _find_search_optimizations(filters)
|
||||
|
||||
assert auth_types.auth_type == AuthSet.WHITE
|
||||
assert auth_types.values == {"B", "C"}
|
||||
assert auth_ids.auth_type == AuthSet.BLACK
|
||||
assert len(auth_ids.values) == 0
|
||||
|
||||
|
||||
def test_optimize_types4():
|
||||
filters = [
|
||||
stix2.Filter("type", "in", ["A", "B", "C"]),
|
||||
stix2.Filter("type", "in", ["D", "E", "F"])
|
||||
]
|
||||
|
||||
auth_types, auth_ids = _find_search_optimizations(filters)
|
||||
|
||||
assert auth_types.auth_type == AuthSet.WHITE
|
||||
assert len(auth_types.values) == 0
|
||||
assert auth_ids.auth_type == AuthSet.BLACK
|
||||
assert len(auth_ids.values) == 0
|
||||
|
||||
|
||||
def test_optimize_types5():
|
||||
filters = [
|
||||
stix2.Filter("type", "in", ["foo", "bar"]),
|
||||
stix2.Filter("type", "!=", "bar")
|
||||
]
|
||||
|
||||
auth_types, auth_ids = _find_search_optimizations(filters)
|
||||
|
||||
assert auth_types.auth_type == AuthSet.WHITE
|
||||
assert auth_types.values == {"foo"}
|
||||
assert auth_ids.auth_type == AuthSet.BLACK
|
||||
assert len(auth_ids.values) == 0
|
||||
|
||||
|
||||
def test_optimize_types6():
|
||||
filters = [
|
||||
stix2.Filter("type", "!=", "foo"),
|
||||
stix2.Filter("type", "!=", "bar")
|
||||
]
|
||||
|
||||
auth_types, auth_ids = _find_search_optimizations(filters)
|
||||
|
||||
assert auth_types.auth_type == AuthSet.BLACK
|
||||
assert auth_types.values == {"foo", "bar"}
|
||||
assert auth_ids.auth_type == AuthSet.BLACK
|
||||
assert len(auth_ids.values) == 0
|
||||
|
||||
|
||||
def test_optimize_types7():
|
||||
filters = [
|
||||
stix2.Filter("type", "=", "foo"),
|
||||
stix2.Filter("type", "!=", "foo")
|
||||
]
|
||||
|
||||
auth_types, auth_ids = _find_search_optimizations(filters)
|
||||
|
||||
assert auth_types.auth_type == AuthSet.WHITE
|
||||
assert len(auth_types.values) == 0
|
||||
assert auth_ids.auth_type == AuthSet.BLACK
|
||||
assert len(auth_ids.values) == 0
|
||||
|
||||
|
||||
def test_optimize_types8():
|
||||
filters = []
|
||||
|
||||
auth_types, auth_ids = _find_search_optimizations(filters)
|
||||
|
||||
assert auth_types.auth_type == AuthSet.BLACK
|
||||
assert len(auth_types.values) == 0
|
||||
assert auth_ids.auth_type == AuthSet.BLACK
|
||||
assert len(auth_ids.values) == 0
|
||||
|
||||
|
||||
def test_optimize_types_ids1():
|
||||
filters = [
|
||||
stix2.Filter("type", "in", ["foo", "bar"]),
|
||||
stix2.Filter("id", "=", "foo--00000000-0000-0000-0000-000000000000")
|
||||
]
|
||||
|
||||
auth_types, auth_ids = _find_search_optimizations(filters)
|
||||
|
||||
assert auth_types.auth_type == AuthSet.WHITE
|
||||
assert auth_types.values == {"foo"}
|
||||
assert auth_ids.auth_type == AuthSet.WHITE
|
||||
assert auth_ids.values == {"foo--00000000-0000-0000-0000-000000000000"}
|
||||
|
||||
|
||||
def test_optimize_types_ids2():
|
||||
filters = [
|
||||
stix2.Filter("type", "=", "foo"),
|
||||
stix2.Filter("id", "=", "bar--00000000-0000-0000-0000-000000000000")
|
||||
]
|
||||
|
||||
auth_types, auth_ids = _find_search_optimizations(filters)
|
||||
|
||||
assert auth_types.auth_type == AuthSet.WHITE
|
||||
assert len(auth_types.values) == 0
|
||||
assert auth_ids.auth_type == AuthSet.WHITE
|
||||
assert len(auth_ids.values) == 0
|
||||
|
||||
|
||||
def test_optimize_types_ids3():
|
||||
filters = [
|
||||
stix2.Filter("type", "in", ["foo", "bar"]),
|
||||
stix2.Filter("id", "!=", "bar--00000000-0000-0000-0000-000000000000")
|
||||
]
|
||||
|
||||
auth_types, auth_ids = _find_search_optimizations(filters)
|
||||
|
||||
assert auth_types.auth_type == AuthSet.WHITE
|
||||
assert auth_types.values == {"foo", "bar"}
|
||||
assert auth_ids.auth_type == AuthSet.BLACK
|
||||
assert auth_ids.values == {"bar--00000000-0000-0000-0000-000000000000"}
|
||||
|
||||
|
||||
def test_optimize_types_ids4():
|
||||
filters = [
|
||||
stix2.Filter("type", "in", ["A", "B", "C"]),
|
||||
stix2.Filter("id", "in", [
|
||||
"B--00000000-0000-0000-0000-000000000000",
|
||||
"C--00000000-0000-0000-0000-000000000000",
|
||||
"D--00000000-0000-0000-0000-000000000000",
|
||||
])
|
||||
]
|
||||
|
||||
auth_types, auth_ids = _find_search_optimizations(filters)
|
||||
|
||||
assert auth_types.auth_type == AuthSet.WHITE
|
||||
assert auth_types.values == {"B", "C"}
|
||||
assert auth_ids.auth_type == AuthSet.WHITE
|
||||
assert auth_ids.values == {
|
||||
"B--00000000-0000-0000-0000-000000000000",
|
||||
"C--00000000-0000-0000-0000-000000000000"
|
||||
}
|
||||
|
||||
|
||||
def test_optimize_types_ids5():
|
||||
filters = [
|
||||
stix2.Filter("type", "in", ["A", "B", "C"]),
|
||||
stix2.Filter("type", "!=", "C"),
|
||||
stix2.Filter("id", "in", [
|
||||
"B--00000000-0000-0000-0000-000000000000",
|
||||
"C--00000000-0000-0000-0000-000000000000",
|
||||
"D--00000000-0000-0000-0000-000000000000"
|
||||
]),
|
||||
stix2.Filter("id", "!=", "D--00000000-0000-0000-0000-000000000000")
|
||||
]
|
||||
|
||||
auth_types, auth_ids = _find_search_optimizations(filters)
|
||||
|
||||
assert auth_types.auth_type == AuthSet.WHITE
|
||||
assert auth_types.values == {"B"}
|
||||
assert auth_ids.auth_type == AuthSet.WHITE
|
||||
assert auth_ids.values == {"B--00000000-0000-0000-0000-000000000000"}
|
||||
|
||||
|
||||
def test_optimize_types_ids6():
|
||||
filters = [
|
||||
stix2.Filter("id", "=", "A--00000000-0000-0000-0000-000000000000")
|
||||
]
|
||||
|
||||
auth_types, auth_ids = _find_search_optimizations(filters)
|
||||
|
||||
assert auth_types.auth_type == AuthSet.WHITE
|
||||
assert auth_types.values == {"A"}
|
||||
assert auth_ids.auth_type == AuthSet.WHITE
|
||||
assert auth_ids.values == {"A--00000000-0000-0000-0000-000000000000"}
|
||||
|
||||
|
||||
def test_search_auth_set_white1():
|
||||
auth_set = AuthSet(
|
||||
{"attack-pattern", "doesntexist"},
|
||||
set()
|
||||
)
|
||||
|
||||
results = _get_matching_dir_entries(FS_PATH, auth_set, stat.S_ISDIR)
|
||||
assert results == ["attack-pattern"]
|
||||
|
||||
results = _get_matching_dir_entries(FS_PATH, auth_set, stat.S_ISREG)
|
||||
assert len(results) == 0
|
||||
|
||||
|
||||
def test_search_auth_set_white2():
|
||||
auth_set = AuthSet(
|
||||
{
|
||||
"malware--6b616fc1-1505-48e3-8b2c-0d19337bff38",
|
||||
"malware--92ec0cbd-2c30-44a2-b270-73f4ec949841"
|
||||
|
||||
},
|
||||
{
|
||||
"malware--92ec0cbd-2c30-44a2-b270-73f4ec949841",
|
||||
"malware--96b08451-b27a-4ff6-893f-790e26393a8e",
|
||||
"doesntexist"
|
||||
}
|
||||
)
|
||||
|
||||
results = _get_matching_dir_entries(
|
||||
os.path.join(FS_PATH, "malware"),
|
||||
auth_set, stat.S_ISDIR
|
||||
)
|
||||
|
||||
assert results == ["malware--6b616fc1-1505-48e3-8b2c-0d19337bff38"]
|
||||
|
||||
|
||||
def test_search_auth_set_white3():
|
||||
auth_set = AuthSet({"20170531213258226477", "doesntexist"}, set())
|
||||
|
||||
results = _get_matching_dir_entries(
|
||||
os.path.join(FS_PATH, "malware",
|
||||
"malware--6b616fc1-1505-48e3-8b2c-0d19337bff38"),
|
||||
auth_set, stat.S_ISREG, ".json"
|
||||
)
|
||||
|
||||
assert results == ["20170531213258226477.json"]
|
||||
|
||||
|
||||
def test_search_auth_set_black1():
|
||||
auth_set = AuthSet(
|
||||
None,
|
||||
{"tool--242f3da3-4425-4d11-8f5c-b842886da966", "doesntexist"}
|
||||
)
|
||||
|
||||
results = _get_matching_dir_entries(
|
||||
os.path.join(FS_PATH, "tool"),
|
||||
auth_set, stat.S_ISDIR
|
||||
)
|
||||
|
||||
assert set(results) == {
|
||||
"tool--03342581-f790-4f03-ba41-e82e67392e23"
|
||||
}
|
||||
|
||||
|
||||
def test_search_auth_set_white_empty():
|
||||
auth_set = AuthSet(
|
||||
set(),
|
||||
set()
|
||||
)
|
||||
|
||||
results = _get_matching_dir_entries(FS_PATH, auth_set, stat.S_ISDIR)
|
||||
|
||||
assert len(results) == 0
|
||||
|
||||
|
||||
def test_search_auth_set_black_empty(rel_fs_store):
|
||||
# Ensure rel_fs_store fixture has run so that the type directories are
|
||||
# predictable (it adds "campaign").
|
||||
auth_set = AuthSet(
|
||||
None,
|
||||
set()
|
||||
)
|
||||
|
||||
results = _get_matching_dir_entries(FS_PATH, auth_set, stat.S_ISDIR)
|
||||
|
||||
# Should get all dirs
|
||||
assert set(results) == {
|
||||
"attack-pattern",
|
||||
"campaign",
|
||||
"course-of-action",
|
||||
"identity",
|
||||
"indicator",
|
||||
"intrusion-set",
|
||||
"malware",
|
||||
"marking-definition",
|
||||
"relationship",
|
||||
"tool"
|
||||
}
|
||||
|
||||
|
||||
def test_timestamp2filename_naive():
|
||||
dt = datetime.datetime(
|
||||
2010, 6, 15,
|
||||
8, 30, 10, 1234
|
||||
)
|
||||
|
||||
filename = _timestamp2filename(dt)
|
||||
assert filename == "20100615083010001234"
|
||||
|
||||
|
||||
def test_timestamp2filename_tz():
|
||||
# one hour west of UTC (i.e. an hour earlier)
|
||||
tz = pytz.FixedOffset(-60)
|
||||
dt = datetime.datetime(
|
||||
2010, 6, 15,
|
||||
7, 30, 10, 1234,
|
||||
tz
|
||||
)
|
||||
|
||||
filename = _timestamp2filename(dt)
|
||||
assert filename == "20100615083010001234"
|
||||
|
|
|
@ -201,8 +201,8 @@ def test_apply_common_filters3():
|
|||
assert len(resp) == 3
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs, [filters[3]]))
|
||||
assert resp[0].id == real_stix_objs[0].id
|
||||
assert len(resp) == 3
|
||||
assert resp[0].id == real_stix_objs[0].id
|
||||
|
||||
|
||||
def test_apply_common_filters4():
|
||||
|
@ -343,14 +343,6 @@ def test_datetime_filter_behavior():
|
|||
filter_with_dt_obj = Filter("created", "=", parse_into_datetime("2016-02-14T00:00:00.000Z", "millisecond"))
|
||||
filter_with_str = Filter("created", "=", "2016-02-14T00:00:00.000Z")
|
||||
|
||||
# check that filter value is converted from datetime to str
|
||||
assert isinstance(filter_with_dt_obj.value, str)
|
||||
|
||||
# compare datetime string to filter w/ datetime obj
|
||||
resp = list(apply_common_filters(stix_objs, [filter_with_dt_obj]))
|
||||
assert len(resp) == 1
|
||||
assert resp[0]["id"] == "vulnerability--ee916c28-c7a4-4d0d-ad56-a8d357f89fef"
|
||||
|
||||
# compare datetime obj to filter w/ datetime obj
|
||||
resp = list(apply_common_filters(real_stix_objs, [filter_with_dt_obj]))
|
||||
assert len(resp) == 1
|
||||
|
|
Loading…
Reference in New Issue