Skip to content
Snippets Groups Projects
Commit cbeac96f authored by Pavel Eis's avatar Pavel Eis
Browse files

Add of misp basic unittests

Two basic tests created in test_misp.py. First in class
TestMispToIdeaConverter tests MISP to IDEA conversion. Loads designed
MISP event and converts it to IDEA event. Then compares one to one
with correctly converted IDEA event.

Second is placed in class TestIdeaToMispConverter. Loads designed
IDEA event and converts it to MISP event. Then checks attribute
count of newly converted MISP event and checks, if all values were
inserted.
parent 1184eb55
No related branches found
No related tags found
No related merge requests found
{
"Format": "IDEA0",
"ID": "9be8f15e-cda5-4627-a7b8-422b9f166cd1",
"Category": [
"Test",
"Availability.DoS"
],
"Description": "Test event",
"CreateTime": "2019-01-30T11:29:39Z",
"DetectTime": "2019-01-28T09:28:32Z",
"Node": [
{
"Name": "ORGNAME",
"Note": "MISP organization id (created event): 1"
},
{
"Name": "ORGNAME",
"Note": "MISP organization id (reported event): 1"
}
],
"Source": [
{
"IP4": [
"192.168.0.1"
]
},
{
"IP4": [
"192.168.0.2"
]
},
{
"Email": [
"test@example.test"
]
},
{
"IP4": [
"192.168.0.3"
],
"Port": [
333
]
},
{
"Port": [
3333
],
"IP4": [
"192.168.0.50"
],
"Proto": [
"UDP"
]
},
{
"IP4": [
"192.168.0.100"
],
"Port": [
222
],
"Proto": [
"IP",
"TCP",
"HTTP"
]
},
{
"IP4": [
"192.168.0.120"
],
"Proto": [
"TCP"
]
},
{
"IP4": [
"190.90.90.90",
"180.80.80.80",
"120.30.30.30"
],
"IP6": [
"fdba:cf29:3b2b:bf4:ffff:ffff:ffff:ffff"
],
"Port": [
"222",
"222"
],
"Proto": [
"tcp"
],
"MAC": [
"2b:54:d6:0c:c2:f2",
"32:f0:9e:19:24:ec"
],
"Email": [
"admin@test.org"
],
"Note": "Test source object",
"Ref": [
"cve:CVE-2018-13280",
"cve:CVE-2017-7901"
]
}
],
"Target": [
{
"IP4": [
"192.90.0.1"
]
},
{
"IP4": [
"192.90.0.2"
],
"Port": [
80
]
},
{
"Email": [
"email@test.org"
]
},
{
"Hostname": [
"example.com"
],
"IP4": [
"20.20.20.20"
]
},
{
"Port": [
480
],
"Hostname": [
"example.com"
],
"IP4": [
"192.90.10.10"
]
},
{
"IP4": [
"192.90.20.20"
],
"Port": [
6666
],
"Proto": [
"UDP"
]
},
{
"IP4": [
"198.20.20.20"
],
"Port": [
444
],
"Proto": [
"IP",
"TCP",
"HTTP"
]
},
{
"IP4": [
"180.200.200.100"
],
"Port": [
200
],
"Proto": [
"TCP"
]
}
],
"Attach": [
{
"Handle": "attach0",
"FileName": [
"definitelyNotVirus.exe"
],
"Hash": [
"md5:c760ee8d2c87a58b93c2df797123e09d"
]
},
{
"Handle": "attach1",
"Hash": [
"sha256:cc9b1edd07ff57d5e6c8fe4749d69442662014a390005a2056226fef1e70a91d"
]
},
{
"Handle": "att2",
"ContentType": "text/plain",
"FileName": [
"exampleName.exe"
],
"Content": "This is test attachment",
"Hash": [
"md5:2fd30a87e52f0189cb19d8c8ebb9761c",
"sha512:f5bf02f82bbc2db7603eba04ca90079e78504cf7198b49e5815683c258a155c0a735f230fd6d06c651ac70493c23fb0b7d413fc068b644c7650942fea06ac374"
],
"Size": 222000,
"Note": "Test Attach object"
}
]
}
\ No newline at end of file
{
"Format": "IDEA0",
"ID": "3b06db03-f22b-4b68-864a-b89e9f141255",
"Category": [
"Test",
"Availability.DoS"
],
"Description": "Test event",
"Source": [
{
"IP4": [
"192.168.0.1",
"192.168.0.2",
"192.168.0.3",
"192.168.0.4"
],
"IP6": [
"fd8a:ff7e:9ba1:020c::/64",
"fd8a:ff7e:9ba1:20c:ffff:ffff:ffff:ffff"
],
"MAC": [
"2b:54:d6:0c:c2:f2",
"32:f0:9e:19:24:ec"
],
"Port": [
90, 300, 443, 3333, 3334
],
"Proto": [
"tcp",
"http"
],
"Email": [
"admin@test.org",
"test.admin@test.org"
],
"Note": "Test source object",
"Ref": [
"cve:CVE-2018-13280",
"cve:CVE-2017-7901"
]
},
{
"IP4": [
"192.169.0.1",
"192.169.0.2",
"192.169.0.3",
"192.169.0.4"
],
"IP6": [
"fd8a:ff7e:9ba1:020d::/64",
"fd8a:ff7e:9ba1:20d:ffff:ffff:ffff:ffff"
],
"MAC": [
"2b:54:d6:09:42:ce",
"32:f0:9e:b2:45:6d"
],
"Port": [
80
]
},
{
"Email": [
"test@example.test"
]
},
{
"IP4": [
"192.170.0.120"
],
"Proto": [
"tcp"
]
}
],
"Target": [
{
"IP4": [
"120.90.0.1",
"120.90.0.2"
],
"Port": [
480
],
"Hostname": [
"example.com"
],
"Note": "Test target object"
},
{
"IP4": [
"120.90.1.2"
],
"Port": [
80, 90, 100
],
"Proto": [
"tcp"
],
"Email": [
"email@test.org"
]
},
{
"Email": [
"email02@test.org"
]
},
{
"Hostname": [
"example.com"
],
"IP4": [
"120.90.5.1"
]
}
],
"Attach": [
{
"Handle": "att1",
"FileName": ["killemall"],
"Type": ["Malware"],
"ContentType": "application/octet-stream",
"Hash": ["sha1:b43daa145cb39e74cc28fef4a2d7b027b75f97ff"],
"Size": 46,
"Ref": ["Trojan-Spy:W32/FinSpy.A"],
"ContentEncoding": "base64",
"Content": "TVpqdXN0a2lkZGluZwo="
}
],
"CreateTime": "2019-01-28T10:19:40Z",
"DetectTime": "2019-01-28T09:28:32Z",
"Node": [
{
"Name": "cz.cesnet.kippo-honey",
"Type": ["Protocol", "Honeypot"],
"SW": ["Kippo"],
"AggrWin": "00:05:00"
}
]
}
\ No newline at end of file
This diff is collapsed.
#!/usr/bin/python3.6
# -*- coding: utf-8 -*-
#
# Copyright (c) 2016, CESNET, z. s. p. o.
# Use of this source is governed by an ISC license, see LICENSE file.
import unittest
from idea.misp import MispToIdea, IdeaToMisp
import os
import json
import re
class TestMispToIdeaConverter(unittest.TestCase):
"""
Basic unittest of MISP to IDEA conversion. generates IDEA event from MISP event saved in file and compares
output to saved IDEA event, which should be the same as the generated output
"""
def setUp(self):
# load saved files, which contain designed test events
self.misp_test_file = open(os.path.join(os.getcwd(), "test_misp_files", "test_misp_event.json"), "r")
self.misp_event = json.load(self.misp_test_file)
self.idea_test_file = open(os.path.join(os.getcwd(), "test_misp_files", "test_idea_event.json"), "r")
self.idea_event = json.load(self.idea_test_file)
def tearDown(self):
self.misp_test_file.close()
self.idea_test_file.close()
def test_raw_ouput(self):
# convert MISP event to IDEA event
idea_converter = MispToIdea()
idea_converted_event = idea_converter.to_idea(self.misp_event)
# CreateTime and ID can and probably will differ
idea_converted_event.pop('CreateTime')
idea_converted_event.pop('ID')
self.idea_event.pop('CreateTime')
self.idea_event.pop('ID')
# compare correctly converted IDEA message (loaded from file) with currently generated version
self.assertTrue(json.dumps(self.idea_event, sort_keys=True) == json.dumps(idea_converted_event, sort_keys=True))
class TestIdeaToMispConverter(unittest.TestCase):
"""
Basic unittest, which tests only, if all attributes, which should be converted, were converted
"""
re_cve = re.compile("cve:", re.IGNORECASE)
def setUp(self):
# load test idea event
self.idea_test_file = open(os.path.join(os.getcwd(), "test_misp_files", "test_idea_event_02.json"), "r")
self.idea_event = json.load(self.idea_test_file)
def tearDown(self):
self.idea_test_file.close()
@staticmethod
def append_value_or_create_list(object_key, value_key, value, updated_object):
"""
Append value to list placed on key or, if key does not exist yet, create key with new list with the value
:param object_key: (source|target|attach)
:param value_key: key of value, which will be inserted (IP4|MAC|IP6|...)
:param value: the inserted value
:param updated_object: dictionary, which will be updated
:return: None (objects gets updated)
"""
try:
updated_object[object_key][value_key].append(str(value))
except KeyError:
updated_object[object_key][value_key] = [str(value)]
def process_source_or_target_object(self, name_of_object, updated_dict):
"""
Loads Source or Target object and get all data from it and save it into updated_dict
:param name_of_object: ("Source", "Target")
:param updated_dict: the dictionary, which will be updated
:return: None (updated_dict gets updated)
"""
for data_object in self.idea_event[name_of_object]:
for data_attrib, key_value in data_object.items():
if data_attrib in ("Type", "AttachHand", "Spoofed", "Imprecise", "Anonymised", "Router", "Netname"):
# these keys are not being converted
continue
if data_attrib == "Note":
# Note is just string, not list as all other values
self.append_value_or_create_list(name_of_object.lower(), "Note", key_value, updated_dict)
else:
# all other keys conatin list
for value in key_value:
# If 'Ref', insert into Vulnerability or Reference
if data_attrib == "Ref" and __class__.re_cve.search(value):
self.append_value_or_create_list(name_of_object.lower(), "Vulnerability",
__class__.re_cve.split(value)[1], updated_dict)
elif data_attrib == "Ref":
self.append_value_or_create_list(name_of_object.lower(), "Reference", key_value,
updated_dict)
else:
# otherwise just insert value under the key
self.append_value_or_create_list(name_of_object.lower(), data_attrib, value, updated_dict)
def test_whole_conversion(self):
"""
Load all attributes, which should be converted, from IDEA event into dictionary and then go through all
attributes of all MISP objects and try to pop these attributes from the dictionary. If dictionary will contain
no data at the end, all attributes from IDEA should be converted correctly
:return:
"""
# convert IDEA event to MISP event
misp_converter = IdeaToMisp()
misp_converted_event = json.loads(misp_converter.to_misp(self.idea_event).to_json())['Event']
attrib_dict = {
"source": {},
"target": {},
"attach": {}
}
# process Source and Target objects
self.process_source_or_target_object("Source", attrib_dict)
self.process_source_or_target_object("Target", attrib_dict)
# process Attach objects
for attach_object in self.idea_event['Attach']:
for attach_attrib, key_value in attach_object.items():
if attach_attrib in ("Handle", "Type", "ContentID", "ExternalURI"):
# these keys are not being converted
continue
if attach_attrib in ("Size", "Note", "ContentType", "ContentCharset", "ContentEncoding", "Content"):
# these keys are just strings, not lists
self.append_value_or_create_list("attach", attach_attrib, key_value, attrib_dict)
else:
# all other values are lists
for value in key_value:
# If 'Ref', insert into Vulnerability or Reference
if attach_attrib == "Ref" and __class__.re_cve.search(value):
self.append_value_or_create_list("attach", "Vulnerability",
__class__.re_cve.split(value)[1], attrib_dict)
elif attach_attrib == "Ref":
self.append_value_or_create_list("attach", "Reference", value, attrib_dict)
elif attach_attrib == "Hash":
# Hash needs to be split and inserted under correct key (hash name)
hash_name = value.split(":", 1)[0].lower()
hash_value = value.split(":", 1)[1]
self.append_value_or_create_list("attach", hash_name, hash_value, attrib_dict)
else:
# otherwise just insert value under the key
self.append_value_or_create_list("attach", attach_attrib, value, attrib_dict)
attribute_count = 0
# Now go through all attributes in all MISP objects and try to remove them from prepared dict before
for misp_object in misp_converted_event['Object']:
for object_attrib in misp_object['Attribute']:
try:
object_name = misp_object['name']
object_key = object_attrib['object_relation']
del_value = object_attrib['value']
attrib_dict[object_name][object_key].remove(del_value)
attribute_count += 1
except ValueError:
# Some value was inserted, while it should't have
self.fail("Value is in MISP object, but not in IDEA message.")
# check attribute count
self.assertEqual(attribute_count, 53)
# Now check all lists under the key, all lists should be empty --> all values were inserted correctly
for object_key in ["source", "target", "attach"]:
for key in attrib_dict[object_key]:
self.assertFalse(bool(attrib_dict[object_key][key]))
if __name__ == "__main__":
unittest.main()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment