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.

Files changed (162) hide show
  1. CHANGELOG.txt +5380 -0
  2. examples/__init__.py +0 -0
  3. examples/add_attributes_from_csv.py +74 -0
  4. examples/add_email_object.py +29 -0
  5. examples/add_fail2ban_object.py +86 -0
  6. examples/add_feed.py +25 -0
  7. examples/add_file_object.py +47 -0
  8. examples/add_filetype_object_from_csv.py +53 -0
  9. examples/add_generic_object.py +26 -0
  10. examples/add_github_user.py +65 -0
  11. examples/add_gitlab_user.py +56 -0
  12. examples/add_named_attribute.py +25 -0
  13. examples/add_organisations.py +57 -0
  14. examples/add_ssh_authorized_keys.py +29 -0
  15. examples/add_user.py +22 -0
  16. examples/add_vehicle_object.py +22 -0
  17. examples/addtag2.py +45 -0
  18. examples/asciidoc_generator.py +114 -0
  19. examples/cache_all.py +10 -0
  20. examples/copyTagsFromAttributesToEvent.py +68 -0
  21. examples/copy_list.py +93 -0
  22. examples/create_events.py +26 -0
  23. examples/cytomic_orion.py +549 -0
  24. examples/del.py +22 -0
  25. examples/delete_user.py +16 -0
  26. examples/edit_organisation.py +20 -0
  27. examples/edit_user.py +20 -0
  28. examples/falsepositive_disabletoids.py +136 -0
  29. examples/fetch_events_feed.py +15 -0
  30. examples/fetch_warninglist_hits.py +38 -0
  31. examples/freetext.py +22 -0
  32. examples/generate_file_objects.py +78 -0
  33. examples/generate_meta_feed.py +15 -0
  34. examples/get.py +37 -0
  35. examples/get_csv.py +37 -0
  36. examples/get_network_activity.py +187 -0
  37. examples/last.py +48 -0
  38. examples/load_csv.py +94 -0
  39. examples/lookup.py +28 -0
  40. examples/misp2cef.py +71 -0
  41. examples/misp2clamav.py +52 -0
  42. examples/openioc_to_misp.py +27 -0
  43. examples/proofpoint_tap.py +203 -0
  44. examples/proofpoint_vap.py +65 -0
  45. examples/search.py +48 -0
  46. examples/search_attributes_yara.py +40 -0
  47. examples/search_sighting.py +42 -0
  48. examples/server_sync_check_conn.py +32 -0
  49. examples/sharing_groups.py +15 -0
  50. examples/show_sightings.py +168 -0
  51. examples/stats_report.py +405 -0
  52. examples/sync_sighting.py +171 -0
  53. examples/tags.py +25 -0
  54. examples/test_sign.py +19 -0
  55. examples/trustar_misp.py +59 -0
  56. examples/up.py +21 -0
  57. examples/upload.py +60 -0
  58. examples/users_list.py +15 -0
  59. examples/vmray_automation.py +281 -0
  60. examples/vt_to_misp.py +182 -0
  61. examples/warninglists.py +22 -0
  62. examples/yara.py +38 -0
  63. examples/yara_dump.py +98 -0
  64. pymisp/api.py +33 -5
  65. pymisp/data/misp-objects/objects/android-app/definition.json +8 -2
  66. pymisp/data/misp-objects/objects/instagram-account/definition.json +66 -0
  67. pymisp/data/misp-objects/objects/lnk/definition.json +13 -1
  68. pymisp/data/misp-objects/objects/rmm/definition.json +88 -0
  69. pymisp/data/misp-objects/objects/spambee-report/definition.json +54 -0
  70. pymisp/data/misp-objects/objects/target-system/definition.json +2 -2
  71. pymisp/data/misp-objects/objects/vulnerability/definition.json +5 -4
  72. pymisp/data/misp-objects/relationships/definition.json +17 -1
  73. pymisp/data/misp-objects/schema_objects.json +1 -1
  74. pymisp/mispevent.py +95 -23
  75. {pymisp-2.5.3.dist-info → pymisp-2.5.7.dist-info}/METADATA +23 -28
  76. {pymisp-2.5.3.dist-info → pymisp-2.5.7.dist-info}/RECORD +144 -30
  77. {pymisp-2.5.3.dist-info → pymisp-2.5.7.dist-info}/WHEEL +1 -1
  78. tests/57c4445b-c548-4654-af0b-4be3950d210f.json +1 -0
  79. tests/__init__.py +0 -0
  80. tests/csv_testfiles/invalid_fieldnames.csv +11 -0
  81. tests/csv_testfiles/valid_fieldnames.csv +4 -0
  82. tests/email_testfiles/mail_1.eml.zip +0 -0
  83. tests/email_testfiles/mail_1.msg +0 -0
  84. tests/email_testfiles/mail_1_bom.eml +858 -0
  85. tests/email_testfiles/mail_1_headers_only.eml +28 -0
  86. tests/email_testfiles/mail_2.eml +32 -0
  87. tests/email_testfiles/mail_3.eml +170 -0
  88. tests/email_testfiles/mail_3.msg +0 -0
  89. tests/email_testfiles/mail_4.msg +0 -0
  90. tests/email_testfiles/mail_5.msg +0 -0
  91. tests/email_testfiles/mail_multiple_to.eml +15 -0
  92. tests/email_testfiles/source +1 -0
  93. tests/git-vuln-finder-quagga.json +1493 -0
  94. tests/misp_event.json +76 -0
  95. tests/mispevent_testfiles/attribute.json +21 -0
  96. tests/mispevent_testfiles/attribute_del.json +23 -0
  97. tests/mispevent_testfiles/def_param.json +53 -0
  98. tests/mispevent_testfiles/event.json +8 -0
  99. tests/mispevent_testfiles/event_obj_attr_tag.json +57 -0
  100. tests/mispevent_testfiles/event_obj_def_param.json +62 -0
  101. tests/mispevent_testfiles/event_obj_tag.json +29 -0
  102. tests/mispevent_testfiles/event_tags.json +18 -0
  103. tests/mispevent_testfiles/existing_event.json +4599 -0
  104. tests/mispevent_testfiles/existing_event_edited.json +4601 -0
  105. tests/mispevent_testfiles/galaxy.json +25 -0
  106. tests/mispevent_testfiles/malware.json +19 -0
  107. tests/mispevent_testfiles/malware_exist.json +163 -0
  108. tests/mispevent_testfiles/misp_custom_obj.json +38 -0
  109. tests/mispevent_testfiles/overwrite_file/definition.json +457 -0
  110. tests/mispevent_testfiles/proposals.json +35 -0
  111. tests/mispevent_testfiles/shadow.json +148 -0
  112. tests/mispevent_testfiles/sighting.json +5 -0
  113. tests/mispevent_testfiles/simple.json +2 -0
  114. tests/mispevent_testfiles/test_object_template/definition.json +29 -0
  115. tests/new_misp_event.json +34 -0
  116. tests/reportlab_testfiles/HTML_event.json +1 -0
  117. tests/reportlab_testfiles/galaxy_1.json +1250 -0
  118. tests/reportlab_testfiles/image_event.json +2490 -0
  119. tests/reportlab_testfiles/japanese_test.json +156 -0
  120. tests/reportlab_testfiles/japanese_test_heavy.json +318 -0
  121. tests/reportlab_testfiles/long_event.json +3730 -0
  122. tests/reportlab_testfiles/mainly_objects_1.json +1092 -0
  123. tests/reportlab_testfiles/mainly_objects_2.json +977 -0
  124. tests/reportlab_testfiles/sighting_1.json +305 -0
  125. tests/reportlab_testfiles/sighting_2.json +221 -0
  126. tests/reportlab_testfiles/to_delete1.json +804 -0
  127. tests/reportlab_testfiles/to_delete2.json +1 -0
  128. tests/reportlab_testfiles/to_delete3.json +1 -0
  129. tests/reportlab_testfiles/very_long_event.json +1006 -0
  130. tests/reportlab_testoutputs/to_delete1.json.pdf +391 -0
  131. tests/reportlab_testoutputs/to_delete2.json.pdf +506 -0
  132. tests/reportlab_testoutputs/to_delete3.json.pdf +277 -0
  133. tests/search_index_result.json +69 -0
  134. tests/sharing_groups.json +98 -0
  135. tests/stix1.xml-utf8 +110 -0
  136. tests/stix2.json +1 -0
  137. tests/test_analyst_data.py +123 -0
  138. tests/test_emailobject.py +157 -0
  139. tests/test_fileobject.py +20 -0
  140. tests/test_mispevent.py +473 -0
  141. tests/test_reportlab.py +431 -0
  142. tests/testlive_comprehensive.py +3734 -0
  143. tests/testlive_sync.py +474 -0
  144. pymisp/data/misp-objects/.git +0 -1
  145. pymisp/data/misp-objects/.gitchangelog.rc +0 -289
  146. pymisp/data/misp-objects/.github/workflows/codeql.yml +0 -41
  147. pymisp/data/misp-objects/.github/workflows/nosetests.yml +0 -39
  148. pymisp/data/misp-objects/.travis.yml +0 -16
  149. pymisp/data/misp-objects/LICENSE-software-only.md +0 -661
  150. pymisp/data/misp-objects/LICENSE.md +0 -36
  151. pymisp/data/misp-objects/README.md +0 -566
  152. pymisp/data/misp-objects/docs/time-related-objects.ods +0 -0
  153. pymisp/data/misp-objects/docs/time-related-objects.pdf +0 -0
  154. pymisp/data/misp-objects/jq_all_the_things.sh +0 -29
  155. pymisp/data/misp-objects/tools/adoc_objects.py +0 -145
  156. pymisp/data/misp-objects/tools/alfred_links_to_relarelationships.py +0 -48
  157. pymisp/data/misp-objects/tools/list_of_objects.py +0 -50
  158. pymisp/data/misp-objects/tools/updated.sh +0 -6
  159. pymisp/data/misp-objects/tools/validate_opposites.sh +0 -17
  160. pymisp/data/misp-objects/unique_uuid.py +0 -16
  161. pymisp/data/misp-objects/validate_all.sh +0 -38
  162. {pymisp-2.5.3.dist-info → pymisp-2.5.7.dist-info}/LICENSE +0 -0
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ '''
4
+ Koen Van Impe
5
+
6
+ Disable the to_ids flag of an attribute when there are to many false positives
7
+ Put this script in crontab to run every /15 or /60
8
+ */5 * * * * mispuser /usr/bin/python3 /home/mispuser/PyMISP/examples/falsepositive_disabletoids.py
9
+
10
+ Do inline config in "main"
11
+
12
+ '''
13
+
14
+ from pymisp import ExpandedPyMISP, MISPEvent
15
+ from keys import misp_url, misp_key, misp_verifycert
16
+ from datetime import datetime
17
+ from datetime import date
18
+
19
+ import datetime as dt
20
+ import smtplib
21
+ import mimetypes
22
+ from email.mime.multipart import MIMEMultipart
23
+ from email import encoders
24
+ from email.mime.base import MIMEBase
25
+ from email.mime.text import MIMEText
26
+ import argparse
27
+
28
+
29
+ def init(url, key, verifycert):
30
+ '''
31
+ Template to get MISP module started
32
+ '''
33
+ return ExpandedPyMISP(url, key, verifycert, 'json')
34
+
35
+
36
+ if __name__ == '__main__':
37
+
38
+ minimal_fp = 0
39
+ threshold_to_ids = .50
40
+ minimal_date_sighting_date = '1970-01-01 00:00:00'
41
+
42
+ smtp_from = 'INSERT_FROM'
43
+ smtp_to = 'INSERT_TO'
44
+ smtp_server = 'localhost'
45
+ report_changes = ''
46
+ ts_format = '%Y-%m-%d %H:%M:%S'
47
+
48
+ parser = argparse.ArgumentParser(description="Disable the to_ids flag of attributes with a certain number of false positives above a threshold.")
49
+ parser.add_argument('-m', '--mail', action='store_true', help='Mail the report')
50
+ parser.add_argument('-o', '--mailoptions', action='store', help='mailoptions: \'smtp_from=INSERT_FROM;smtp_to=INSERT_TO;smtp_server=localhost\'')
51
+ parser.add_argument('-b', '--minimal-fp', default=minimal_fp, type=int, help='Minimal number of false positive (default: %(default)s )')
52
+ parser.add_argument('-t', '--threshold', default=threshold_to_ids, type=float, help='Threshold false positive/true positive rate (default: %(default)s )')
53
+ parser.add_argument('-d', '--minimal-date-sighting', default=minimal_date_sighting_date, help='Minimal date for sighting (false positive / true positive) (default: %(default)s )')
54
+
55
+ args = parser.parse_args()
56
+ misp = init(misp_url, misp_key, misp_verifycert)
57
+
58
+ minimal_fp = int(args.minimal_fp)
59
+ threshold_to_ids = args.threshold
60
+ minimal_date_sighting_date = args.minimal_date_sighting
61
+ minimal_date_sighting = int(dt.datetime.strptime(minimal_date_sighting_date, '%Y-%m-%d %H:%M:%S').strftime("%s"))
62
+
63
+ # Fetch all the attributes
64
+ result = misp.search('attributes', to_ids=1, include_sightings=1)
65
+
66
+ if 'Attribute' in result:
67
+ for attribute in result['Attribute']:
68
+ true_positive = 0
69
+ false_positive = 0
70
+ compute_threshold = 0
71
+ attribute_id = attribute['id']
72
+ attribute_value = attribute['value']
73
+ attribute_uuid = attribute['uuid']
74
+ event_id = attribute['event_id']
75
+
76
+ # Only do something if there is a sighting
77
+ if 'Sighting' in attribute:
78
+
79
+ for sighting in attribute['Sighting']:
80
+ if int(sighting['date_sighting']) > minimal_date_sighting:
81
+ if int(sighting['type']) == 0:
82
+ true_positive = true_positive + 1
83
+ elif int(sighting['type']) == 1:
84
+ false_positive = false_positive + 1
85
+
86
+ if false_positive > minimal_fp:
87
+ compute_threshold = false_positive / (true_positive + false_positive)
88
+
89
+ if compute_threshold >= threshold_to_ids:
90
+ # Fetch event title for report text
91
+ event_details = misp.get_event(event_id)
92
+ event_info = event_details['Event']['info']
93
+
94
+ misp.update_attribute( { 'uuid': attribute_uuid, 'to_ids': 0})
95
+
96
+ report_changes = report_changes + 'Disable to_ids for [%s] (%s) in event [%s] (%s) - FP: %s TP: %s \n' % (attribute_value, attribute_id, event_info, event_id, false_positive, true_positive)
97
+
98
+ # Changing the attribute to_ids flag sets the event to unpublished
99
+ misp.publish(event_id)
100
+
101
+ # Only send/print the report if it contains content
102
+ if report_changes:
103
+ if args.mail:
104
+ if args.mailoptions:
105
+ mailoptions = args.mailoptions.split(';')
106
+ for s in mailoptions:
107
+ if s.split('=')[0] == 'smtp_from':
108
+ smtp_from = s.split('=')[1]
109
+ if s.split('=')[0] == 'smtp_to':
110
+ smtp_to = s.split('=')[1]
111
+ if s.split('=')[0] == 'smtp_server':
112
+ smtp_server = s.split('=')[1]
113
+
114
+ now = datetime.now()
115
+ current_date = now.strftime(ts_format)
116
+ report_changes_body = 'MISP Disable to_ids flags for %s on %s\n-------------------------------------------------------------------------------\n\n' % (misp_url, current_date)
117
+ report_changes_body = report_changes_body + 'Minimal number of false positives before considering threshold: %s\n' % (minimal_fp)
118
+ report_changes_body = report_changes_body + 'Threshold false positives/true positives to disable to_ids flag: %s\n' % (threshold_to_ids)
119
+ report_changes_body = report_changes_body + 'Minimal date for sighting false positives: %s\n\n' % (minimal_date_sighting_date)
120
+ report_changes_body = report_changes_body + report_changes
121
+ report_changes_body = report_changes_body + '\nEvents that have attributes with changed to_ids flag have been republished, without e-mail notification.'
122
+ report_changes_body = report_changes_body + '\n\nMISP Disable to_ids Finished\n'
123
+
124
+ subject = 'Report of disable to_ids flag for false positives sightings of %s' % (current_date)
125
+ msg = MIMEMultipart()
126
+ msg['From'] = smtp_from
127
+ msg['To'] = smtp_to
128
+ msg['Subject'] = subject
129
+
130
+ msg.attach(MIMEText(report_changes_body, 'text'))
131
+ print(report_changes_body)
132
+ server = smtplib.SMTP(smtp_server)
133
+ server.sendmail(smtp_from, smtp_to, msg.as_string())
134
+
135
+ else:
136
+ print(report_changes)
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ from keys import misp_url, misp_key, misp_verifycert
5
+ import argparse
6
+ from pymisp import ExpandedPyMISP
7
+
8
+
9
+ if __name__ == '__main__':
10
+ parser = argparse.ArgumentParser(description='Fetch all events from a feed.')
11
+ parser.add_argument("-f", "--feed", required=True, help="feed's ID to be fetched.")
12
+ args = parser.parse_args()
13
+
14
+ misp = ExpandedPyMISP(misp_url, misp_key, misp_verifycert)
15
+ misp.fetch_feed(args.feed)
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ from pymisp import PyMISP
5
+ from keys import misp_url, misp_key
6
+ import argparse
7
+
8
+
9
+ def init(url, key):
10
+ return PyMISP(url, key)
11
+
12
+
13
+ def loop_attributes(elem):
14
+ if 'Attribute' in elem.keys():
15
+ for attribute in elem['Attribute']:
16
+ if 'warnings' in attribute.keys():
17
+ for warning in attribute['warnings']:
18
+ print("Value {} has a hit in warninglist with name '{}' and id '{}'".format(warning['value'],
19
+ warning[
20
+ 'warninglist_name'],
21
+ warning[
22
+ 'warninglist_id']))
23
+
24
+
25
+ if __name__ == '__main__':
26
+ parser = argparse.ArgumentParser(description='Print all warninglist hits for an event.')
27
+ parser.add_argument("eventid", type=str, help="The event id of the event to get info of")
28
+ args = parser.parse_args()
29
+ misp = init(misp_url, misp_key)
30
+ evt = misp.search('events', eventid=args.eventid, includeWarninglistHits=1)['response'][0]['Event']
31
+ if 'warnings' in evt.keys():
32
+ print('warnings in entire event:')
33
+ print(str(evt['warnings']) + '\n')
34
+ print('Warnings at attribute levels:')
35
+ loop_attributes(evt)
36
+ if 'Object' in evt.keys():
37
+ for obj in evt['Object']:
38
+ loop_attributes(obj)
examples/freetext.py ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ from pymisp import ExpandedPyMISP
5
+ from keys import misp_url, misp_key, misp_verifycert
6
+ import argparse
7
+
8
+ from io import open
9
+
10
+
11
+ if __name__ == '__main__':
12
+ parser = argparse.ArgumentParser(description="Update a MISP event.")
13
+ parser.add_argument("-e", "--event", required=True, help="Event ID to update.")
14
+ parser.add_argument("-i", "--input", required=True, help="Input file")
15
+
16
+ args = parser.parse_args()
17
+
18
+ pymisp = PyMISP(misp_url, misp_key, misp_verifycert)
19
+
20
+ with open(args.input, 'r') as f:
21
+ result = pymisp.freetext(args.event, f.read())
22
+ print(result)
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ import argparse
5
+ import json
6
+
7
+ try:
8
+ from pymisp import pymisp_json_default, AbstractMISP
9
+ from pymisp.tools import make_binary_objects
10
+ except ImportError:
11
+ pass
12
+
13
+
14
+ def check():
15
+ missing_dependencies = {'pydeep': False, 'lief': False, 'magic': False, 'pymisp': False}
16
+ try:
17
+ import pymisp # noqa
18
+ except ImportError:
19
+ missing_dependencies['pymisp'] = 'Please install pydeep: pip install pymisp'
20
+ try:
21
+ import pydeep # noqa
22
+ except ImportError:
23
+ missing_dependencies['pydeep'] = 'Please install pydeep: pip install git+https://github.com/kbandla/pydeep.git'
24
+ try:
25
+ import lief # noqa
26
+ except ImportError:
27
+ missing_dependencies['lief'] = 'Please install lief, documentation here: https://github.com/lief-project/LIEF'
28
+ try:
29
+ import magic # noqa
30
+ except ImportError:
31
+ missing_dependencies['magic'] = 'Please install python-magic: pip install python-magic.'
32
+ return json.dumps(missing_dependencies)
33
+
34
+
35
+ def make_objects(path):
36
+ to_return = {'objects': [], 'references': []}
37
+ fo, peo, seos = make_binary_objects(path)
38
+
39
+ if seos:
40
+ for s in seos:
41
+ to_return['objects'].append(s)
42
+ if s.ObjectReference:
43
+ to_return['references'] += s.ObjectReference
44
+
45
+ if peo:
46
+ if hasattr(peo, 'certificates') and hasattr(peo, 'signers'):
47
+ # special authenticode case for PE objects
48
+ for c in peo.certificates:
49
+ to_return['objects'].append(c)
50
+ for s in peo.signers:
51
+ to_return['objects'].append(s)
52
+ del peo.certificates
53
+ del peo.signers
54
+ del peo.sections
55
+ to_return['objects'].append(peo)
56
+ if peo.ObjectReference:
57
+ to_return['references'] += peo.ObjectReference
58
+
59
+ if fo:
60
+ to_return['objects'].append(fo)
61
+ if fo.ObjectReference:
62
+ to_return['references'] += fo.ObjectReference
63
+ return json.dumps(to_return, default=pymisp_json_default)
64
+
65
+
66
+ if __name__ == '__main__':
67
+ parser = argparse.ArgumentParser(description='Extract indicators out of binaries and returns MISP objects.')
68
+ group = parser.add_mutually_exclusive_group()
69
+ group.add_argument("-p", "--path", help="Path to process.")
70
+ group.add_argument("-c", "--check", action='store_true', help="Check the dependencies.")
71
+ args = parser.parse_args()
72
+ a = AbstractMISP()
73
+
74
+ if args.check:
75
+ print(check())
76
+ if args.path:
77
+ obj = make_objects(args.path)
78
+ print(obj)
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ from pymisp.tools import feed_meta_generator
5
+ import argparse
6
+ from pathlib import Path
7
+
8
+ if __name__ == '__main__':
9
+ parser = argparse.ArgumentParser(description='Build meta files for feed')
10
+ parser.add_argument("--feed", required=True, help="Path to directory containing the feed.")
11
+ args = parser.parse_args()
12
+
13
+ feed = Path(args.feed)
14
+
15
+ feed_meta_generator(feed)
examples/get.py ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ from pymisp import ExpandedPyMISP
5
+ from keys import misp_url, misp_key, misp_verifycert
6
+ import argparse
7
+ import os
8
+
9
+
10
+ proxies = {
11
+ 'http': 'http://127.0.0.1:8123',
12
+ 'https': 'http://127.0.0.1:8123',
13
+ }
14
+
15
+ proxies = None
16
+
17
+
18
+ if __name__ == '__main__':
19
+
20
+ parser = argparse.ArgumentParser(description='Get an event from a MISP instance.')
21
+ parser.add_argument("-e", "--event", required=True, help="Event ID to get.")
22
+ parser.add_argument("-o", "--output", help="Output file")
23
+
24
+ args = parser.parse_args()
25
+
26
+ if args.output is not None and os.path.exists(args.output):
27
+ print('Output file already exists, abort.')
28
+ exit(0)
29
+
30
+ misp = ExpandedPyMISP(misp_url, misp_key, misp_verifycert, proxies=proxies)
31
+
32
+ event = misp.get_event(args.event, pythonify=True)
33
+ if args.output:
34
+ with open(args.output, 'w') as f:
35
+ f.write(event.to_json())
36
+ else:
37
+ print(event.to_json())
examples/get_csv.py ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ import argparse
5
+
6
+ from pymisp import ExpandedPyMISP
7
+ from keys import misp_url, misp_key, misp_verifycert
8
+
9
+
10
+ if __name__ == '__main__':
11
+ parser = argparse.ArgumentParser(description='Get MISP stuff as CSV.')
12
+ parser.add_argument("--controller", default='attributes', help="Attribute to use for the search (events, objects, attributes)")
13
+ parser.add_argument("-e", "--event_id", help="Event ID to fetch. Without it, it will fetch the whole database.")
14
+ parser.add_argument("-a", "--attribute", nargs='+', help="Attribute column names")
15
+ parser.add_argument("-o", "--object_attribute", nargs='+', help="Object attribute column names")
16
+ parser.add_argument("-t", "--misp_types", nargs='+', help="MISP types to fetch (ip-src, hostname, ...)")
17
+ parser.add_argument("-c", "--context", action='store_true', help="Add event level context (tags...)")
18
+ parser.add_argument("-f", "--outfile", help="Output file to write the CSV.")
19
+
20
+ args = parser.parse_args()
21
+ pymisp = ExpandedPyMISP(misp_url, misp_key, misp_verifycert, debug=True)
22
+ attr = []
23
+ if args.attribute:
24
+ attr += args.attribute
25
+ if args.object_attribute:
26
+ attr += args.object_attribute
27
+ if not attr:
28
+ attr = None
29
+ print(args.context)
30
+ response = pymisp.search(return_format='csv', controller=args.controller, eventid=args.event_id, requested_attributes=attr,
31
+ type_attribute=args.misp_types, include_context=args.context)
32
+
33
+ if args.outfile:
34
+ with open(args.outfile, 'w') as f:
35
+ f.write(response)
36
+ else:
37
+ print(response)
@@ -0,0 +1,187 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ Python script to extract network activity from MISP database
6
+
7
+ Koen Van Impe 20141116
8
+ netflow 20150804
9
+ Feed it a list of event_id's (1 id per line) with the option "-f".
10
+ Use --no-comment to get a flat list of entries without event id and title information
11
+
12
+ Usage
13
+ ./get_network_activity.py --netflow --event 8
14
+ get netflow filter for event 8
15
+
16
+ ./get_network_activity.py -f get_network_activity.event_id --netflow
17
+ get netflow filter for events in id file
18
+
19
+ ./get_network_activity.py -f get_network_activity.event_id
20
+ get output with comments
21
+ """
22
+
23
+ from pymisp import PyMISP
24
+
25
+ from keys import misp_key
26
+ from keys import misp_url
27
+ from keys import misp_verifycert
28
+
29
+ source = None
30
+
31
+
32
+ def init():
33
+ """
34
+ Initialize PyMISP
35
+ Get configuration settings from config file
36
+ """
37
+ global source
38
+ source = PyMISP(misp_url, misp_key, misp_verifycert, 'json')
39
+
40
+
41
+ def get_event(event_id):
42
+ """
43
+ Get details of an event and add it to the result arrays
44
+ :event_id the id of the event
45
+ """
46
+ global network_ip_src, network_ip_dst, network_hostname, network_domain
47
+ global app_hostname, app_domain, app_ip_src, app_ip_dst, app_ids_only, app_printcomment, app_netflow
48
+
49
+ event_id = int(event_id)
50
+ if event_id > 0:
51
+ event_json = source.get_event(event_id)
52
+ event_core = event_json["Event"]
53
+ # event_threatlevel_id = event_core["threat_level_id"]
54
+
55
+ # attribute_count = event_core["attribute_count"]
56
+ attribute = event_core["Attribute"]
57
+
58
+ for attribute in event_core["Attribute"]:
59
+ if app_ids_only and not attribute["to_ids"]:
60
+ continue
61
+
62
+ value = attribute["value"]
63
+ title = event_core["info"]
64
+ if app_netflow:
65
+ app_printcomment = False
66
+ if attribute["type"] == "ip-dst" and app_ip_dst:
67
+ network_ip_dst.append([build_entry(value, event_id, title, "ip-dst")])
68
+ else:
69
+ if attribute["type"] == "ip-src" and app_ip_src:
70
+ network_ip_src.append([build_entry(value, event_id, title, "ip-src")])
71
+ elif attribute["type"] == "ip-dst" and app_ip_dst:
72
+ network_ip_dst.append([build_entry(value, event_id, title, "ip-dst")])
73
+ elif attribute["type"] == "domain" and app_domain:
74
+ network_domain.append([build_entry(value, event_id, title, "domain")])
75
+ elif attribute["type"] == "hostname" and app_hostname:
76
+ network_hostname.append([build_entry(value, event_id, title, "hostname")])
77
+ else:
78
+ continue
79
+ else:
80
+ print("Not a valid ID")
81
+ return
82
+
83
+
84
+ def build_entry(value, event_id, title, source):
85
+ """
86
+ Build the line containing the entry
87
+
88
+ :value the datavalue of the entry
89
+ :event_id id of the event
90
+ :title name of the event
91
+ :source from which set was the entry retrieved
92
+ """
93
+ global app_printcomment
94
+
95
+ if app_printcomment:
96
+ if app_printtitle:
97
+ return "%s # Event: %s / %s (from %s) " % (value, event_id, title, source)
98
+ else:
99
+ return "%s # Event: %s (from %s) " % (value, event_id, source)
100
+ else:
101
+ return value
102
+
103
+
104
+ def print_events():
105
+ """
106
+ Print the events from the result arrays
107
+ """
108
+ global network_ip_src, network_ip_dst, network_domain, network_hostname
109
+ global app_hostname, app_domain, app_ip_src, app_ip_dst, app_ids_only, app_printcomment, app_printtitle, app_netflow
110
+
111
+ if app_netflow:
112
+ firsthost = True
113
+ for ip in network_ip_dst:
114
+ if firsthost:
115
+ firsthost = False
116
+ else:
117
+ print(" or ")
118
+ print("host %s" % ip[0])
119
+ else:
120
+ if app_ip_src:
121
+ for ip in network_ip_src:
122
+ print(ip[0])
123
+ if app_ip_dst:
124
+ for ip in network_ip_dst:
125
+ print(ip[0])
126
+ if app_domain:
127
+ for ip in network_domain:
128
+ print(ip[0])
129
+ if app_hostname:
130
+ for ip in network_hostname:
131
+ print(ip[0])
132
+
133
+
134
+ if __name__ == '__main__':
135
+ import argparse
136
+
137
+ network_ip_src = []
138
+ network_ip_dst = []
139
+ network_domain = []
140
+ network_hostname = []
141
+
142
+ parser = argparse.ArgumentParser(
143
+ description='Download network activity information from MISP.')
144
+ parser.add_argument('-f', '--filename', type=str,
145
+ help='File containing a list of event id.')
146
+ parser.add_argument('--hostname', action='store_true', default=False,
147
+ help='Include hostnames.')
148
+ parser.add_argument('--no-ip-src', action='store_true', default=False,
149
+ help='Do not include ip-src.')
150
+ parser.add_argument('--no-ip-dst', action='store_true', default=False,
151
+ help='Do not include ip-dst.')
152
+ parser.add_argument('--domain', action='store_true', default=False,
153
+ help='Include domains.')
154
+ parser.add_argument('--no-comment', action='store_false', default=True,
155
+ help='Do not include comment in the output.')
156
+ parser.add_argument('--no-ids-only', action='store_true', default=False,
157
+ help='Include IDS and non-IDS attribures.')
158
+ parser.add_argument('--no-titles', action='store_true', default=False,
159
+ help='Do not include titles')
160
+ parser.add_argument('--netflow', action='store_true', default=False,
161
+ help='Netflow (nfdump) output')
162
+ parser.add_argument('--event', type=int, default=0,
163
+ help='EventID to parse (not using filename)')
164
+ args = parser.parse_args()
165
+
166
+ init()
167
+ app_printcomment = args.no_comment
168
+ app_hostname = args.hostname
169
+ app_domain = args.domain
170
+ app_ip_src = not(args.no_ip_src)
171
+ app_ip_dst = not(args.no_ip_dst)
172
+ app_ids_only = args.no_ids_only
173
+ app_printtitle = not(args.no_titles)
174
+ app_netflow = args.netflow
175
+ app_event = args.event
176
+
177
+ if app_event > 0:
178
+ get_event(app_event)
179
+ print_events()
180
+ elif args.filename is not None:
181
+ # print "app_printcomment %s app_hostname %s app_domain %s app_ip_src %s app_ip_dst %s app_ids_only %s app_printtitle %s" % (app_printcomment,app_hostname, app_domain, app_ip_src, app_ip_dst, app_ids_only, app_printtitle)
182
+ with open(args.filename, 'r') as line:
183
+ for event_id in line:
184
+ get_event(event_id.strip())
185
+ print_events()
186
+ else:
187
+ print("No filename given, stopping.")
examples/last.py ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ from pymisp import ExpandedPyMISP
5
+ from keys import misp_url, misp_key, misp_verifycert
6
+ try:
7
+ from keys import misp_client_cert
8
+ except ImportError:
9
+ misp_client_cert = ''
10
+ import argparse
11
+ import os
12
+
13
+
14
+ # Usage for pipe masters: ./last.py -l 5h | jq .
15
+ # Usage in case of large data set and pivoting page by page: python3 last.py -l 48h -m 10 -p 2 | jq .[].Event.info
16
+
17
+ if __name__ == '__main__':
18
+ parser = argparse.ArgumentParser(description='Download latest events from a MISP instance.')
19
+ parser.add_argument("-l", "--last", required=True, help="can be defined in days, hours, minutes (for example 5d or 12h or 30m).")
20
+ parser.add_argument("-m", "--limit", required=False, default="10", help="Add the limit of records to get (by default, the limit is set to 10)")
21
+ parser.add_argument("-p", "--page", required=False, default="1", help="Add the page to request to paginate over large dataset (by default page is set to 1)")
22
+ parser.add_argument("-o", "--output", help="Output file")
23
+
24
+ args = parser.parse_args()
25
+
26
+ if args.output is not None and os.path.exists(args.output):
27
+ print('Output file already exists, aborted.')
28
+ exit(0)
29
+
30
+ if misp_client_cert == '':
31
+ misp_client_cert = None
32
+ else:
33
+ misp_client_cert = (misp_client_cert)
34
+
35
+ misp = ExpandedPyMISP(misp_url, misp_key, misp_verifycert, cert=misp_client_cert)
36
+ result = misp.search(publish_timestamp=args.last, limit=args.limit, page=args.page, pythonify=True)
37
+
38
+ if not result:
39
+ print('No results for that time period')
40
+ exit(0)
41
+
42
+ if args.output:
43
+ with open(args.output, 'w') as f:
44
+ for r in result:
45
+ f.write(r.to_json() + '\n')
46
+ else:
47
+ for r in result:
48
+ print(r.to_json())