pymisp 2.5.3__py3-none-any.whl → 2.5.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pymisp might be problematic. Click here for more details.
- CHANGELOG.txt +5380 -0
- examples/__init__.py +0 -0
- examples/add_attributes_from_csv.py +74 -0
- examples/add_email_object.py +29 -0
- examples/add_fail2ban_object.py +86 -0
- examples/add_feed.py +25 -0
- examples/add_file_object.py +47 -0
- examples/add_filetype_object_from_csv.py +53 -0
- examples/add_generic_object.py +26 -0
- examples/add_github_user.py +65 -0
- examples/add_gitlab_user.py +56 -0
- examples/add_named_attribute.py +25 -0
- examples/add_organisations.py +57 -0
- examples/add_ssh_authorized_keys.py +29 -0
- examples/add_user.py +22 -0
- examples/add_vehicle_object.py +22 -0
- examples/addtag2.py +45 -0
- examples/asciidoc_generator.py +114 -0
- examples/cache_all.py +10 -0
- examples/copyTagsFromAttributesToEvent.py +68 -0
- examples/copy_list.py +93 -0
- examples/create_events.py +26 -0
- examples/cytomic_orion.py +549 -0
- examples/del.py +22 -0
- examples/delete_user.py +16 -0
- examples/edit_organisation.py +20 -0
- examples/edit_user.py +20 -0
- examples/falsepositive_disabletoids.py +136 -0
- examples/fetch_events_feed.py +15 -0
- examples/fetch_warninglist_hits.py +38 -0
- examples/freetext.py +22 -0
- examples/generate_file_objects.py +78 -0
- examples/generate_meta_feed.py +15 -0
- examples/get.py +37 -0
- examples/get_csv.py +37 -0
- examples/get_network_activity.py +187 -0
- examples/last.py +48 -0
- examples/load_csv.py +94 -0
- examples/lookup.py +28 -0
- examples/misp2cef.py +71 -0
- examples/misp2clamav.py +52 -0
- examples/openioc_to_misp.py +27 -0
- examples/proofpoint_tap.py +203 -0
- examples/proofpoint_vap.py +65 -0
- examples/search.py +48 -0
- examples/search_attributes_yara.py +40 -0
- examples/search_sighting.py +42 -0
- examples/server_sync_check_conn.py +32 -0
- examples/sharing_groups.py +15 -0
- examples/show_sightings.py +168 -0
- examples/stats_report.py +405 -0
- examples/sync_sighting.py +171 -0
- examples/tags.py +25 -0
- examples/test_sign.py +19 -0
- examples/trustar_misp.py +59 -0
- examples/up.py +21 -0
- examples/upload.py +60 -0
- examples/users_list.py +15 -0
- examples/vmray_automation.py +281 -0
- examples/vt_to_misp.py +182 -0
- examples/warninglists.py +22 -0
- examples/yara.py +38 -0
- examples/yara_dump.py +98 -0
- pymisp/api.py +33 -5
- pymisp/data/misp-objects/objects/android-app/definition.json +8 -2
- pymisp/data/misp-objects/objects/instagram-account/definition.json +66 -0
- pymisp/data/misp-objects/objects/lnk/definition.json +13 -1
- pymisp/data/misp-objects/objects/rmm/definition.json +88 -0
- pymisp/data/misp-objects/objects/spambee-report/definition.json +54 -0
- pymisp/data/misp-objects/objects/target-system/definition.json +2 -2
- pymisp/data/misp-objects/objects/vulnerability/definition.json +5 -4
- pymisp/data/misp-objects/relationships/definition.json +17 -1
- pymisp/data/misp-objects/schema_objects.json +1 -1
- pymisp/mispevent.py +95 -23
- {pymisp-2.5.3.dist-info → pymisp-2.5.7.dist-info}/METADATA +23 -28
- {pymisp-2.5.3.dist-info → pymisp-2.5.7.dist-info}/RECORD +144 -30
- {pymisp-2.5.3.dist-info → pymisp-2.5.7.dist-info}/WHEEL +1 -1
- tests/57c4445b-c548-4654-af0b-4be3950d210f.json +1 -0
- tests/__init__.py +0 -0
- tests/csv_testfiles/invalid_fieldnames.csv +11 -0
- tests/csv_testfiles/valid_fieldnames.csv +4 -0
- tests/email_testfiles/mail_1.eml.zip +0 -0
- tests/email_testfiles/mail_1.msg +0 -0
- tests/email_testfiles/mail_1_bom.eml +858 -0
- tests/email_testfiles/mail_1_headers_only.eml +28 -0
- tests/email_testfiles/mail_2.eml +32 -0
- tests/email_testfiles/mail_3.eml +170 -0
- tests/email_testfiles/mail_3.msg +0 -0
- tests/email_testfiles/mail_4.msg +0 -0
- tests/email_testfiles/mail_5.msg +0 -0
- tests/email_testfiles/mail_multiple_to.eml +15 -0
- tests/email_testfiles/source +1 -0
- tests/git-vuln-finder-quagga.json +1493 -0
- tests/misp_event.json +76 -0
- tests/mispevent_testfiles/attribute.json +21 -0
- tests/mispevent_testfiles/attribute_del.json +23 -0
- tests/mispevent_testfiles/def_param.json +53 -0
- tests/mispevent_testfiles/event.json +8 -0
- tests/mispevent_testfiles/event_obj_attr_tag.json +57 -0
- tests/mispevent_testfiles/event_obj_def_param.json +62 -0
- tests/mispevent_testfiles/event_obj_tag.json +29 -0
- tests/mispevent_testfiles/event_tags.json +18 -0
- tests/mispevent_testfiles/existing_event.json +4599 -0
- tests/mispevent_testfiles/existing_event_edited.json +4601 -0
- tests/mispevent_testfiles/galaxy.json +25 -0
- tests/mispevent_testfiles/malware.json +19 -0
- tests/mispevent_testfiles/malware_exist.json +163 -0
- tests/mispevent_testfiles/misp_custom_obj.json +38 -0
- tests/mispevent_testfiles/overwrite_file/definition.json +457 -0
- tests/mispevent_testfiles/proposals.json +35 -0
- tests/mispevent_testfiles/shadow.json +148 -0
- tests/mispevent_testfiles/sighting.json +5 -0
- tests/mispevent_testfiles/simple.json +2 -0
- tests/mispevent_testfiles/test_object_template/definition.json +29 -0
- tests/new_misp_event.json +34 -0
- tests/reportlab_testfiles/HTML_event.json +1 -0
- tests/reportlab_testfiles/galaxy_1.json +1250 -0
- tests/reportlab_testfiles/image_event.json +2490 -0
- tests/reportlab_testfiles/japanese_test.json +156 -0
- tests/reportlab_testfiles/japanese_test_heavy.json +318 -0
- tests/reportlab_testfiles/long_event.json +3730 -0
- tests/reportlab_testfiles/mainly_objects_1.json +1092 -0
- tests/reportlab_testfiles/mainly_objects_2.json +977 -0
- tests/reportlab_testfiles/sighting_1.json +305 -0
- tests/reportlab_testfiles/sighting_2.json +221 -0
- tests/reportlab_testfiles/to_delete1.json +804 -0
- tests/reportlab_testfiles/to_delete2.json +1 -0
- tests/reportlab_testfiles/to_delete3.json +1 -0
- tests/reportlab_testfiles/very_long_event.json +1006 -0
- tests/reportlab_testoutputs/to_delete1.json.pdf +391 -0
- tests/reportlab_testoutputs/to_delete2.json.pdf +506 -0
- tests/reportlab_testoutputs/to_delete3.json.pdf +277 -0
- tests/search_index_result.json +69 -0
- tests/sharing_groups.json +98 -0
- tests/stix1.xml-utf8 +110 -0
- tests/stix2.json +1 -0
- tests/test_analyst_data.py +123 -0
- tests/test_emailobject.py +157 -0
- tests/test_fileobject.py +20 -0
- tests/test_mispevent.py +473 -0
- tests/test_reportlab.py +431 -0
- tests/testlive_comprehensive.py +3734 -0
- tests/testlive_sync.py +474 -0
- pymisp/data/misp-objects/.git +0 -1
- pymisp/data/misp-objects/.gitchangelog.rc +0 -289
- pymisp/data/misp-objects/.github/workflows/codeql.yml +0 -41
- pymisp/data/misp-objects/.github/workflows/nosetests.yml +0 -39
- pymisp/data/misp-objects/.travis.yml +0 -16
- pymisp/data/misp-objects/LICENSE-software-only.md +0 -661
- pymisp/data/misp-objects/LICENSE.md +0 -36
- pymisp/data/misp-objects/README.md +0 -566
- pymisp/data/misp-objects/docs/time-related-objects.ods +0 -0
- pymisp/data/misp-objects/docs/time-related-objects.pdf +0 -0
- pymisp/data/misp-objects/jq_all_the_things.sh +0 -29
- pymisp/data/misp-objects/tools/adoc_objects.py +0 -145
- pymisp/data/misp-objects/tools/alfred_links_to_relarelationships.py +0 -48
- pymisp/data/misp-objects/tools/list_of_objects.py +0 -50
- pymisp/data/misp-objects/tools/updated.sh +0 -6
- pymisp/data/misp-objects/tools/validate_opposites.sh +0 -17
- pymisp/data/misp-objects/unique_uuid.py +0 -16
- pymisp/data/misp-objects/validate_all.sh +0 -38
- {pymisp-2.5.3.dist-info → pymisp-2.5.7.dist-info}/LICENSE +0 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import unittest
|
|
6
|
+
from pymisp import (MISPAttribute, MISPEvent, MISPEventReport, MISPNote,
|
|
7
|
+
MISPObject, MISPOpinion)
|
|
8
|
+
from uuid import uuid4
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TestAnalystData(unittest.TestCase):
|
|
12
|
+
def setUp(self) -> None:
|
|
13
|
+
self.note_dict = {
|
|
14
|
+
"uuid": uuid4(),
|
|
15
|
+
"note": "note3"
|
|
16
|
+
}
|
|
17
|
+
self.opinion_dict = {
|
|
18
|
+
"uuid": uuid4(),
|
|
19
|
+
"opinion": 75,
|
|
20
|
+
"comment": "Agree"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
def test_analyst_data_on_attribute(self) -> None:
|
|
24
|
+
attribute = MISPAttribute()
|
|
25
|
+
attribute.from_dict(type='filename', value='foo.exe')
|
|
26
|
+
self._attach_analyst_data(attribute)
|
|
27
|
+
|
|
28
|
+
def test_analyst_data_on_attribute_alternative(self) -> None:
|
|
29
|
+
event = MISPEvent()
|
|
30
|
+
event.info = 'Test on Attribute'
|
|
31
|
+
event.add_attribute('domain', 'foo.bar')
|
|
32
|
+
self._attach_analyst_data(event.attributes[0])
|
|
33
|
+
|
|
34
|
+
def test_analyst_data_on_event(self) -> None:
|
|
35
|
+
event = MISPEvent()
|
|
36
|
+
event.info = 'Test Event'
|
|
37
|
+
self._attach_analyst_data(event)
|
|
38
|
+
|
|
39
|
+
def test_analyst_data_on_event_report(self) -> None:
|
|
40
|
+
event_report = MISPEventReport()
|
|
41
|
+
event_report.from_dict(name='Test Report', content='This is a report')
|
|
42
|
+
self._attach_analyst_data(event_report)
|
|
43
|
+
|
|
44
|
+
def test_analyst_data_on_event_report_alternative(self) -> None:
|
|
45
|
+
event = MISPEvent()
|
|
46
|
+
event.info = 'Test on Event Report'
|
|
47
|
+
event.add_event_report('Test Report', 'This is a report')
|
|
48
|
+
self._attach_analyst_data(event.event_reports[0])
|
|
49
|
+
|
|
50
|
+
def test_analyst_data_on_object(self) -> None:
|
|
51
|
+
misp_object = MISPObject('file')
|
|
52
|
+
misp_object.add_attribute('filename', 'foo.exe')
|
|
53
|
+
self._attach_analyst_data(misp_object)
|
|
54
|
+
|
|
55
|
+
def test_analyst_data_on_object_alternative(self) -> None:
|
|
56
|
+
event = MISPEvent()
|
|
57
|
+
event.info = 'Test on Object'
|
|
58
|
+
misp_object = MISPObject('file')
|
|
59
|
+
misp_object.add_attribute('filename', 'foo.exe')
|
|
60
|
+
event.add_object(misp_object)
|
|
61
|
+
self._attach_analyst_data(event.objects[0])
|
|
62
|
+
|
|
63
|
+
def test_analyst_data_on_object_attribute(self) -> None:
|
|
64
|
+
misp_object = MISPObject('file')
|
|
65
|
+
object_attribute = misp_object.add_attribute('filename', 'foo.exe')
|
|
66
|
+
self._attach_analyst_data(object_attribute)
|
|
67
|
+
|
|
68
|
+
def test_analyst_data_object_object_attribute_alternative(self) -> None:
|
|
69
|
+
misp_object = MISPObject('file')
|
|
70
|
+
misp_object.add_attribute('filename', 'foo.exe')
|
|
71
|
+
self._attach_analyst_data(misp_object.attributes[0])
|
|
72
|
+
|
|
73
|
+
def _attach_analyst_data(
|
|
74
|
+
self, container: MISPAttribute | MISPEvent | MISPEventReport | MISPObject) -> None:
|
|
75
|
+
object_type = container._analyst_data_object_type
|
|
76
|
+
note1 = container.add_note(note='note1')
|
|
77
|
+
opinion1 = note1.add_opinion(opinion=25, comment='Disagree')
|
|
78
|
+
opinion2 = container.add_opinion(opinion=50, comment='Neutral')
|
|
79
|
+
note2 = opinion2.add_note(note='note2')
|
|
80
|
+
|
|
81
|
+
dict_note = MISPNote()
|
|
82
|
+
dict_note.from_dict(
|
|
83
|
+
object_type=object_type, object_uuid=container.uuid, **self.note_dict
|
|
84
|
+
)
|
|
85
|
+
note3 = container.add_note(**dict_note)
|
|
86
|
+
dict_opinion = MISPOpinion()
|
|
87
|
+
dict_opinion.from_dict(
|
|
88
|
+
object_type='Note', object_uuid=note3.uuid, **self.opinion_dict
|
|
89
|
+
)
|
|
90
|
+
container.add_opinion(**dict_opinion)
|
|
91
|
+
|
|
92
|
+
self.assertEqual(len(container.notes), 3)
|
|
93
|
+
self.assertEqual(len(container.opinions), 3)
|
|
94
|
+
|
|
95
|
+
misp_note1, misp_note2, misp_note3 = container.notes
|
|
96
|
+
misp_opinion1, misp_opinion2, misp_opinion3 = container.opinions
|
|
97
|
+
|
|
98
|
+
self.assertEqual(misp_note1.object_type, object_type)
|
|
99
|
+
self.assertEqual(misp_note1.object_uuid, container.uuid)
|
|
100
|
+
self.assertEqual(misp_note1.note, 'note1')
|
|
101
|
+
|
|
102
|
+
self.assertEqual(misp_note2.object_type, 'Opinion')
|
|
103
|
+
self.assertEqual(misp_note2.object_uuid, opinion2.uuid)
|
|
104
|
+
self.assertEqual(misp_note2.note, 'note2')
|
|
105
|
+
|
|
106
|
+
self.assertEqual(misp_note3.object_type, object_type)
|
|
107
|
+
self.assertEqual(misp_note3.object_uuid, container.uuid)
|
|
108
|
+
self.assertEqual(misp_note3.note, 'note3')
|
|
109
|
+
|
|
110
|
+
self.assertEqual(misp_opinion1.object_type, 'Note')
|
|
111
|
+
self.assertEqual(misp_opinion1.object_uuid, note1.uuid)
|
|
112
|
+
self.assertEqual(misp_opinion1.opinion, 25)
|
|
113
|
+
self.assertEqual(misp_opinion1.comment, 'Disagree')
|
|
114
|
+
|
|
115
|
+
self.assertEqual(misp_opinion2.object_type, object_type)
|
|
116
|
+
self.assertEqual(misp_opinion2.object_uuid, container.uuid)
|
|
117
|
+
self.assertEqual(misp_opinion2.opinion, 50)
|
|
118
|
+
self.assertEqual(misp_opinion2.comment, 'Neutral')
|
|
119
|
+
|
|
120
|
+
self.assertEqual(misp_opinion3.object_type, 'Note')
|
|
121
|
+
self.assertEqual(misp_opinion3.object_uuid, note3.uuid)
|
|
122
|
+
self.assertEqual(misp_opinion3.opinion, 75)
|
|
123
|
+
self.assertEqual(misp_opinion3.comment, 'Agree')
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
# import json
|
|
4
|
+
import unittest
|
|
5
|
+
|
|
6
|
+
from email.message import EmailMessage
|
|
7
|
+
from io import BytesIO
|
|
8
|
+
from os import urandom
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import TypeVar, Type
|
|
11
|
+
from zipfile import ZipFile
|
|
12
|
+
|
|
13
|
+
from pymisp.tools import EMailObject
|
|
14
|
+
from pymisp.exceptions import PyMISPNotImplementedYet, InvalidMISPObject
|
|
15
|
+
|
|
16
|
+
T = TypeVar('T', bound='TestEmailObject')
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TestEmailObject(unittest.TestCase):
|
|
20
|
+
|
|
21
|
+
eml_1: BytesIO
|
|
22
|
+
|
|
23
|
+
@classmethod
|
|
24
|
+
def setUpClass(cls: type[T]) -> None:
|
|
25
|
+
with ZipFile(Path("tests/email_testfiles/mail_1.eml.zip"), 'r') as myzip:
|
|
26
|
+
with myzip.open('mail_1.eml', pwd=b'AVs are dumb') as myfile:
|
|
27
|
+
cls.eml_1 = BytesIO(myfile.read())
|
|
28
|
+
|
|
29
|
+
def test_mail_1(self) -> None:
|
|
30
|
+
email_object = EMailObject(pseudofile=self.eml_1)
|
|
31
|
+
self.assertEqual(self._get_values(email_object, "subject")[0], "письмо уведом-е")
|
|
32
|
+
self.assertEqual(self._get_values(email_object, "to")[0], "kinney@noth.com")
|
|
33
|
+
self.assertEqual(self._get_values(email_object, "from")[0], "suvorov.s@nalg.ru")
|
|
34
|
+
self.assertEqual(self._get_values(email_object, "from-display-name")[0], "служба ФНС Даниил Суворов")
|
|
35
|
+
self.assertEqual(len(self._get_values(email_object, "email-body")), 1)
|
|
36
|
+
|
|
37
|
+
self.assertEqual(self._get_values(email_object, "received-header-ip"),
|
|
38
|
+
['64.98.42.207', '2603:10b6:207:3d::31',
|
|
39
|
+
'2a01:111:f400:7e49::205', '43.230.105.145'])
|
|
40
|
+
|
|
41
|
+
self.assertIsInstance(email_object.email, EmailMessage)
|
|
42
|
+
for file_name, file_content in email_object.attachments:
|
|
43
|
+
self.assertIsInstance(file_name, str)
|
|
44
|
+
self.assertIsInstance(file_content, BytesIO)
|
|
45
|
+
|
|
46
|
+
def test_mail_1_headers_only(self) -> None:
|
|
47
|
+
email_object = EMailObject(Path("tests/email_testfiles/mail_1_headers_only.eml"))
|
|
48
|
+
self.assertEqual(self._get_values(email_object, "subject")[0], "письмо уведом-е")
|
|
49
|
+
self.assertEqual(self._get_values(email_object, "to")[0], "kinney@noth.com")
|
|
50
|
+
self.assertEqual(self._get_values(email_object, "from")[0], "suvorov.s@nalg.ru")
|
|
51
|
+
|
|
52
|
+
self.assertEqual(len(self._get_values(email_object, "email-body")), 0)
|
|
53
|
+
|
|
54
|
+
self.assertIsInstance(email_object.email, EmailMessage)
|
|
55
|
+
self.assertEqual(len(email_object.attachments), 0)
|
|
56
|
+
|
|
57
|
+
def test_mail_multiple_to(self) -> None:
|
|
58
|
+
email_object = EMailObject(Path("tests/email_testfiles/mail_multiple_to.eml"))
|
|
59
|
+
|
|
60
|
+
to = self._get_values(email_object, "to")
|
|
61
|
+
to_display_name = self._get_values(email_object, "to-display-name")
|
|
62
|
+
self.assertEqual(to[0], "jan.novak@example.com")
|
|
63
|
+
self.assertEqual(to_display_name[0], "Novak, Jan")
|
|
64
|
+
self.assertEqual(to[1], "jan.marek@example.com")
|
|
65
|
+
self.assertEqual(to_display_name[1], "Marek, Jan")
|
|
66
|
+
|
|
67
|
+
def test_msg(self) -> None:
|
|
68
|
+
# Test result of eml converted to msg is the same
|
|
69
|
+
eml_email_object = EMailObject(pseudofile=self.eml_1)
|
|
70
|
+
email_object = EMailObject(Path("tests/email_testfiles/mail_1.msg"))
|
|
71
|
+
|
|
72
|
+
self.assertIsInstance(email_object.email, EmailMessage)
|
|
73
|
+
for file_name, file_content in email_object.attachments:
|
|
74
|
+
self.assertIsInstance(file_name, str)
|
|
75
|
+
self.assertIsInstance(file_content, BytesIO)
|
|
76
|
+
|
|
77
|
+
self.assertEqual(self._get_values(email_object, "subject")[0],
|
|
78
|
+
self._get_values(eml_email_object, "subject")[0])
|
|
79
|
+
self.assertEqual(self._get_values(email_object, "to")[0],
|
|
80
|
+
self._get_values(eml_email_object, "to")[0])
|
|
81
|
+
self.assertEqual(self._get_values(email_object, "from")[0],
|
|
82
|
+
self._get_values(eml_email_object, "from")[0])
|
|
83
|
+
self.assertEqual(self._get_values(email_object, "from-display-name")[0],
|
|
84
|
+
self._get_values(eml_email_object, "from-display-name")[0])
|
|
85
|
+
self.assertEqual(len(self._get_values(email_object, "email-body")), 2)
|
|
86
|
+
|
|
87
|
+
self.assertEqual(self._get_values(email_object, "received-header-ip"),
|
|
88
|
+
self._get_values(eml_email_object, "received-header-ip"))
|
|
89
|
+
|
|
90
|
+
def test_bom_encoded(self) -> None:
|
|
91
|
+
"""Test utf-8-sig encoded email"""
|
|
92
|
+
bom_email_object = EMailObject(Path("tests/email_testfiles/mail_1_bom.eml"))
|
|
93
|
+
eml_email_object = EMailObject(pseudofile=self.eml_1)
|
|
94
|
+
|
|
95
|
+
self.assertIsInstance(bom_email_object.email, EmailMessage)
|
|
96
|
+
for file_name, file_content in bom_email_object.attachments:
|
|
97
|
+
self.assertIsInstance(file_name, str)
|
|
98
|
+
self.assertIsInstance(file_content, BytesIO)
|
|
99
|
+
|
|
100
|
+
self.assertEqual(self._get_values(bom_email_object, "subject")[0],
|
|
101
|
+
self._get_values(eml_email_object, "subject")[0])
|
|
102
|
+
self.assertEqual(self._get_values(bom_email_object, "to")[0],
|
|
103
|
+
self._get_values(eml_email_object, "to")[0])
|
|
104
|
+
self.assertEqual(self._get_values(bom_email_object, "from")[0],
|
|
105
|
+
self._get_values(eml_email_object, "from")[0])
|
|
106
|
+
self.assertEqual(self._get_values(bom_email_object, "from-display-name")[0],
|
|
107
|
+
self._get_values(eml_email_object, "from-display-name")[0])
|
|
108
|
+
self.assertEqual(len(self._get_values(bom_email_object, "email-body")), 1)
|
|
109
|
+
|
|
110
|
+
self.assertEqual(self._get_values(bom_email_object, "received-header-ip"),
|
|
111
|
+
self._get_values(eml_email_object, "received-header-ip"))
|
|
112
|
+
|
|
113
|
+
def test_handling_of_various_email_types(self) -> None:
|
|
114
|
+
self._does_not_fail(Path("tests/email_testfiles/mail_2.eml"),
|
|
115
|
+
"ensuring all headers work")
|
|
116
|
+
self._does_not_fail(Path('tests/email_testfiles/mail_3.eml'),
|
|
117
|
+
"Check for related content in emails emls")
|
|
118
|
+
self._does_not_fail(Path('tests/email_testfiles/mail_3.msg'),
|
|
119
|
+
"Check for related content in emails msgs")
|
|
120
|
+
self._does_not_fail(Path('tests/email_testfiles/mail_4.msg'),
|
|
121
|
+
"Check that HTML without specific encoding")
|
|
122
|
+
self._does_not_fail(Path('tests/email_testfiles/mail_5.msg'),
|
|
123
|
+
"Check encapsulated HTML works")
|
|
124
|
+
|
|
125
|
+
def _does_not_fail(self, path: Path, test_type: str="test") -> None:
|
|
126
|
+
found_error = None
|
|
127
|
+
try:
|
|
128
|
+
EMailObject(path)
|
|
129
|
+
except Exception as _e:
|
|
130
|
+
found_error = _e
|
|
131
|
+
if found_error is not None:
|
|
132
|
+
self.fail('Error {} raised when parsing test email {} which tests against {}. It should not have raised an error.'.format(
|
|
133
|
+
type(found_error),
|
|
134
|
+
path,
|
|
135
|
+
test_type))
|
|
136
|
+
|
|
137
|
+
def test_random_binary_blob(self) -> None:
|
|
138
|
+
"""Email parser fails correctly on random binary blob."""
|
|
139
|
+
random_data = urandom(1024)
|
|
140
|
+
random_blob = BytesIO(random_data)
|
|
141
|
+
found_error = None
|
|
142
|
+
try:
|
|
143
|
+
broken_obj = EMailObject(pseudofile=random_data)
|
|
144
|
+
except Exception as _e:
|
|
145
|
+
found_error = _e
|
|
146
|
+
if not isinstance(found_error, InvalidMISPObject):
|
|
147
|
+
self.fail("Expected InvalidMISPObject when EmailObject receives completely unknown binary input data. But, did not get that exception.")
|
|
148
|
+
try:
|
|
149
|
+
broken_obj = EMailObject(pseudofile=random_blob)
|
|
150
|
+
except Exception as _e:
|
|
151
|
+
found_error = _e
|
|
152
|
+
if not isinstance(found_error, InvalidMISPObject):
|
|
153
|
+
self.fail("Expected InvalidMISPObject when EmailObject receives completely unknown binary input data in a pseudofile. But, did not get that exception.")
|
|
154
|
+
|
|
155
|
+
@staticmethod
|
|
156
|
+
def _get_values(obj: EMailObject, relation: str) -> list[str]:
|
|
157
|
+
return [attr.value for attr in obj.attributes if attr['object_relation'] == relation]
|
tests/test_fileobject.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import unittest
|
|
6
|
+
import json
|
|
7
|
+
from pymisp.tools import FileObject
|
|
8
|
+
import pathlib
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TestFileObject(unittest.TestCase):
|
|
12
|
+
def test_mimeType(self) -> None:
|
|
13
|
+
file_object = FileObject(filepath=pathlib.Path(__file__))
|
|
14
|
+
attributes = json.loads(file_object.to_json())['Attribute']
|
|
15
|
+
mime = next(attr for attr in attributes if attr['object_relation'] == 'mimetype')
|
|
16
|
+
# was "Python script, ASCII text executable"
|
|
17
|
+
# libmagic on linux: 'text/x-python'
|
|
18
|
+
# libmagic on os x: 'text/x-script.python'
|
|
19
|
+
self.assertEqual(mime['value'][:7], 'text/x-')
|
|
20
|
+
self.assertEqual(mime['value'][-6:], 'python')
|