From 0671f93724e75d584a1ac9ca94f6e272663e5cd3 Mon Sep 17 00:00:00 2001 From: chrisr3d Date: Wed, 18 Mar 2020 18:05:57 +0100 Subject: [PATCH 01/30] new: Expansion module to query MALWAREbazaar API with some hash attribute --- misp_modules/modules/expansion/__init__.py | 2 +- .../modules/expansion/malwarebazaar.py | 53 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 misp_modules/modules/expansion/malwarebazaar.py diff --git a/misp_modules/modules/expansion/__init__.py b/misp_modules/modules/expansion/__init__.py index 2a99050..a8e35db 100644 --- a/misp_modules/modules/expansion/__init__.py +++ b/misp_modules/modules/expansion/__init__.py @@ -15,5 +15,5 @@ __all__ = ['cuckoo_submit', 'vmray_submit', 'bgpranking', 'circl_passivedns', 'c 'qrcode', 'ocr_enrich', 'pdf_enrich', 'docx_enrich', 'xlsx_enrich', 'pptx_enrich', 'ods_enrich', 'odt_enrich', 'joesandbox_submit', 'joesandbox_query', 'urlhaus', 'virustotal_public', 'apiosintds', 'urlscan', 'securitytrails', 'apivoid', - 'assemblyline_submit', 'assemblyline_query', 'ransomcoindb', + 'assemblyline_submit', 'assemblyline_query', 'ransomcoindb', 'malwarebazaar', 'lastline_query', 'lastline_submit', 'sophoslabs_intelix', 'cytomic_orion'] diff --git a/misp_modules/modules/expansion/malwarebazaar.py b/misp_modules/modules/expansion/malwarebazaar.py new file mode 100644 index 0000000..4930fd6 --- /dev/null +++ b/misp_modules/modules/expansion/malwarebazaar.py @@ -0,0 +1,53 @@ +import json +import requests +from pymisp import MISPEvent, MISPObject + +mispattributes = {'input': ['md5', 'sha1', 'sha256'], + 'format': 'misp_standard'} +moduleinfo = {'version': '0.1', 'author': 'Christian Studer', + 'description': 'Query Malware Bazaar to get additional information about the input hash.', + 'module-type': ['expansion', 'hover']} +moduleconfig = [] + + + +def parse_response(response): + mapping = {'file_name': {'type': 'filename', 'object_relation': 'filename'}, + 'file_size': {'type': 'size-in-bytes', 'object_relation': 'size-in-bytes'}, + 'file_type_mime': {'type': 'mime-type', 'object_relation': 'mimetype'}, + 'md5_hash': {'type': 'md5', 'object_relation': 'md5'}, + 'sha1_hash': {'type': 'sha1', 'object_relation': 'sha1'}, + 'sha256_hash': {'type': 'sha256', 'object_relation': 'sha256'}, + 'ssdeep': {'type': 'ssdeep', 'object_relation': 'ssdeep'}} + misp_event = MISPEvent() + for data in response: + misp_object = MISPObject('file') + for feature, attribute in mapping.items(): + if feature in data: + misp_attribute = {'value': data[feature]} + misp_attribute.update(attribute) + misp_object.add_attribute(**misp_attribute) + misp_event.add_object(**misp_object) + return {'results': {'Object': [json.loads(misp_object.to_json()) for misp_object in misp_event.objects]}} + + +def handler(q=False): + if q is False: + return False + request = json.loads(q) + attribute = request['attribute'] + url = 'https://mb-api.abuse.ch/api/v1/' + response = requests.post(url, data={'query': 'get_info', 'hash': attribute['value']}).json() + query_status = response['query_status'] + if query_status == 'ok': + return parse_response(response['data']) + return {'error': 'Hash not found on MALWAREbazzar' if query_status == 'hash_not_found' else f'Problem encountered during the query: {query_status}'} + + +def introspection(): + return mispattributes + + +def version(): + moduleinfo['config'] = moduleconfig + return moduleinfo From 8805bd86492aac6531fe64610e7d7706c2b632c1 Mon Sep 17 00:00:00 2001 From: chrisr3d Date: Wed, 18 Mar 2020 18:42:26 +0100 Subject: [PATCH 02/30] add: Added documentation for the latest new modules --- README.md | 1 + doc/README.md | 34 ++++++++++++++++++++++++++++++++ doc/expansion/malwarebazaar.json | 8 ++++++++ 3 files changed, 43 insertions(+) create mode 100644 doc/expansion/malwarebazaar.json diff --git a/README.md b/README.md index fe37cd5..165f3c5 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ For more information: [Extending MISP with Python modules](https://www.misp-proj * [Lastline query](misp_modules/modules/expansion/lastline_query.py) - Query Lastline with the link to an analysis and parse the report. * [macaddress.io](misp_modules/modules/expansion/macaddress_io.py) - a hover module to retrieve vendor details and other information regarding a given MAC address or an OUI from [MAC address Vendor Lookup](https://macaddress.io). See [integration tutorial here](https://macaddress.io/integrations/MISP-module). * [macvendors](misp_modules/modules/expansion/macvendors.py) - a hover module to retrieve mac vendor information. +* [MALWAREbazaar](misp_modules/modules/expansion/malwarebazaar.py) - an expansion module to query MALWAREbazaar with some payload. * [ocr-enrich](misp_modules/modules/expansion/ocr_enrich.py) - an enrichment module to get OCRized data from images into MISP. * [ods-enrich](misp_modules/modules/expansion/ods_enrich.py) - an enrichment module to get text out of OpenOffice spreadsheet document into MISP (using free-text parser). * [odt-enrich](misp_modules/modules/expansion/odt_enrich.py) - an enrichment module to get text out of OpenOffice document into MISP (using free-text parser). diff --git a/doc/README.md b/doc/README.md index 7e6bee3..9f221bd 100644 --- a/doc/README.md +++ b/doc/README.md @@ -295,6 +295,24 @@ An expansion hover module to expand information about CVE id. ----- +#### [cytomic_orion.py](https://github.com/MISP/misp-modules/tree/master/misp_modules/modules/expansion/cytomic_orion.py.py) + + + +An expansion module to enrich attributes in MISP by quering the Cytomic Orion API +- **features**: +>This module takes an MD5 hash and searches for occurrences of this hash in the Cytomic Orion database. Returns observed files and machines. +- **input**: +>MD5, hash of the sample / malware to search for. +- **output**: +>MISP objects with sightings of the hash in Cytomic Orion. Includes files and machines. +- **references**: +>https://www.vanimpe.eu/2020/03/10/integrating-misp-and-cytomic-orion/, https://www.cytomicmodel.com/solutions/ +- **requirements**: +>Access (license) to Cytomic Orion + +----- + #### [dbl_spamhaus](https://github.com/MISP/misp-modules/tree/master/misp_modules/modules/expansion/dbl_spamhaus.py) @@ -681,6 +699,22 @@ Module to access Macvendors API. ----- +#### [malwarebazaar](https://github.com/MISP/misp-modules/tree/master/misp_modules/modules/expansion/malwarebazaar.py) + +Query the MALWAREbazaar API to get additional information about the input hash attribute. +- **features**: +>The module takes a hash attribute as input and queries MALWAREbazaar's API to fetch additional data about it. The result, if the payload is known on the databases, is at least one file object describing the file the input hash is related to. +> +>The module is using the new format of modules able to return object since the result is one or multiple MISP object(s). +- **input**: +>A hash attribute (md5, sha1 or sha256). +- **output**: +>File object(s) related to the input attribute found on MALWAREbazaar databases. +- **references**: +>https://bazaar.abuse.ch/ + +----- + #### [ocr-enrich](https://github.com/MISP/misp-modules/tree/master/misp_modules/modules/expansion/ocr-enrich.py) Module to process some optical character recognition on pictures. diff --git a/doc/expansion/malwarebazaar.json b/doc/expansion/malwarebazaar.json new file mode 100644 index 0000000..2db6ad5 --- /dev/null +++ b/doc/expansion/malwarebazaar.json @@ -0,0 +1,8 @@ +{ + "description": "Query the MALWAREbazaar API to get additional information about the input hash attribute.", + "requirements": [], + "input": "A hash attribute (md5, sha1 or sha256).", + "output": "File object(s) related to the input attribute found on MALWAREbazaar databases.", + "references": ["https://bazaar.abuse.ch/"], + "features": "The module takes a hash attribute as input and queries MALWAREbazaar's API to fetch additional data about it. The result, if the payload is known on the databases, is at least one file object describing the file the input hash is related to.\n\nThe module is using the new format of modules able to return object since the result is one or multiple MISP object(s)." +} From 48b381d704ac9c1a1efcaccd9d8758f715d771dd Mon Sep 17 00:00:00 2001 From: chrisr3d Date: Wed, 18 Mar 2020 18:58:11 +0100 Subject: [PATCH 03/30] fix: Making pep8 happy --- misp_modules/modules/expansion/malwarebazaar.py | 1 - 1 file changed, 1 deletion(-) diff --git a/misp_modules/modules/expansion/malwarebazaar.py b/misp_modules/modules/expansion/malwarebazaar.py index 4930fd6..4574b75 100644 --- a/misp_modules/modules/expansion/malwarebazaar.py +++ b/misp_modules/modules/expansion/malwarebazaar.py @@ -10,7 +10,6 @@ moduleinfo = {'version': '0.1', 'author': 'Christian Studer', moduleconfig = [] - def parse_response(response): mapping = {'file_name': {'type': 'filename', 'object_relation': 'filename'}, 'file_size': {'type': 'size-in-bytes', 'object_relation': 'size-in-bytes'}, From 6f74885056a04119a95df9f8eab0e132b8cfd859 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 May 2020 17:05:53 +0000 Subject: [PATCH 04/30] build(deps): bump httplib2 from 0.17.0 to 0.18.0 Bumps [httplib2](https://github.com/httplib2/httplib2) from 0.17.0 to 0.18.0. - [Release notes](https://github.com/httplib2/httplib2/releases) - [Changelog](https://github.com/httplib2/httplib2/blob/master/CHANGELOG) - [Commits](https://github.com/httplib2/httplib2/compare/v0.17.0...v0.18.0) Signed-off-by: dependabot[bot] --- Pipfile.lock | 323 +++++++++++++++++++++++---------------------------- 1 file changed, 146 insertions(+), 177 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index ac5749a..9a23d0d 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -112,10 +112,10 @@ }, "certifi": { "hashes": [ - "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", - "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" + "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304", + "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519" ], - "version": "==2019.11.28" + "version": "==2020.4.5.1" }, "cffi": { "hashes": [ @@ -159,10 +159,10 @@ }, "click": { "hashes": [ - "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc", - "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a" + "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a", + "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc" ], - "version": "==7.1.1" + "version": "==7.1.2" }, "click-plugins": { "hashes": [ @@ -180,29 +180,27 @@ }, "cryptography": { "hashes": [ - "sha256:02079a6addc7b5140ba0825f542c0869ff4df9a69c360e339ecead5baefa843c", - "sha256:1df22371fbf2004c6f64e927668734070a8953362cd8370ddd336774d6743595", - "sha256:369d2346db5934345787451504853ad9d342d7f721ae82d098083e1f49a582ad", - "sha256:3cda1f0ed8747339bbdf71b9f38ca74c7b592f24f65cdb3ab3765e4b02871651", - "sha256:44ff04138935882fef7c686878e1c8fd80a723161ad6a98da31e14b7553170c2", - "sha256:4b1030728872c59687badcca1e225a9103440e467c17d6d1730ab3d2d64bfeff", - "sha256:58363dbd966afb4f89b3b11dfb8ff200058fbc3b947507675c19ceb46104b48d", - "sha256:6ec280fb24d27e3d97aa731e16207d58bd8ae94ef6eab97249a2afe4ba643d42", - "sha256:7270a6c29199adc1297776937a05b59720e8a782531f1f122f2eb8467f9aab4d", - "sha256:73fd30c57fa2d0a1d7a49c561c40c2f79c7d6c374cc7750e9ac7c99176f6428e", - "sha256:7f09806ed4fbea8f51585231ba742b58cbcfbfe823ea197d8c89a5e433c7e912", - "sha256:90df0cc93e1f8d2fba8365fb59a858f51a11a394d64dbf3ef844f783844cc793", - "sha256:971221ed40f058f5662a604bd1ae6e4521d84e6cad0b7b170564cc34169c8f13", - "sha256:a518c153a2b5ed6b8cc03f7ae79d5ffad7315ad4569b2d5333a13c38d64bd8d7", - "sha256:b0de590a8b0979649ebeef8bb9f54394d3a41f66c5584fff4220901739b6b2f0", - "sha256:b43f53f29816ba1db8525f006fa6f49292e9b029554b3eb56a189a70f2a40879", - "sha256:d31402aad60ed889c7e57934a03477b572a03af7794fa8fb1780f21ea8f6551f", - "sha256:de96157ec73458a7f14e3d26f17f8128c959084931e8997b9e655a39c8fde9f9", - "sha256:df6b4dca2e11865e6cfbfb708e800efb18370f5a46fd601d3755bc7f85b3a8a2", - "sha256:ecadccc7ba52193963c0475ac9f6fa28ac01e01349a2ca48509667ef41ffd2cf", - "sha256:fb81c17e0ebe3358486cd8cc3ad78adbae58af12fc2bf2bc0bb84e8090fa5ce8" + "sha256:091d31c42f444c6f519485ed528d8b451d1a0c7bf30e8ca583a0cac44b8a0df6", + "sha256:18452582a3c85b96014b45686af264563e3e5d99d226589f057ace56196ec78b", + "sha256:1dfa985f62b137909496e7fc182dac687206d8d089dd03eaeb28ae16eec8e7d5", + "sha256:1e4014639d3d73fbc5ceff206049c5a9a849cefd106a49fa7aaaa25cc0ce35cf", + "sha256:22e91636a51170df0ae4dcbd250d318fd28c9f491c4e50b625a49964b24fe46e", + "sha256:3b3eba865ea2754738616f87292b7f29448aec342a7c720956f8083d252bf28b", + "sha256:651448cd2e3a6bc2bb76c3663785133c40d5e1a8c1a9c5429e4354201c6024ae", + "sha256:726086c17f94747cedbee6efa77e99ae170caebeb1116353c6cf0ab67ea6829b", + "sha256:844a76bc04472e5135b909da6aed84360f522ff5dfa47f93e3dd2a0b84a89fa0", + "sha256:88c881dd5a147e08d1bdcf2315c04972381d026cdb803325c03fe2b4a8ed858b", + "sha256:96c080ae7118c10fcbe6229ab43eb8b090fccd31a09ef55f83f690d1ef619a1d", + "sha256:a0c30272fb4ddda5f5ffc1089d7405b7a71b0b0f51993cb4e5dbb4590b2fc229", + "sha256:bb1f0281887d89617b4c68e8db9a2c42b9efebf2702a3c5bf70599421a8623e3", + "sha256:c447cf087cf2dbddc1add6987bbe2f767ed5317adb2d08af940db517dd704365", + "sha256:c4fd17d92e9d55b84707f4fd09992081ba872d1a0c610c109c18e062e06a2e55", + "sha256:d0d5aeaedd29be304848f1c5059074a740fa9f6f26b84c5b63e8b29e73dfc270", + "sha256:daf54a4b07d67ad437ff239c8a4080cfd1cc7213df57d33c97de7b4738048d5e", + "sha256:e993468c859d084d5579e2ebee101de8f5a27ce8e2159959b6673b418fd8c785", + "sha256:f118a95c7480f5be0df8afeb9a11bd199aa20afab7a96bcf20409b411a3a85f0" ], - "version": "==2.8" + "version": "==2.9.2" }, "decorator": { "hashes": [ @@ -213,10 +211,10 @@ }, "deprecated": { "hashes": [ - "sha256:408038ab5fdeca67554e8f6742d1521cd3cd0ee0ff9d47f29318a4f4da31c308", - "sha256:8b6a5aa50e482d8244a62e5582b96c372e87e3a28e8b49c316e46b95c76a611d" + "sha256:525ba66fb5f90b07169fdd48b6373c18f1ee12728ca277ca44567a367d9d7f74", + "sha256:a766c1dccb30c5f6eb2b203f87edd1d8588847709c78589e1521d769addc8218" ], - "version": "==1.2.7" + "version": "==1.2.10" }, "dnspython": { "hashes": [ @@ -277,10 +275,11 @@ }, "httplib2": { "hashes": [ - "sha256:79751cc040229ec896aa01dced54de0cd0bf042f928e84d5761294422dde4454", - "sha256:de96d0a49f46d0ee7e0aae80141d37b8fcd6a68fb05d02e0b82c128592dd8261" + "sha256:4f6988e6399a2546b525a037d56da34aed4d149bbdc0e78523018d5606c26e74", + "sha256:b0e1f3ed76c97380fe2485bc47f25235453b40ef33ca5921bb2897e257a49c4c" ], - "version": "==0.17.0" + "index": "pypi", + "version": "==0.18.0" }, "idna": { "hashes": [ @@ -297,14 +296,6 @@ "markers": "python_version < '3.7'", "version": "==1.1.0" }, - "importlib-metadata": { - "hashes": [ - "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f", - "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e" - ], - "markers": "python_version < '3.8'", - "version": "==1.6.0" - }, "isodate": { "hashes": [ "sha256:2e364a3d5759479cdb2d37cce6b9376ea504db2ff90252a2e5b7cc89cc9ff2d8", @@ -388,9 +379,9 @@ }, "maxminddb": { "hashes": [ - "sha256:d0ce131d901eb11669996b49a59f410efd3da2c6dbe2c0094fe2fef8d85b6336" + "sha256:f4d28823d9ca23323d113dc7af8db2087aa4f657fafc64ff8f7a8afda871425b" ], - "version": "==1.5.2" + "version": "==1.5.4" }, "misp-modules": { "editable": true, @@ -398,25 +389,25 @@ }, "multidict": { "hashes": [ - "sha256:317f96bc0950d249e96d8d29ab556d01dd38888fbe68324f46fd834b430169f1", - "sha256:42f56542166040b4474c0c608ed051732033cd821126493cf25b6c276df7dd35", - "sha256:4b7df040fb5fe826d689204f9b544af469593fb3ff3a069a6ad3409f742f5928", - "sha256:544fae9261232a97102e27a926019100a9db75bec7b37feedd74b3aa82f29969", - "sha256:620b37c3fea181dab09267cd5a84b0f23fa043beb8bc50d8474dd9694de1fa6e", - "sha256:6e6fef114741c4d7ca46da8449038ec8b1e880bbe68674c01ceeb1ac8a648e78", - "sha256:7774e9f6c9af3f12f296131453f7b81dabb7ebdb948483362f5afcaac8a826f1", - "sha256:85cb26c38c96f76b7ff38b86c9d560dea10cf3459bb5f4caf72fc1bb932c7136", - "sha256:a326f4240123a2ac66bb163eeba99578e9d63a8654a59f4688a79198f9aa10f8", - "sha256:ae402f43604e3b2bc41e8ea8b8526c7fa7139ed76b0d64fc48e28125925275b2", - "sha256:aee283c49601fa4c13adc64c09c978838a7e812f85377ae130a24d7198c0331e", - "sha256:b51249fdd2923739cd3efc95a3d6c363b67bbf779208e9f37fd5e68540d1a4d4", - "sha256:bb519becc46275c594410c6c28a8a0adc66fe24fef154a9addea54c1adb006f5", - "sha256:c2c37185fb0af79d5c117b8d2764f4321eeb12ba8c141a95d0aa8c2c1d0a11dd", - "sha256:dc561313279f9d05a3d0ffa89cd15ae477528ea37aa9795c4654588a3287a9ab", - "sha256:e439c9a10a95cb32abd708bb8be83b2134fa93790a4fb0535ca36db3dda94d20", - "sha256:fc3b4adc2ee8474cb3cd2a155305d5f8eda0a9c91320f83e55748e1fcb68f8e3" + "sha256:1ece5a3369835c20ed57adadc663400b5525904e53bae59ec854a5d36b39b21a", + "sha256:275ca32383bc5d1894b6975bb4ca6a7ff16ab76fa622967625baeebcf8079000", + "sha256:3750f2205b800aac4bb03b5ae48025a64e474d2c6cc79547988ba1d4122a09e2", + "sha256:4538273208e7294b2659b1602490f4ed3ab1c8cf9dbdd817e0e9db8e64be2507", + "sha256:5141c13374e6b25fe6bf092052ab55c0c03d21bd66c94a0e3ae371d3e4d865a5", + "sha256:51a4d210404ac61d32dada00a50ea7ba412e6ea945bbe992e4d7a595276d2ec7", + "sha256:5cf311a0f5ef80fe73e4f4c0f0998ec08f954a6ec72b746f3c179e37de1d210d", + "sha256:6513728873f4326999429a8b00fc7ceddb2509b01d5fd3f3be7881a257b8d463", + "sha256:7388d2ef3c55a8ba80da62ecfafa06a1c097c18032a501ffd4cabbc52d7f2b19", + "sha256:9456e90649005ad40558f4cf51dbb842e32807df75146c6d940b6f5abb4a78f3", + "sha256:c026fe9a05130e44157b98fea3ab12969e5b60691a276150db9eda71710cd10b", + "sha256:d14842362ed4cf63751648e7672f7174c9818459d169231d03c56e84daf90b7c", + "sha256:e0d072ae0f2a179c375f67e3da300b47e1a83293c554450b29c900e50afaae87", + "sha256:f07acae137b71af3bb548bd8da720956a3bc9f9a0b87733e0899226a2317aeb7", + "sha256:fbb77a75e529021e7c4a8d4e823d88ef4d23674a202be4f5addffc72cbb91430", + "sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255", + "sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d" ], - "version": "==4.7.5" + "version": "==4.7.6" }, "np": { "hashes": [ @@ -427,29 +418,29 @@ }, "numpy": { "hashes": [ - "sha256:1598a6de323508cfeed6b7cd6c4efb43324f4692e20d1f76e1feec7f59013448", - "sha256:1b0ece94018ae21163d1f651b527156e1f03943b986188dd81bc7e066eae9d1c", - "sha256:2e40be731ad618cb4974d5ba60d373cdf4f1b8dcbf1dcf4d9dff5e212baf69c5", - "sha256:4ba59db1fcc27ea31368af524dcf874d9277f21fd2e1f7f1e2e0c75ee61419ed", - "sha256:59ca9c6592da581a03d42cc4e270732552243dc45e87248aa8d636d53812f6a5", - "sha256:5e0feb76849ca3e83dd396254e47c7dba65b3fa9ed3df67c2556293ae3e16de3", - "sha256:6d205249a0293e62bbb3898c4c2e1ff8a22f98375a34775a259a0523111a8f6c", - "sha256:6fcc5a3990e269f86d388f165a089259893851437b904f422d301cdce4ff25c8", - "sha256:82847f2765835c8e5308f136bc34018d09b49037ec23ecc42b246424c767056b", - "sha256:87902e5c03355335fc5992a74ba0247a70d937f326d852fc613b7f53516c0963", - "sha256:9ab21d1cb156a620d3999dd92f7d1c86824c622873841d6b080ca5495fa10fef", - "sha256:a1baa1dc8ecd88fb2d2a651671a84b9938461e8a8eed13e2f0a812a94084d1fa", - "sha256:a244f7af80dacf21054386539699ce29bcc64796ed9850c99a34b41305630286", - "sha256:a35af656a7ba1d3decdd4fae5322b87277de8ac98b7d9da657d9e212ece76a61", - "sha256:b1fe1a6f3a6f355f6c29789b5927f8bd4f134a4bd9a781099a7c4f66af8850f5", - "sha256:b5ad0adb51b2dee7d0ee75a69e9871e2ddfb061c73ea8bc439376298141f77f5", - "sha256:ba3c7a2814ec8a176bb71f91478293d633c08582119e713a0c5351c0f77698da", - "sha256:cd77d58fb2acf57c1d1ee2835567cd70e6f1835e32090538f17f8a3a99e5e34b", - "sha256:cdb3a70285e8220875e4d2bc394e49b4988bdb1298ffa4e0bd81b2f613be397c", - "sha256:deb529c40c3f1e38d53d5ae6cd077c21f1d49e13afc7936f7f868455e16b64a0", - "sha256:e7894793e6e8540dbeac77c87b489e331947813511108ae097f1715c018b8f3d" + "sha256:00d7b54c025601e28f468953d065b9b121ddca7fff30bed7be082d3656dd798d", + "sha256:02ec9582808c4e48be4e93cd629c855e644882faf704bc2bd6bbf58c08a2a897", + "sha256:0e6f72f7bb08f2f350ed4408bb7acdc0daba637e73bce9f5ea2b207039f3af88", + "sha256:1be2e96314a66f5f1ce7764274327fd4fb9da58584eaff00b5a5221edefee7d6", + "sha256:2466fbcf23711ebc5daa61d28ced319a6159b260a18839993d871096d66b93f7", + "sha256:2b573fcf6f9863ce746e4ad00ac18a948978bb3781cffa4305134d31801f3e26", + "sha256:3f0dae97e1126f529ebb66f3c63514a0f72a177b90d56e4bce8a0b5def34627a", + "sha256:50fb72bcbc2cf11e066579cb53c4ca8ac0227abb512b6cbc1faa02d1595a2a5d", + "sha256:57aea170fb23b1fd54fa537359d90d383d9bf5937ee54ae8045a723caa5e0961", + "sha256:709c2999b6bd36cdaf85cf888d8512da7433529f14a3689d6e37ab5242e7add5", + "sha256:7d59f21e43bbfd9a10953a7e26b35b6849d888fc5a331fa84a2d9c37bd9fe2a2", + "sha256:904b513ab8fbcbdb062bed1ce2f794ab20208a1b01ce9bd90776c6c7e7257032", + "sha256:96dd36f5cdde152fd6977d1bbc0f0561bccffecfde63cd397c8e6033eb66baba", + "sha256:9933b81fecbe935e6a7dc89cbd2b99fea1bf362f2790daf9422a7bb1dc3c3085", + "sha256:bbcc85aaf4cd84ba057decaead058f43191cc0e30d6bc5d44fe336dc3d3f4509", + "sha256:dccd380d8e025c867ddcb2f84b439722cf1f23f3a319381eac45fd077dee7170", + "sha256:e22cd0f72fc931d6abc69dc7764484ee20c6a60b0d0fee9ce0426029b1c1bdae", + "sha256:ed722aefb0ebffd10b32e67f48e8ac4c5c4cf5d3a785024fdf0e9eb17529cd9d", + "sha256:efb7ac5572c9a57159cf92c508aad9f856f1cb8e8302d7fdb99061dbe52d712c", + "sha256:efdba339fffb0e80fcc19524e4fdbda2e2b5772ea46720c44eaac28096d60720", + "sha256:f22273dd6a403ed870207b853a856ff6327d5cbce7a835dfa0645b3fc00273ec" ], - "version": "==1.18.2" + "version": "==1.18.4" }, "oauth2": { "hashes": [ @@ -573,10 +564,10 @@ }, "progressbar2": { "hashes": [ - "sha256:2c21c14482016162852c8265da03886c2b4dea6f84e5a817ad9b39f6bd82a772", - "sha256:7849b84c01a39e4eddd2b369a129fed5e24dfb78d484ae63f9e08e58277a2928" + "sha256:57594cc7ff7ff93138d6c09f650f9d31290b5d3bd1cf12339ced96a50c148749", + "sha256:ecf687696dd449067f69ef6730c4d4a0189db1f8d1aad9e376358354631d5b2c" ], - "version": "==3.50.1" + "version": "==3.51.3" }, "psutil": { "hashes": [ @@ -736,10 +727,10 @@ }, "pyparsing": { "hashes": [ - "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f", - "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec" + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" ], - "version": "==2.4.6" + "version": "==2.4.7" }, "pypdns": { "hashes": [ @@ -785,10 +776,10 @@ }, "python-magic": { "hashes": [ - "sha256:f2674dcfad52ae6c49d4803fa027809540b130db1dec928cfbb9240316831375", - "sha256:f3765c0f582d2dfc72c15f3b5a82aecfae9498bd29ca840d72f37d7bd38bfcd5" + "sha256:356efa93c8899047d1eb7d3eb91e871ba2f5b1376edbaf4cc305e3c872207355", + "sha256:b757db2a5289ea3f1ced9e60f072965243ea43a2221430048fd8cacab17be0ce" ], - "version": "==0.4.15" + "version": "==0.4.18" }, "python-pptx": { "hashes": [ @@ -846,17 +837,17 @@ }, "rdflib": { "hashes": [ - "sha256:58d5994610105a457cff7fdfe3d683d87786c5028a45ae032982498a7e913d6f", - "sha256:da1df14552555c5c7715d8ce71c08f404c988c58a1ecd38552d0da4fc261280d" + "sha256:78149dd49d385efec3b3adfbd61c87afaf1281c30d3fcaf1b323b34f603fb155", + "sha256:88208ea971a87886d60ae2b1a4b2cdc263527af0454c422118d43fe64b357877" ], - "version": "==4.2.2" + "version": "==5.0.0" }, "redis": { "hashes": [ - "sha256:0dcfb335921b88a850d461dc255ff4708294943322bd55de6cfd68972490ca1f", - "sha256:b205cffd05ebfd0a468db74f0eedbff8df1a7bfc47521516ade4692991bb0833" + "sha256:2ef11f489003f151777c064c5dbc6653dfb9f3eade159bcadc524619fddc2242", + "sha256:6d65e84bc58091140081ee9d9c187aab0480097750fac44239307a3bdf0b1251" ], - "version": "==3.4.1" + "version": "==3.5.2" }, "reportlab": { "hashes": [ @@ -952,10 +943,10 @@ }, "soupsieve": { "hashes": [ - "sha256:e914534802d7ffd233242b785229d5ba0766a7f487385e3f714446a07bf540ae", - "sha256:fcd71e08c0aee99aca1b73f45478549ee7e7fc006d51b37bec9e9def7dc22b69" + "sha256:1634eea42ab371d3d346309b93df7870a88610f0725d47528be902a0d95ecc55", + "sha256:a59dc181727e95d25f781f0eb4fd1825ff45590ec8ff49eadfd7f1a537cc0232" ], - "version": "==2.0" + "version": "==2.0.1" }, "sparqlwrapper": { "hashes": [ @@ -997,10 +988,10 @@ }, "url-normalize": { "hashes": [ - "sha256:3468d64cb22a9092a2c086e46c781f741dc9a1689b24e9b48ab5e8244ffa6c02", - "sha256:51e0f14050c79e732d175c33d12167f5e642cc23e0cb23275236af843faf884f" + "sha256:1709cb4739e496f9f807a894e361915792f273538e250b1ab7da790544a665c3", + "sha256:1bd7085349dcdf06e52194d0f75ff99fff2eeed0da85a50e4cc2346452c1b8bc" ], - "version": "==1.4.1" + "version": "==1.4.2" }, "urlarchiver": { "hashes": [ @@ -1011,10 +1002,10 @@ }, "urllib3": { "hashes": [ - "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", - "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc" + "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527", + "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115" ], - "version": "==1.25.8" + "version": "==1.25.9" }, "uwhois": { "editable": true, @@ -1119,13 +1110,6 @@ "sha256:e15199cdb423316e15f108f51249e44eb156ae5dba232cb73be555324a1d49c2" ], "version": "==1.4.2" - }, - "zipp": { - "hashes": [ - "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b", - "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96" - ], - "version": "==3.1.0" } }, "develop": { @@ -1138,10 +1122,10 @@ }, "certifi": { "hashes": [ - "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", - "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" + "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304", + "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519" ], - "version": "==2019.11.28" + "version": "==2020.4.5.1" }, "chardet": { "hashes": [ @@ -1160,39 +1144,39 @@ }, "coverage": { "hashes": [ - "sha256:03f630aba2b9b0d69871c2e8d23a69b7fe94a1e2f5f10df5049c0df99db639a0", - "sha256:046a1a742e66d065d16fb564a26c2a15867f17695e7f3d358d7b1ad8a61bca30", - "sha256:0a907199566269e1cfa304325cc3b45c72ae341fbb3253ddde19fa820ded7a8b", - "sha256:165a48268bfb5a77e2d9dbb80de7ea917332a79c7adb747bd005b3a07ff8caf0", - "sha256:1b60a95fc995649464e0cd48cecc8288bac5f4198f21d04b8229dc4097d76823", - "sha256:1f66cf263ec77af5b8fe14ef14c5e46e2eb4a795ac495ad7c03adc72ae43fafe", - "sha256:2e08c32cbede4a29e2a701822291ae2bc9b5220a971bba9d1e7615312efd3037", - "sha256:3844c3dab800ca8536f75ae89f3cf566848a3eb2af4d9f7b1103b4f4f7a5dad6", - "sha256:408ce64078398b2ee2ec08199ea3fcf382828d2f8a19c5a5ba2946fe5ddc6c31", - "sha256:443be7602c790960b9514567917af538cac7807a7c0c0727c4d2bbd4014920fd", - "sha256:4482f69e0701139d0f2c44f3c395d1d1d37abd81bfafbf9b6efbe2542679d892", - "sha256:4a8a259bf990044351baf69d3b23e575699dd60b18460c71e81dc565f5819ac1", - "sha256:513e6526e0082c59a984448f4104c9bf346c2da9961779ede1fc458e8e8a1f78", - "sha256:5f587dfd83cb669933186661a351ad6fc7166273bc3e3a1531ec5c783d997aac", - "sha256:62061e87071497951155cbccee487980524d7abea647a1b2a6eb6b9647df9006", - "sha256:641e329e7f2c01531c45c687efcec8aeca2a78a4ff26d49184dce3d53fc35014", - "sha256:65a7e00c00472cd0f59ae09d2fb8a8aaae7f4a0cf54b2b74f3138d9f9ceb9cb2", - "sha256:6ad6ca45e9e92c05295f638e78cd42bfaaf8ee07878c9ed73e93190b26c125f7", - "sha256:73aa6e86034dad9f00f4bbf5a666a889d17d79db73bc5af04abd6c20a014d9c8", - "sha256:7c9762f80a25d8d0e4ab3cb1af5d9dffbddb3ee5d21c43e3474c84bf5ff941f7", - "sha256:85596aa5d9aac1bf39fe39d9fa1051b0f00823982a1de5766e35d495b4a36ca9", - "sha256:86a0ea78fd851b313b2e712266f663e13b6bc78c2fb260b079e8b67d970474b1", - "sha256:8a620767b8209f3446197c0e29ba895d75a1e272a36af0786ec70fe7834e4307", - "sha256:922fb9ef2c67c3ab20e22948dcfd783397e4c043a5c5fa5ff5e9df5529074b0a", - "sha256:9fad78c13e71546a76c2f8789623eec8e499f8d2d799f4b4547162ce0a4df435", - "sha256:a37c6233b28e5bc340054cf6170e7090a4e85069513320275a4dc929144dccf0", - "sha256:c3fc325ce4cbf902d05a80daa47b645d07e796a80682c1c5800d6ac5045193e5", - "sha256:cda33311cb9fb9323958a69499a667bd728a39a7aa4718d7622597a44c4f1441", - "sha256:db1d4e38c9b15be1521722e946ee24f6db95b189d1447fa9ff18dd16ba89f732", - "sha256:eda55e6e9ea258f5e4add23bcf33dc53b2c319e70806e180aecbff8d90ea24de", - "sha256:f372cdbb240e09ee855735b9d85e7f50730dcfb6296b74b95a3e5dea0615c4c1" + "sha256:00f1d23f4336efc3b311ed0d807feb45098fc86dee1ca13b3d6768cdab187c8a", + "sha256:01333e1bd22c59713ba8a79f088b3955946e293114479bbfc2e37d522be03355", + "sha256:0cb4be7e784dcdc050fc58ef05b71aa8e89b7e6636b99967fadbdba694cf2b65", + "sha256:0e61d9803d5851849c24f78227939c701ced6704f337cad0a91e0972c51c1ee7", + "sha256:1601e480b9b99697a570cea7ef749e88123c04b92d84cedaa01e117436b4a0a9", + "sha256:2742c7515b9eb368718cd091bad1a1b44135cc72468c731302b3d641895b83d1", + "sha256:2d27a3f742c98e5c6b461ee6ef7287400a1956c11421eb574d843d9ec1f772f0", + "sha256:402e1744733df483b93abbf209283898e9f0d67470707e3c7516d84f48524f55", + "sha256:5c542d1e62eece33c306d66fe0a5c4f7f7b3c08fecc46ead86d7916684b36d6c", + "sha256:5f2294dbf7875b991c381e3d5af2bcc3494d836affa52b809c91697449d0eda6", + "sha256:6402bd2fdedabbdb63a316308142597534ea8e1895f4e7d8bf7476c5e8751fef", + "sha256:66460ab1599d3cf894bb6baee8c684788819b71a5dc1e8fa2ecc152e5d752019", + "sha256:782caea581a6e9ff75eccda79287daefd1d2631cc09d642b6ee2d6da21fc0a4e", + "sha256:79a3cfd6346ce6c13145731d39db47b7a7b859c0272f02cdb89a3bdcbae233a0", + "sha256:7a5bdad4edec57b5fb8dae7d3ee58622d626fd3a0be0dfceda162a7035885ecf", + "sha256:8fa0cbc7ecad630e5b0f4f35b0f6ad419246b02bc750de7ac66db92667996d24", + "sha256:a027ef0492ede1e03a8054e3c37b8def89a1e3c471482e9f046906ba4f2aafd2", + "sha256:a3f3654d5734a3ece152636aad89f58afc9213c6520062db3978239db122f03c", + "sha256:a82b92b04a23d3c8a581fc049228bafde988abacba397d57ce95fe95e0338ab4", + "sha256:acf3763ed01af8410fc36afea23707d4ea58ba7e86a8ee915dfb9ceff9ef69d0", + "sha256:adeb4c5b608574a3d647011af36f7586811a2c1197c861aedb548dd2453b41cd", + "sha256:b83835506dfc185a319031cf853fa4bb1b3974b1f913f5bb1a0f3d98bdcded04", + "sha256:bb28a7245de68bf29f6fb199545d072d1036a1917dca17a1e75bbb919e14ee8e", + "sha256:bf9cb9a9fd8891e7efd2d44deb24b86d647394b9705b744ff6f8261e6f29a730", + "sha256:c317eaf5ff46a34305b202e73404f55f7389ef834b8dbf4da09b9b9b37f76dd2", + "sha256:dbe8c6ae7534b5b024296464f387d57c13caa942f6d8e6e0346f27e509f0f768", + "sha256:de807ae933cfb7f0c7d9d981a053772452217df2bf38e7e6267c9cbf9545a796", + "sha256:dead2ddede4c7ba6cb3a721870f5141c97dc7d85a079edb4bd8d88c3ad5b20c7", + "sha256:dec5202bfe6f672d4511086e125db035a52b00f1648d6407cc8e526912c0353a", + "sha256:e1ea316102ea1e1770724db01998d1603ed921c54a86a2efcb03428d5417e489", + "sha256:f90bfc4ad18450c80b024036eaf91e4a246ae287701aaa88eaebebf150868052" ], - "version": "==5.0.4" + "version": "==5.1" }, "entrypoints": { "hashes": [ @@ -1216,14 +1200,6 @@ ], "version": "==2.9" }, - "importlib-metadata": { - "hashes": [ - "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f", - "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e" - ], - "markers": "python_version < '3.8'", - "version": "==1.6.0" - }, "mccabe": { "hashes": [ "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", @@ -1233,10 +1209,10 @@ }, "more-itertools": { "hashes": [ - "sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c", - "sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507" + "sha256:558bb897a2232f5e4f8e2399089e35aecb746e1f9191b6584a151647e89267be", + "sha256:7818f596b1e87be009031c7653d01acc46ed422e6656b394b0f765ce66ed4982" ], - "version": "==8.2.0" + "version": "==8.3.0" }, "nose": { "hashes": [ @@ -1249,10 +1225,10 @@ }, "packaging": { "hashes": [ - "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3", - "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752" + "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8", + "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181" ], - "version": "==20.3" + "version": "==20.4" }, "pluggy": { "hashes": [ @@ -1284,10 +1260,10 @@ }, "pyparsing": { "hashes": [ - "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f", - "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec" + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" ], - "version": "==2.4.6" + "version": "==2.4.7" }, "pytest": { "hashes": [ @@ -1317,10 +1293,10 @@ }, "urllib3": { "hashes": [ - "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", - "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc" + "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527", + "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115" ], - "version": "==1.25.8" + "version": "==1.25.9" }, "wcwidth": { "hashes": [ @@ -1328,13 +1304,6 @@ "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1" ], "version": "==0.1.9" - }, - "zipp": { - "hashes": [ - "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b", - "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96" - ], - "version": "==3.1.0" } } } From 31d15056f9f85298eb95a5b0dac7ba0ddd8c19e7 Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Wed, 3 Jun 2020 11:12:47 +0200 Subject: [PATCH 05/30] new: [passivedns, passivessl] Add support for ip-src|port and ip-dst|port --- misp_modules/modules/expansion/circl_passivedns.py | 10 ++++++---- misp_modules/modules/expansion/circl_passivessl.py | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/misp_modules/modules/expansion/circl_passivedns.py b/misp_modules/modules/expansion/circl_passivedns.py index 75ff6c6..2455be0 100755 --- a/misp_modules/modules/expansion/circl_passivedns.py +++ b/misp_modules/modules/expansion/circl_passivedns.py @@ -2,7 +2,7 @@ import json import pypdns from pymisp import MISPAttribute, MISPEvent, MISPObject -mispattributes = {'input': ['hostname', 'domain', 'ip-src', 'ip-dst'], 'format': 'misp_standard'} +mispattributes = {'input': ['hostname', 'domain', 'ip-src', 'ip-dst', 'ip-src|port', 'ip-dst|port'], 'format': 'misp_standard'} moduleinfo = {'version': '0.2', 'author': 'Alexandre Dulaunoy', 'description': 'Module to access CIRCL Passive DNS', 'module-type': ['expansion', 'hover']} @@ -24,9 +24,11 @@ class PassiveDNSParser(): results = {key: event[key] for key in ('Attribute', 'Object')} return {'results': results} - def parse(self, value): + def parse(self): + value = self.attribute.value.split('|')[0] if '|' in self.attribute.type else self.attribute.value + try: - results = self.pdns.query(self.attribute.value) + results = self.pdns.query(value) except Exception: self.result = {'error': 'There is an authentication error, please make sure you supply correct credentials.'} return @@ -57,7 +59,7 @@ def handler(q=False): if not any(input_type == attribute['type'] for input_type in mispattributes['input']): return {'error': 'Unsupported attributes type'} pdns_parser = PassiveDNSParser(attribute, authentication) - pdns_parser.parse(attribute['value']) + pdns_parser.parse() return pdns_parser.get_results() diff --git a/misp_modules/modules/expansion/circl_passivessl.py b/misp_modules/modules/expansion/circl_passivessl.py index 0c11106..e43defc 100755 --- a/misp_modules/modules/expansion/circl_passivessl.py +++ b/misp_modules/modules/expansion/circl_passivessl.py @@ -2,7 +2,7 @@ import json import pypssl from pymisp import MISPAttribute, MISPEvent, MISPObject -mispattributes = {'input': ['ip-src', 'ip-dst'], 'format': 'misp_standard'} +mispattributes = {'input': ['ip-src', 'ip-dst', 'ip-src|port', 'ip-dst|port'], 'format': 'misp_standard'} moduleinfo = {'version': '0.2', 'author': 'RaphaĆ«l Vinot', 'description': 'Module to access CIRCL Passive SSL', 'module-type': ['expansion', 'hover']} @@ -31,9 +31,11 @@ class PassiveSSLParser(): results = {key: event[key] for key in ('Attribute', 'Object')} return {'results': results} - def parse(self, value): + def parse(self): + value = self.attribute.value.split('|')[0] if '|' in self.attribute.type else self.attribute.value + try: - results = self.pssl.query(self.attribute.value) + results = self.pssl.query(value) except Exception: self.result = {'error': 'There is an authentication error, please make sure you supply correct credentials.'} return @@ -78,7 +80,7 @@ def handler(q=False): if not any(input_type == attribute['type'] for input_type in mispattributes['input']): return {'error': 'Unsupported attributes type'} pssl_parser = PassiveSSLParser(attribute, authentication) - pssl_parser.parse(attribute['value']) + pssl_parser.parse() return pssl_parser.get_results() From 6e21893be4869bcd5874bea0e2c854996962a47b Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Wed, 3 Jun 2020 10:48:43 +0200 Subject: [PATCH 06/30] fix: [circl_passivedns] Return not found error If passivedns returns empty response, return Not found error instead of error in log --- misp_modules/modules/expansion/circl_passivedns.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/misp_modules/modules/expansion/circl_passivedns.py b/misp_modules/modules/expansion/circl_passivedns.py index 75ff6c6..ef8042d 100755 --- a/misp_modules/modules/expansion/circl_passivedns.py +++ b/misp_modules/modules/expansion/circl_passivedns.py @@ -30,6 +30,11 @@ class PassiveDNSParser(): except Exception: self.result = {'error': 'There is an authentication error, please make sure you supply correct credentials.'} return + + if not results: + self.result = {'error': 'Not found'} + return + mapping = {'count': 'counter', 'origin': 'text', 'time_first': 'datetime', 'rrtype': 'text', 'rrname': 'text', 'rdata': 'text', From b053e1c01b0ea8f4189d7815dd194947113b22c5 Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Wed, 3 Jun 2020 11:19:21 +0200 Subject: [PATCH 07/30] fix: [circl_passivessl] Return not found error If passivessl returns empty response, return Not found error instead of error in log --- misp_modules/modules/expansion/circl_passivessl.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/misp_modules/modules/expansion/circl_passivessl.py b/misp_modules/modules/expansion/circl_passivessl.py index 0c11106..86ded68 100755 --- a/misp_modules/modules/expansion/circl_passivessl.py +++ b/misp_modules/modules/expansion/circl_passivessl.py @@ -37,6 +37,11 @@ class PassiveSSLParser(): except Exception: self.result = {'error': 'There is an authentication error, please make sure you supply correct credentials.'} return + + if not results: + self.result = {'error': 'Not found'} + return + for ip_address, certificates in results.items(): ip_uuid = self._handle_ip_attribute(ip_address) for certificate in certificates['certificates']: From fe1ea90b25773463ed2e6f0e8753a464cf9d148b Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Wed, 3 Jun 2020 14:06:57 +0200 Subject: [PATCH 08/30] fix: [circl_passivessl] Return proper error for IPv6 addresses --- misp_modules/modules/expansion/circl_passivessl.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/misp_modules/modules/expansion/circl_passivessl.py b/misp_modules/modules/expansion/circl_passivessl.py index 3419bbb..102bed8 100755 --- a/misp_modules/modules/expansion/circl_passivessl.py +++ b/misp_modules/modules/expansion/circl_passivessl.py @@ -44,6 +44,10 @@ class PassiveSSLParser(): self.result = {'error': 'Not found'} return + if 'error' in results: + self.result = {'error': results['error']} + return + for ip_address, certificates in results.items(): ip_uuid = self._handle_ip_attribute(ip_address) for certificate in certificates['certificates']: From a91d50b5073ec8890d3eec1c704d6e4626584bc9 Mon Sep 17 00:00:00 2001 From: Jesse Hedden Date: Sat, 27 Jun 2020 17:29:01 -0700 Subject: [PATCH 09/30] corrected variable name --- misp_modules/modules/expansion/trustar_enrich.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misp_modules/modules/expansion/trustar_enrich.py b/misp_modules/modules/expansion/trustar_enrich.py index 48b4895..efe7c53 100644 --- a/misp_modules/modules/expansion/trustar_enrich.py +++ b/misp_modules/modules/expansion/trustar_enrich.py @@ -81,7 +81,7 @@ class TruSTARParser: trustar_obj = MISPObject('trustar_report') indicator_type = summary.indicator_type indicator_value = summary.value - if summary_type in self.ENTITY_TYPE_MAPPINGS: + if indicator_type in self.ENTITY_TYPE_MAPPINGS: trustar_obj.add_attribute(indicator_type, attribute_type=self.ENTITY_TYPE_MAPPINGS[indicator_type], value=indicator_value) trustar_obj.add_attribute("INDICATOR_SUMMARY", attribute_type="text", From a70558945a1124c70875a5d9f217a55439828ea9 Mon Sep 17 00:00:00 2001 From: Jesse Hedden Date: Sat, 27 Jun 2020 17:46:51 -0700 Subject: [PATCH 10/30] removed obsolete file --- misp_modules/modules/import_mod/trustar_import.py | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 misp_modules/modules/import_mod/trustar_import.py diff --git a/misp_modules/modules/import_mod/trustar_import.py b/misp_modules/modules/import_mod/trustar_import.py deleted file mode 100644 index 2c55be2..0000000 --- a/misp_modules/modules/import_mod/trustar_import.py +++ /dev/null @@ -1,7 +0,0 @@ -import base64 -import json - -from trustar import TruStar - -misp_errors = {'error': "Error"} - From c0dae2b31b309557acaaeb4f0ccbd887e6b01780 Mon Sep 17 00:00:00 2001 From: chrisr3d Date: Tue, 30 Jun 2020 18:08:34 +0200 Subject: [PATCH 11/30] fix: Removed trustar_import module name in init to avoid validation issues (until it is submitted via PR?) --- misp_modules/modules/import_mod/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/misp_modules/modules/import_mod/__init__.py b/misp_modules/modules/import_mod/__init__.py index 45e3359..fbad911 100644 --- a/misp_modules/modules/import_mod/__init__.py +++ b/misp_modules/modules/import_mod/__init__.py @@ -15,5 +15,4 @@ __all__ = [ 'threatanalyzer_import', 'csvimport', 'joe_import', - 'trustar_import', ] From de8d78cc70e66413ee0c425782579e56dee53a25 Mon Sep 17 00:00:00 2001 From: chrisr3d Date: Tue, 30 Jun 2020 18:41:42 +0200 Subject: [PATCH 12/30] add: Trustar python library added to Pipfile --- Pipfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Pipfile b/Pipfile index 9e651de..8459176 100644 --- a/Pipfile +++ b/Pipfile @@ -60,6 +60,7 @@ geoip2 = "*" apiosintDS = "*" assemblyline_client = "*" vt-graph-api = "*" +trustar = "*" [requires] python_version = "3" From f45d9964f3e65abdc7a2f216bf10ef61aa6db7be Mon Sep 17 00:00:00 2001 From: Jesse Hedden Date: Tue, 30 Jun 2020 10:07:16 -0700 Subject: [PATCH 13/30] removed obsoleted module name --- misp_modules/modules/import_mod/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/misp_modules/modules/import_mod/__init__.py b/misp_modules/modules/import_mod/__init__.py index 45e3359..fbad911 100644 --- a/misp_modules/modules/import_mod/__init__.py +++ b/misp_modules/modules/import_mod/__init__.py @@ -15,5 +15,4 @@ __all__ = [ 'threatanalyzer_import', 'csvimport', 'joe_import', - 'trustar_import', ] From 26b0357ac71c66b4b5f7065827e9d4e461fcfedc Mon Sep 17 00:00:00 2001 From: chrisr3d Date: Tue, 30 Jun 2020 23:10:35 +0200 Subject: [PATCH 14/30] fix: Making pep8 happy --- misp_modules/modules/expansion/rbl.py | 10 +++++----- misp_modules/modules/import_mod/csvimport.py | 4 ++-- .../modules/import_mod/threatanalyzer_import.py | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/misp_modules/modules/expansion/rbl.py b/misp_modules/modules/expansion/rbl.py index 73f1b9b..4d7bba5 100644 --- a/misp_modules/modules/expansion/rbl.py +++ b/misp_modules/modules/expansion/rbl.py @@ -88,18 +88,18 @@ def handler(q=False): else: misperrors['error'] = "Unsupported attributes type" return misperrors - listed = [] - info = [] + listeds = [] + infos = [] ipRev = '.'.join(ip.split('.')[::-1]) for rbl in rbls: query = '{}.{}'.format(ipRev, rbl) try: txt = resolver.query(query, 'TXT') - listed.append(query) - info.append([str(t) for t in txt]) + listeds.append(query) + infos.append([str(t) for t in txt]) except Exception: continue - result = "\n".join(["{}: {}".format(l, " - ".join(i)) for l, i in zip(listed, info)]) + result = "\n".join([f"{listed}: {' - '.join(info)}" for listed, info in zip(listeds, infos)]) if not result: return {'error': 'No data found by querying known RBLs'} return {'results': [{'types': mispattributes.get('output'), 'values': result}]} diff --git a/misp_modules/modules/import_mod/csvimport.py b/misp_modules/modules/import_mod/csvimport.py index e4dc2e5..3ea7c25 100644 --- a/misp_modules/modules/import_mod/csvimport.py +++ b/misp_modules/modules/import_mod/csvimport.py @@ -244,11 +244,11 @@ def __any_mandatory_misp_field(header): def __special_parsing(data, delimiter): - return list(tuple(l.strip() for l in line[0].split(delimiter)) for line in csv.reader(io.TextIOWrapper(io.BytesIO(data.encode()), encoding='utf-8')) if line and not line[0].startswith('#')) + return list(tuple(part.strip() for part in line[0].split(delimiter)) for line in csv.reader(io.TextIOWrapper(io.BytesIO(data.encode()), encoding='utf-8')) if line and not line[0].startswith('#')) def __standard_parsing(data): - return list(tuple(l.strip() for l in line) for line in csv.reader(io.TextIOWrapper(io.BytesIO(data.encode()), encoding='utf-8')) if line and not line[0].startswith('#')) + return list(tuple(part.strip() for part in line) for line in csv.reader(io.TextIOWrapper(io.BytesIO(data.encode()), encoding='utf-8')) if line and not line[0].startswith('#')) def handler(q=False): diff --git a/misp_modules/modules/import_mod/threatanalyzer_import.py b/misp_modules/modules/import_mod/threatanalyzer_import.py index ff0a5b1..cbb9fef 100755 --- a/misp_modules/modules/import_mod/threatanalyzer_import.py +++ b/misp_modules/modules/import_mod/threatanalyzer_import.py @@ -99,7 +99,7 @@ def handler(q=False): results = process_analysis_json(json.loads(data.decode('utf-8'))) except ValueError: log.warning('MISP modules {0} failed: uploaded file is not a zip or json file.'.format(request['module'])) - return {'error': 'Uploaded file is not a zip or json file.'.format(request['module'])} + return {'error': 'Uploaded file is not a zip or json file.'} pass # keep only unique entries based on the value field results = list({v['values']: v for v in results}.values()) From f99174af2e6f571e262af4c9ea54b9357071391c Mon Sep 17 00:00:00 2001 From: chrisr3d Date: Wed, 1 Jul 2020 11:27:36 +0200 Subject: [PATCH 15/30] fix: Removed multiple spaces to comply with pep8 --- misp_modules/modules/import_mod/csvimport.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misp_modules/modules/import_mod/csvimport.py b/misp_modules/modules/import_mod/csvimport.py index 3ea7c25..34eed8c 100644 --- a/misp_modules/modules/import_mod/csvimport.py +++ b/misp_modules/modules/import_mod/csvimport.py @@ -244,7 +244,7 @@ def __any_mandatory_misp_field(header): def __special_parsing(data, delimiter): - return list(tuple(part.strip() for part in line[0].split(delimiter)) for line in csv.reader(io.TextIOWrapper(io.BytesIO(data.encode()), encoding='utf-8')) if line and not line[0].startswith('#')) + return list(tuple(part.strip() for part in line[0].split(delimiter)) for line in csv.reader(io.TextIOWrapper(io.BytesIO(data.encode()), encoding='utf-8')) if line and not line[0].startswith('#')) def __standard_parsing(data): From cda5feedaadc4f06eb7a4c83347ee504feef29e8 Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Wed, 1 Jul 2020 16:13:40 +0200 Subject: [PATCH 16/30] fix: [virustotal] Subdomains is optional in VT response --- misp_modules/modules/expansion/virustotal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misp_modules/modules/expansion/virustotal.py b/misp_modules/modules/expansion/virustotal.py index f47a2e3..b09de81 100644 --- a/misp_modules/modules/expansion/virustotal.py +++ b/misp_modules/modules/expansion/virustotal.py @@ -52,7 +52,7 @@ class VirusTotalParser(object): 'downloaded': 'downloaded-from', 'referrer': 'referring'} siblings = (self.parse_siblings(domain) for domain in req['domain_siblings']) - uuid = self.parse_resolutions(req['resolutions'], req['subdomains'], siblings) + uuid = self.parse_resolutions(req['resolutions'], req['subdomains'] if 'subdomains' in req else None, siblings) for feature_type, relationship in feature_types.items(): for feature in ('undetected_{}_samples', 'detected_{}_samples'): for sample in req.get(feature.format(feature_type), [])[:self.limit]: From b5e0995926d9064d0d3e8f5195e241208c0d027b Mon Sep 17 00:00:00 2001 From: chrisr3d Date: Fri, 3 Jul 2020 09:41:20 +0200 Subject: [PATCH 17/30] fix: Fixed validators dependency issues - Possible rollback if we get issues with virustotal --- Pipfile | 2 +- Pipfile.lock | 734 +++++++++++++++++++++++++++------------------------ 2 files changed, 395 insertions(+), 341 deletions(-) diff --git a/Pipfile b/Pipfile index 8459176..1169368 100644 --- a/Pipfile +++ b/Pipfile @@ -18,7 +18,7 @@ pypdns = "*" pypssl = "*" pyeupi = "*" uwhois = {editable = true,git = "https://github.com/Rafiot/uwhoisd.git",ref = "testing",subdirectory = "client"} -pymisp = {editable = true,extras = ["fileobjects,openioc,virustotal,pdfexport"],git = "https://github.com/MISP/PyMISP.git"} +pymisp = {editable = true,extras = ["fileobjects,openioc,pdfexport"],git = "https://github.com/MISP/PyMISP.git"} pyonyphe = {editable = true,git = "https://github.com/sebdraven/pyonyphe"} pydnstrails = {editable = true,git = "https://github.com/sebdraven/pydnstrails"} pytesseract = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 9a23d0d..73aeaed 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "b62db6df8a7b42f4c6915d6fbb1d4c38ccbb7209e559708433d28cdddebd3df9" + "sha256": "c2d937b384431e4b313b29bb02db0bd1d3a866ddcb7c6e91cbfa34f88d351b59" }, "pipfile-spec": 6, "requires": { @@ -18,30 +18,21 @@ "default": { "aiohttp": { "hashes": [ - "sha256:0419705a36b43c0ac6f15469f9c2a08cad5c939d78bd12a5c23ea167c8253b2b", - "sha256:1812fc4bc6ac1bde007daa05d2d0f61199324e0cc893b11523e646595047ca08", - "sha256:2214b5c0153f45256d5d52d1e0cafe53f9905ed035a142191727a5fb620c03dd", - "sha256:275909137f0c92c61ba6bb1af856a522d5546f1de8ea01e4e726321c697754ac", - "sha256:3983611922b561868428ea1e7269e757803713f55b53502423decc509fef1650", - "sha256:51afec6ffa50a9da4cdef188971a802beb1ca8e8edb40fa429e5e529db3475fa", - "sha256:589f2ec8a101a0f340453ee6945bdfea8e1cd84c8d88e5be08716c34c0799d95", - "sha256:789820ddc65e1f5e71516adaca2e9022498fa5a837c79ba9c692a9f8f916c330", - "sha256:7a968a0bdaaf9abacc260911775611c9a602214a23aeb846f2eb2eeaa350c4dc", - "sha256:7aeefbed253f59ea39e70c5848de42ed85cb941165357fc7e87ab5d8f1f9592b", - "sha256:7b2eb55c66512405103485bd7d285a839d53e7fdc261ab20e5bcc51d7aaff5de", - "sha256:87bc95d3d333bb689c8d755b4a9d7095a2356108002149523dfc8e607d5d32a4", - "sha256:9d80e40db208e29168d3723d1440ecbb06054d349c5ece6a2c5a611490830dd7", - "sha256:a1b442195c2a77d33e4dbee67c9877ccbdd3a1f686f91eb479a9577ed8cc326b", - "sha256:ab3d769413b322d6092f169f316f7b21cd261a7589f7e31db779d5731b0480d8", - "sha256:b066d3dec5d0f5aee6e34e5765095dc3d6d78ef9839640141a2b20816a0642bd", - "sha256:b24e7845ae8de3e388ef4bcfcf7f96b05f52c8e633b33cf8003a6b1d726fc7c2", - "sha256:c59a953c3f8524a7c86eaeaef5bf702555be12f5668f6384149fe4bb75c52698", - "sha256:cf2cc6c2c10d242790412bea7ccf73726a9a44b4c4b073d2699ef3b48971fd95", - "sha256:e0c9c8d4150ae904f308ff27b35446990d2b1dfc944702a21925937e937394c6", - "sha256:f1839db4c2b08a9c8f9788112644f8a8557e8e0ecc77b07091afabb941dc55d0", - "sha256:f3df52362be39908f9c028a65490fae0475e4898b43a03d8aa29d1e765b45e07" + "sha256:1e984191d1ec186881ffaed4581092ba04f7c61582a177b187d3a2f07ed9719e", + "sha256:259ab809ff0727d0e834ac5e8a283dc5e3e0ecc30c4d80b3cd17a4139ce1f326", + "sha256:2f4d1a4fdce595c947162333353d4a44952a724fba9ca3205a3df99a33d1307a", + "sha256:32e5f3b7e511aa850829fbe5aa32eb455e5534eaa4b1ce93231d00e2f76e5654", + "sha256:344c780466b73095a72c616fac5ea9c4665add7fc129f285fbdbca3cccf4612a", + "sha256:460bd4237d2dbecc3b5ed57e122992f60188afe46e7319116da5eb8a9dfedba4", + "sha256:4c6efd824d44ae697814a2a85604d8e992b875462c6655da161ff18fd4f29f17", + "sha256:50aaad128e6ac62e7bf7bd1f0c0a24bc968a0c0590a726d5a955af193544bcec", + "sha256:6206a135d072f88da3e71cc501c59d5abffa9d0bb43269a6dcd28d66bfafdbdd", + "sha256:65f31b622af739a802ca6fd1a3076fd0ae523f8485c52924a89561ba10c49b48", + "sha256:ae55bac364c405caa23a4f2d6cfecc6a0daada500274ffca4a9230e7129eac59", + "sha256:b778ce0c909a2653741cb4b1ac7015b5c130ab9c897611df43ae6a58523cb965" ], - "version": "==3.4.4" + "markers": "python_full_version >= '3.5.3'", + "version": "==3.6.2" }, "antlr4-python3-runtime": { "hashes": [ @@ -77,6 +68,7 @@ "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f", "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3" ], + "markers": "python_full_version >= '3.5.3'", "version": "==3.0.1" }, "attrs": { @@ -84,6 +76,7 @@ "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==19.3.0" }, "backscatter": { @@ -96,12 +89,12 @@ }, "beautifulsoup4": { "hashes": [ - "sha256:05fd825eb01c290877657a56df4c6e4c311b3965bda790c613a3d6fb01a5462a", - "sha256:9fbb4d6e48ecd30bcacc5b63b94088192dcda178513b2ae3c394229f8911b887", - "sha256:e1505eeed31b0f4ce2dbb3bc8eb256c04cc2b3b72af7d551a4ab6efd5cbe5dae" + "sha256:73cc4d115b96f79c7d77c1c7f7a0a8d4c57860d1041df407dd1aae7f07a77fd7", + "sha256:a6237df3c32ccfaee4fd201c8f5f9d9df619b93121d01353a64a73ce8c6ef9a8", + "sha256:e718f2342e2e099b640a34ab782407b7b676f47ee272d6739e60b8ea23829f2c" ], "index": "pypi", - "version": "==4.8.2" + "version": "==4.9.1" }, "blockchain": { "hashes": [ @@ -112,10 +105,10 @@ }, "certifi": { "hashes": [ - "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304", - "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519" + "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3", + "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41" ], - "version": "==2020.4.5.1" + "version": "==2020.6.20" }, "cffi": { "hashes": [ @@ -162,6 +155,7 @@ "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a", "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==7.1.2" }, "click-plugins": { @@ -176,8 +170,17 @@ "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff", "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==0.4.3" }, + "configparser": { + "hashes": [ + "sha256:2ca44140ee259b5e3d8aaf47c79c36a7ab0d5e94d70bd4105c03ede7a20ea5a1", + "sha256:cffc044844040c7ce04e9acd1838b5f2e5fa3170182f6fda4d2ea8b0099dbadd" + ], + "markers": "python_version >= '3.6'", + "version": "==5.0.0" + }, "cryptography": { "hashes": [ "sha256:091d31c42f444c6f519485ed528d8b451d1a0c7bf30e8ca583a0cac44b8a0df6", @@ -214,6 +217,7 @@ "sha256:525ba66fb5f90b07169fdd48b6373c18f1ee12728ca277ca44567a367d9d7f74", "sha256:a766c1dccb30c5f6eb2b203f87edd1d8588847709c78589e1521d769addc8218" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.2.10" }, "dnspython": { @@ -226,10 +230,11 @@ }, "domaintools-api": { "hashes": [ - "sha256:f567f407b8997e947df5badf7c2bea64fdfd33c54ade24eab36ef575fb71ccb7" + "sha256:62e2e688d14dbd7ca51a44bd0a8490aa69c712895475598afbdbb1e1e15bf2f2", + "sha256:fe75e3cc86e7e2904b06d8e94b1986e721fdce85d695c87d1140403957e4c989" ], "index": "pypi", - "version": "==0.3.3" + "version": "==0.5.2" }, "enum-compat": { "hashes": [ @@ -255,6 +260,7 @@ "hashes": [ "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d" ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.18.2" }, "futures": { @@ -275,24 +281,23 @@ }, "httplib2": { "hashes": [ - "sha256:4f6988e6399a2546b525a037d56da34aed4d149bbdc0e78523018d5606c26e74", - "sha256:b0e1f3ed76c97380fe2485bc47f25235453b40ef33ca5921bb2897e257a49c4c" + "sha256:8af66c1c52c7ffe1aa5dc4bcd7c769885254b0756e6e69f953c7f0ab49a70ba3", + "sha256:ca2914b015b6247791c4866782fa6042f495b94401a0f0bd3e1d6e0ba2236782" ], - "index": "pypi", - "version": "==0.18.0" + "version": "==0.18.1" }, "idna": { "hashes": [ - "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb", - "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa" + "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", + "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" ], - "version": "==2.9" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.10" }, "idna-ssl": { "hashes": [ "sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c" ], - "index": "pypi", "markers": "python_version < '3.7'", "version": "==1.1.0" }, @@ -305,10 +310,10 @@ }, "jbxapi": { "hashes": [ - "sha256:98253ba0bf79a9d0c87d823d54e2f7568625708185b3d4517ee4982cc964d888" + "sha256:58eb7d77a52169309e2322ce874c0f00a7900a515d1d0798ff85973cdb2766e3" ], "index": "pypi", - "version": "==3.4.0" + "version": "==3.8.0" }, "jsonschema": { "hashes": [ @@ -338,36 +343,36 @@ }, "lxml": { "hashes": [ - "sha256:06d4e0bbb1d62e38ae6118406d7cdb4693a3fa34ee3762238bcb96c9e36a93cd", - "sha256:0701f7965903a1c3f6f09328c1278ac0eee8f56f244e66af79cb224b7ef3801c", - "sha256:1f2c4ec372bf1c4a2c7e4bb20845e8bcf8050365189d86806bad1e3ae473d081", - "sha256:4235bc124fdcf611d02047d7034164897ade13046bda967768836629bc62784f", - "sha256:5828c7f3e615f3975d48f40d4fe66e8a7b25f16b5e5705ffe1d22e43fb1f6261", - "sha256:585c0869f75577ac7a8ff38d08f7aac9033da2c41c11352ebf86a04652758b7a", - "sha256:5d467ce9c5d35b3bcc7172c06320dddb275fea6ac2037f72f0a4d7472035cea9", - "sha256:63dbc21efd7e822c11d5ddbedbbb08cd11a41e0032e382a0fd59b0b08e405a3a", - "sha256:7bc1b221e7867f2e7ff1933165c0cec7153dce93d0cdba6554b42a8beb687bdb", - "sha256:8620ce80f50d023d414183bf90cc2576c2837b88e00bea3f33ad2630133bbb60", - "sha256:8a0ebda56ebca1a83eb2d1ac266649b80af8dd4b4a3502b2c1e09ac2f88fe128", - "sha256:90ed0e36455a81b25b7034038e40880189169c308a3df360861ad74da7b68c1a", - "sha256:95e67224815ef86924fbc2b71a9dbd1f7262384bca4bc4793645794ac4200717", - "sha256:afdb34b715daf814d1abea0317b6d672476b498472f1e5aacbadc34ebbc26e89", - "sha256:b4b2c63cc7963aedd08a5f5a454c9f67251b1ac9e22fd9d72836206c42dc2a72", - "sha256:d068f55bda3c2c3fcaec24bd083d9e2eede32c583faf084d6e4b9daaea77dde8", - "sha256:d5b3c4b7edd2e770375a01139be11307f04341ec709cf724e0f26ebb1eef12c3", - "sha256:deadf4df349d1dcd7b2853a2c8796593cc346600726eff680ed8ed11812382a7", - "sha256:df533af6f88080419c5a604d0d63b2c33b1c0c4409aba7d0cb6de305147ea8c8", - "sha256:e4aa948eb15018a657702fee0b9db47e908491c64d36b4a90f59a64741516e77", - "sha256:e5d842c73e4ef6ed8c1bd77806bf84a7cb535f9c0cf9b2c74d02ebda310070e1", - "sha256:ebec08091a22c2be870890913bdadd86fcd8e9f0f22bcb398abd3af914690c15", - "sha256:edc15fcfd77395e24543be48871c251f38132bb834d9fdfdad756adb6ea37679", - "sha256:f2b74784ed7e0bc2d02bd53e48ad6ba523c9b36c194260b7a5045071abbb1012", - "sha256:fa071559f14bd1e92077b1b5f6c22cf09756c6de7139370249eb372854ce51e6", - "sha256:fd52e796fee7171c4361d441796b64df1acfceb51f29e545e812f16d023c4bbc", - "sha256:fe976a0f1ef09b3638778024ab9fb8cde3118f203364212c198f71341c0715ca" + "sha256:06748c7192eab0f48e3d35a7adae609a329c6257495d5e53878003660dc0fec6", + "sha256:0790ddca3f825dd914978c94c2545dbea5f56f008b050e835403714babe62a5f", + "sha256:1aa7a6197c1cdd65d974f3e4953764eee3d9c7b67e3966616b41fab7f8f516b7", + "sha256:22c6d34fdb0e65d5f782a4d1a1edb52e0a8365858dafb1c08cb1d16546cf0786", + "sha256:2754d4406438c83144f9ffd3628bbe2dcc6d62b20dbc5c1ec4bc4385e5d44b42", + "sha256:27ee0faf8077c7c1a589573b1450743011117f1aa1a91d5ae776bbc5ca6070f2", + "sha256:2b02c106709466a93ed424454ce4c970791c486d5fcdf52b0d822a7e29789626", + "sha256:2d1ddce96cf15f1254a68dba6935e6e0f1fe39247de631c115e84dd404a6f031", + "sha256:4f282737d187ae723b2633856085c31ae5d4d432968b7f3f478a48a54835f5c4", + "sha256:51bb4edeb36d24ec97eb3e6a6007be128b720114f9a875d6b370317d62ac80b9", + "sha256:7eee37c1b9815e6505847aa5e68f192e8a1b730c5c7ead39ff317fde9ce29448", + "sha256:7fd88cb91a470b383aafad554c3fe1ccf6dfb2456ff0e84b95335d582a799804", + "sha256:9144ce36ca0824b29ebc2e02ca186e54040ebb224292072250467190fb613b96", + "sha256:925baf6ff1ef2c45169f548cc85204433e061360bfa7d01e1be7ae38bef73194", + "sha256:a636346c6c0e1092ffc202d97ec1843a75937d8c98aaf6771348ad6422e44bb0", + "sha256:a87dbee7ad9dce3aaefada2081843caf08a44a8f52e03e0a4cc5819f8398f2f4", + "sha256:a9e3b8011388e7e373565daa5e92f6c9cb844790dc18e43073212bb3e76f7007", + "sha256:afb53edf1046599991fb4a7d03e601ab5f5422a5435c47ee6ba91ec3b61416a6", + "sha256:b26719890c79a1dae7d53acac5f089d66fd8cc68a81f4e4bd355e45470dc25e1", + "sha256:b7462cdab6fffcda853338e1741ce99706cdf880d921b5a769202ea7b94e8528", + "sha256:b77975465234ff49fdad871c08aa747aae06f5e5be62866595057c43f8d2f62c", + "sha256:c47a8a5d00060122ca5908909478abce7bbf62d812e3fc35c6c802df8fb01fe7", + "sha256:c79e5debbe092e3c93ca4aee44c9a7631bdd407b2871cb541b979fd350bbbc29", + "sha256:d8d40e0121ca1606aa9e78c28a3a7d88a05c06b3ca61630242cded87d8ce55fa", + "sha256:ee2be8b8f72a2772e72ab926a3bccebf47bb727bda41ae070dc91d1fb759b726", + "sha256:f95d28193c3863132b1f55c1056036bf580b5a488d908f7d22a04ace8935a3a9", + "sha256:fadd2a63a2bfd7fb604508e553d1cf68eca250b2fbdbd81213b5f6f2fbf23529" ], "index": "pypi", - "version": "==4.5.0" + "version": "==4.5.1" }, "maclookup": { "hashes": [ @@ -381,6 +386,7 @@ "hashes": [ "sha256:f4d28823d9ca23323d113dc7af8db2087aa4f657fafc64ff8f7a8afda871425b" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==1.5.4" }, "misp-modules": { @@ -407,6 +413,7 @@ "sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255", "sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d" ], + "markers": "python_version >= '3.5'", "version": "==4.7.6" }, "np": { @@ -418,29 +425,35 @@ }, "numpy": { "hashes": [ - "sha256:00d7b54c025601e28f468953d065b9b121ddca7fff30bed7be082d3656dd798d", - "sha256:02ec9582808c4e48be4e93cd629c855e644882faf704bc2bd6bbf58c08a2a897", - "sha256:0e6f72f7bb08f2f350ed4408bb7acdc0daba637e73bce9f5ea2b207039f3af88", - "sha256:1be2e96314a66f5f1ce7764274327fd4fb9da58584eaff00b5a5221edefee7d6", - "sha256:2466fbcf23711ebc5daa61d28ced319a6159b260a18839993d871096d66b93f7", - "sha256:2b573fcf6f9863ce746e4ad00ac18a948978bb3781cffa4305134d31801f3e26", - "sha256:3f0dae97e1126f529ebb66f3c63514a0f72a177b90d56e4bce8a0b5def34627a", - "sha256:50fb72bcbc2cf11e066579cb53c4ca8ac0227abb512b6cbc1faa02d1595a2a5d", - "sha256:57aea170fb23b1fd54fa537359d90d383d9bf5937ee54ae8045a723caa5e0961", - "sha256:709c2999b6bd36cdaf85cf888d8512da7433529f14a3689d6e37ab5242e7add5", - "sha256:7d59f21e43bbfd9a10953a7e26b35b6849d888fc5a331fa84a2d9c37bd9fe2a2", - "sha256:904b513ab8fbcbdb062bed1ce2f794ab20208a1b01ce9bd90776c6c7e7257032", - "sha256:96dd36f5cdde152fd6977d1bbc0f0561bccffecfde63cd397c8e6033eb66baba", - "sha256:9933b81fecbe935e6a7dc89cbd2b99fea1bf362f2790daf9422a7bb1dc3c3085", - "sha256:bbcc85aaf4cd84ba057decaead058f43191cc0e30d6bc5d44fe336dc3d3f4509", - "sha256:dccd380d8e025c867ddcb2f84b439722cf1f23f3a319381eac45fd077dee7170", - "sha256:e22cd0f72fc931d6abc69dc7764484ee20c6a60b0d0fee9ce0426029b1c1bdae", - "sha256:ed722aefb0ebffd10b32e67f48e8ac4c5c4cf5d3a785024fdf0e9eb17529cd9d", - "sha256:efb7ac5572c9a57159cf92c508aad9f856f1cb8e8302d7fdb99061dbe52d712c", - "sha256:efdba339fffb0e80fcc19524e4fdbda2e2b5772ea46720c44eaac28096d60720", - "sha256:f22273dd6a403ed870207b853a856ff6327d5cbce7a835dfa0645b3fc00273ec" + "sha256:13af0184177469192d80db9bd02619f6fa8b922f9f327e077d6f2a6acb1ce1c0", + "sha256:26a45798ca2a4e168d00de75d4a524abf5907949231512f372b217ede3429e98", + "sha256:26f509450db547e4dfa3ec739419b31edad646d21fb8d0ed0734188b35ff6b27", + "sha256:30a59fb41bb6b8c465ab50d60a1b298d1cd7b85274e71f38af5a75d6c475d2d2", + "sha256:33c623ef9ca5e19e05991f127c1be5aeb1ab5cdf30cb1c5cf3960752e58b599b", + "sha256:356f96c9fbec59974a592452ab6a036cd6f180822a60b529a975c9467fcd5f23", + "sha256:3c40c827d36c6d1c3cf413694d7dc843d50997ebffbc7c87d888a203ed6403a7", + "sha256:4d054f013a1983551254e2379385e359884e5af105e3efe00418977d02f634a7", + "sha256:63d971bb211ad3ca37b2adecdd5365f40f3b741a455beecba70fd0dde8b2a4cb", + "sha256:658624a11f6e1c252b2cd170d94bf28c8f9410acab9f2fd4369e11e1cd4e1aaf", + "sha256:76766cc80d6128750075378d3bb7812cf146415bd29b588616f72c943c00d598", + "sha256:7b57f26e5e6ee2f14f960db46bd58ffdca25ca06dd997729b1b179fddd35f5a3", + "sha256:7b852817800eb02e109ae4a9cef2beda8dd50d98b76b6cfb7b5c0099d27b52d4", + "sha256:8cde829f14bd38f6da7b2954be0f2837043e8b8d7a9110ec5e318ae6bf706610", + "sha256:a2e3a39f43f0ce95204beb8fe0831199542ccab1e0c6e486a0b4947256215632", + "sha256:a86c962e211f37edd61d6e11bb4df7eddc4a519a38a856e20a6498c319efa6b0", + "sha256:a8705c5073fe3fcc297fb8e0b31aa794e05af6a329e81b7ca4ffecab7f2b95ef", + "sha256:b6aaeadf1e4866ca0fdf7bb4eed25e521ae21a7947c59f78154b24fc7abbe1dd", + "sha256:be62aeff8f2f054eff7725f502f6228298891fd648dc2630e03e44bf63e8cee0", + "sha256:c2edbb783c841e36ca0fa159f0ae97a88ce8137fb3a6cd82eae77349ba4b607b", + "sha256:cbe326f6d364375a8e5a8ccb7e9cd73f4b2f6dc3b2ed205633a0db8243e2a96a", + "sha256:d34fbb98ad0d6b563b95de852a284074514331e6b9da0a9fc894fb1cdae7a79e", + "sha256:d97a86937cf9970453c3b62abb55a6475f173347b4cde7f8dcdb48c8e1b9952d", + "sha256:dd53d7c4a69e766e4900f29db5872f5824a06827d594427cf1a4aa542818b796", + "sha256:df1889701e2dfd8ba4dc9b1a010f0a60950077fb5242bb92c8b5c7f1a6f2668a", + "sha256:fa1fe75b4a9e18b66ae7f0b122543c42debcf800aaafa0212aaff3ad273c2596" ], - "version": "==1.18.4" + "markers": "python_version >= '3.6'", + "version": "==1.19.0" }, "oauth2": { "hashes": [ @@ -457,58 +470,51 @@ }, "opencv-python": { "hashes": [ - "sha256:0f2e739c582e8c5e432130648bc6d66a56bc65f4cd9ff0bc7033033d2130c7a3", - "sha256:0f3d159ad6cb9cbd188c726f87485f0799a067a0a15f34c25d7b5c8db3cb2e50", - "sha256:167a6aff9bd124a3a67e0ec25d0da5ecdc8d96a56405e3e5e7d586c4105eb1bb", - "sha256:1b90d50bc7a31e9573a8da1b80fcd1e4d9c86c0e5f76387858e1b87eb8b0332b", - "sha256:2baf1213ae2fd678991f905d7b2b94eddfdfb5f75757db0f0b31eebd48ca200d", - "sha256:312dda54c7e809c20d7409418060ae0e9cdbe82975e7ced429eb3c234ffc0d4a", - "sha256:32384e675f7cefe707cac40a95eeb142d6869065e39c5500374116297cd8ca6d", - "sha256:5c50634dd8f2f866fd99fd939292ce10e52bef82804ebc4e7f915221c3b7e951", - "sha256:6841bb9cc24751dbdf94e7eefc4e6d70ec297952501954471299fd12ab67391c", - "sha256:68c1c846dd267cd7e293d3fc0bb238db0a744aa1f2e721e327598f00cb982098", - "sha256:703910aaa1dcd25a412f78a190fb7a352d9a64ee7d9a35566d786f3cc66ebf20", - "sha256:8002959146ed21959e3118c60c8e94ceac02eea15b691da6c62cff4787c63f7f", - "sha256:889eef049d38488b5b4646c48a831feed37c0fd44f3d83c05cff80f4baded145", - "sha256:8c76983c9ec3e4cf3a4c1d172ec4285332d9fb1c7194d724aff0c518437471ee", - "sha256:9cd9bd72f4a9743ef6f11f0f96784bd215a542e996db1717d4c2d3d03eb81a1b", - "sha256:a1a5517301dc8d56243a14253d231ec755b94486b4fff2ae68269bc941bb1f2e", - "sha256:a2b08aec2eacae868723136383d9eb84a33062a7a7ec5ec3bd2c423bd1355946", - "sha256:a8529a79233f3581a66984acd16bce52ab0163f6f77568dd69e9ee4956d2e1db", - "sha256:afbc81a3870739610a9f9a1197374d6a45892cf1933c90fc5617d39790991ed3", - "sha256:baeb5dd8b21c718580687f5b4efd03f8139b1c56239cdf6b9805c6946e80f268", - "sha256:db1d49b753e6e6c76585f21d09c7e9812176732baa9bddb64bc2fc6cd24d4179", - "sha256:e242ed419aeb2488e0f9ee6410a34917f0f8d62b3ae96aa3170d83bae75004e2", - "sha256:e36a8857be2c849e54009f1bee25e8c34fbc683fcd38c6c700af4cba5f8d57c2", - "sha256:e699232fd033ef0053efec2cba0a7505514f374ba7b18c732a77cb5304311ef9", - "sha256:eae3da9231d87980f8082d181c276a04f7a6fdac130cebd467390b96dd05f944", - "sha256:ee6814c94dbf1cae569302afef9dd29efafc52373e8770ded0db549a3b6e0c00", - "sha256:f01a87a015227d8af407161eb48222fc3c8b01661cdc841e2b86eee4f1a7a417" + "sha256:068928b9907b3d3acd53b129062557d6b0b8b324bfade77f028dbe4dfe482bf2", + "sha256:0e7c91718351449877c2d4141abd64eee1f9c8701bcfaf4e8627bd023e303368", + "sha256:1ab92d807427641ec45d28d5907426aa06b4ffd19c5b794729c74d91cd95090e", + "sha256:31d634dea1b47c231b88d384f90605c598214d0c596443c9bb808e11761829f5", + "sha256:5fdfc0bed37315f27d30ae5ae9bad47ec0a0a28c323739d39c8177b7e0929238", + "sha256:6fa8fac14dd5af4819d475f74af12d65fbbfa391d3110c3a972934a5e6507c24", + "sha256:78cc89ebc808886eb190626ee71ab65e47f374121975f86e4d5f7c0e3ce6bed9", + "sha256:7c7ba11720d01cb572b4b6945d115cb103462c0a28996b44d4e540d06e6a90fd", + "sha256:a37ee82f1b8ed4b4645619c504311e71ce845b78f40055e78d71add5fab7da82", + "sha256:aa3ca1f54054e1c6439fdf1edafa2a2b940a9eaac04a7b422a1cba9b2d7b9690", + "sha256:b9de3dd956574662712da8e285f0f54327959a4e95b96a2847d3c3f5ee7b96e2", + "sha256:c0087b428cef9a32d977390656d91b02245e0e91f909870492df7e39202645dd", + "sha256:d87e506ab205799727f0efa34b3888949bf029a3ada5eb000ff632606370ca6e", + "sha256:d8a55585631f9c9eca4b1a996e9732ae023169cf2f46f69e4518d67d96198226", + "sha256:dcb8da8c5ebaa6360c8555547a4c7beb6cd983dd95ba895bb78b86cc8cf3de2b", + "sha256:e2206bb8c17c0f212f1f356d82d72dd090ff4651994034416da9bf0c29732825", + "sha256:e3c57d6579e5bf85f564d6d48d8ee89868b92879a9232b9975d072c346625e92", + "sha256:ef89cbf332b9a735d8a82e9ff79cc743eeeb775ad1cd7100bc2aa2429b496f07", + "sha256:f45c1c3cdda1857bedd4dfe0bbd49c9419af0cc57f33490341edeae97d18f037", + "sha256:fb3c855347310788e4286b867997be354c55535597966ed5dac876d9166013a4" ], "index": "pypi", - "version": "==4.2.0.32" + "version": "==4.2.0.34" }, "pandas": { "hashes": [ - "sha256:07c1b58936b80eafdfe694ce964ac21567b80a48d972879a359b3ebb2ea76835", - "sha256:0ebe327fb088df4d06145227a4aa0998e4f80a9e6aed4b61c1f303bdfdf7c722", - "sha256:11c7cb654cd3a0e9c54d81761b5920cdc86b373510d829461d8f2ed6d5905266", - "sha256:12f492dd840e9db1688126216706aa2d1fcd3f4df68a195f9479272d50054645", - "sha256:167a1315367cea6ec6a5e11e791d9604f8e03f95b57ad227409de35cf850c9c5", - "sha256:1a7c56f1df8d5ad8571fa251b864231f26b47b59cbe41aa5c0983d17dbb7a8e4", - "sha256:1fa4bae1a6784aa550a1c9e168422798104a85bf9c77a1063ea77ee6f8452e3a", - "sha256:32f42e322fb903d0e189a4c10b75ba70d90958cc4f66a1781ed027f1a1d14586", - "sha256:387dc7b3c0424327fe3218f81e05fc27832772a5dffbed385013161be58df90b", - "sha256:6597df07ea361231e60c00692d8a8099b519ed741c04e65821e632bc9ccb924c", - "sha256:743bba36e99d4440403beb45a6f4f3a667c090c00394c176092b0b910666189b", - "sha256:858a0d890d957ae62338624e4aeaf1de436dba2c2c0772570a686eaca8b4fc85", - "sha256:863c3e4b7ae550749a0bb77fa22e601a36df9d2905afef34a6965bed092ba9e5", - "sha256:a210c91a02ec5ff05617a298ad6f137b9f6f5771bf31f2d6b6367d7f71486639", - "sha256:ca84a44cf727f211752e91eab2d1c6c1ab0f0540d5636a8382a3af428542826e", - "sha256:d234bcf669e8b4d6cbcd99e3ce7a8918414520aeb113e2a81aeb02d0a533d7f7" + "sha256:02f1e8f71cd994ed7fcb9a35b6ddddeb4314822a0e09a9c5b2d278f8cb5d4096", + "sha256:13f75fb18486759da3ff40f5345d9dd20e7d78f2a39c5884d013456cec9876f0", + "sha256:35b670b0abcfed7cad76f2834041dcf7ae47fd9b22b63622d67cdc933d79f453", + "sha256:4c73f373b0800eb3062ffd13d4a7a2a6d522792fa6eb204d67a4fad0a40f03dc", + "sha256:5759edf0b686b6f25a5d4a447ea588983a33afc8a0081a0954184a4a87fd0dd7", + "sha256:5a7cf6044467c1356b2b49ef69e50bf4d231e773c3ca0558807cdba56b76820b", + "sha256:69c5d920a0b2a9838e677f78f4dde506b95ea8e4d30da25859db6469ded84fa8", + "sha256:8778a5cc5a8437a561e3276b85367412e10ae9fff07db1eed986e427d9a674f8", + "sha256:9871ef5ee17f388f1cb35f76dc6106d40cb8165c562d573470672f4cdefa59ef", + "sha256:9c31d52f1a7dd2bb4681d9f62646c7aa554f19e8e9addc17e8b1b20011d7522d", + "sha256:ab8173a8efe5418bbe50e43f321994ac6673afc5c7c4839014cf6401bbdd0705", + "sha256:ae961f1f0e270f1e4e2273f6a539b2ea33248e0e3a11ffb479d757918a5e03a9", + "sha256:b3c4f93fcb6e97d993bf87cdd917883b7dab7d20c627699f360a8fb49e9e0b91", + "sha256:c9410ce8a3dee77653bc0684cfa1535a7f9c291663bd7ad79e39f5ab58f67ab3", + "sha256:f69e0f7b7c09f1f612b1f8f59e2df72faa8a6b41c5a436dde5b615aaf948f107", + "sha256:faa42a78d1350b02a7d2f0dbe3c80791cf785663d6997891549d0f86dc49125e" ], "index": "pypi", - "version": "==1.0.3" + "version": "==1.0.5" }, "pandas-ods-reader": { "hashes": [ @@ -536,38 +542,42 @@ }, "pillow": { "hashes": [ - "sha256:0a628977ac2e01ca96aaae247ec2bd38e729631ddf2221b4b715446fd45505be", - "sha256:4d9ed9a64095e031435af120d3c910148067087541131e82b3e8db302f4c8946", - "sha256:54ebae163e8412aff0b9df1e88adab65788f5f5b58e625dc5c7f51eaf14a6837", - "sha256:5bfef0b1cdde9f33881c913af14e43db69815c7e8df429ceda4c70a5e529210f", - "sha256:5f3546ceb08089cedb9e8ff7e3f6a7042bb5b37c2a95d392fb027c3e53a2da00", - "sha256:5f7ae9126d16194f114435ebb79cc536b5682002a4fa57fa7bb2cbcde65f2f4d", - "sha256:62a889aeb0a79e50ecf5af272e9e3c164148f4bd9636cc6bcfa182a52c8b0533", - "sha256:7406f5a9b2fd966e79e6abdaf700585a4522e98d6559ce37fc52e5c955fade0a", - "sha256:8453f914f4e5a3d828281a6628cf517832abfa13ff50679a4848926dac7c0358", - "sha256:87269cc6ce1e3dee11f23fa515e4249ae678dbbe2704598a51cee76c52e19cda", - "sha256:875358310ed7abd5320f21dd97351d62de4929b0426cdb1eaa904b64ac36b435", - "sha256:8ac6ce7ff3892e5deaab7abaec763538ffd011f74dc1801d93d3c5fc541feee2", - "sha256:91b710e3353aea6fc758cdb7136d9bbdcb26b53cefe43e2cba953ac3ee1d3313", - "sha256:9d2ba4ed13af381233e2d810ff3bab84ef9f18430a9b336ab69eaf3cd24299ff", - "sha256:a62ec5e13e227399be73303ff301f2865bf68657d15ea50b038d25fc41097317", - "sha256:ab76e5580b0ed647a8d8d2d2daee170e8e9f8aad225ede314f684e297e3643c2", - "sha256:bf4003aa538af3f4205c5fac56eacaa67a6dd81e454ffd9e9f055fff9f1bc614", - "sha256:bf598d2e37cf8edb1a2f26ed3fb255191f5232badea4003c16301cb94ac5bdd0", - "sha256:c18f70dc27cc5d236f10e7834236aff60aadc71346a5bc1f4f83a4b3abee6386", - "sha256:c5ed816632204a2fc9486d784d8e0d0ae754347aba99c811458d69fcdfd2a2f9", - "sha256:dc058b7833184970d1248135b8b0ab702e6daa833be14035179f2acb78ff5636", - "sha256:ff3797f2f16bf9d17d53257612da84dd0758db33935777149b3334c01ff68865" + "sha256:0295442429645fa16d05bd567ef5cff178482439c9aad0411d3f0ce9b88b3a6f", + "sha256:06aba4169e78c439d528fdeb34762c3b61a70813527a2c57f0540541e9f433a8", + "sha256:09d7f9e64289cb40c2c8d7ad674b2ed6105f55dc3b09aa8e4918e20a0311e7ad", + "sha256:0a80dd307a5d8440b0a08bd7b81617e04d870e40a3e46a32d9c246e54705e86f", + "sha256:1ca594126d3c4def54babee699c055a913efb01e106c309fa6b04405d474d5ae", + "sha256:25930fadde8019f374400f7986e8404c8b781ce519da27792cbe46eabec00c4d", + "sha256:431b15cffbf949e89df2f7b48528be18b78bfa5177cb3036284a5508159492b5", + "sha256:52125833b070791fcb5710fabc640fc1df07d087fc0c0f02d3661f76c23c5b8b", + "sha256:5e51ee2b8114def244384eda1c82b10e307ad9778dac5c83fb0943775a653cd8", + "sha256:612cfda94e9c8346f239bf1a4b082fdd5c8143cf82d685ba2dba76e7adeeb233", + "sha256:6d7741e65835716ceea0fd13a7d0192961212fd59e741a46bbed7a473c634ed6", + "sha256:6edb5446f44d901e8683ffb25ebdfc26988ee813da3bf91e12252b57ac163727", + "sha256:725aa6cfc66ce2857d585f06e9519a1cc0ef6d13f186ff3447ab6dff0a09bc7f", + "sha256:8dad18b69f710bf3a001d2bf3afab7c432785d94fcf819c16b5207b1cfd17d38", + "sha256:94cf49723928eb6070a892cb39d6c156f7b5a2db4e8971cb958f7b6b104fb4c4", + "sha256:97f9e7953a77d5a70f49b9a48da7776dc51e9b738151b22dacf101641594a626", + "sha256:9ad7f865eebde135d526bb3163d0b23ffff365cf87e767c649550964ad72785d", + "sha256:a060cf8aa332052df2158e5a119303965be92c3da6f2d93b6878f0ebca80b2f6", + "sha256:c79f9c5fb846285f943aafeafda3358992d64f0ef58566e23484132ecd8d7d63", + "sha256:c92302a33138409e8f1ad16731568c55c9053eee71bb05b6b744067e1b62380f", + "sha256:d08b23fdb388c0715990cbc06866db554e1822c4bdcf6d4166cf30ac82df8c41", + "sha256:d350f0f2c2421e65fbc62690f26b59b0bcda1b614beb318c81e38647e0f673a1", + "sha256:ec29604081f10f16a7aea809ad42e27764188fc258b02259a03a8ff7ded3808d", + "sha256:edf31f1150778abd4322444c393ab9c7bd2af271dd4dafb4208fb613b1f3cdc9", + "sha256:f7e30c27477dffc3e85c2463b3e649f751789e0f6c8456099eea7ddd53be4a8a", + "sha256:ffe538682dc19cc542ae7c3e504fdf54ca7f86fb8a135e59dd6bc8627eae6cce" ], "index": "pypi", - "version": "==7.0.0" + "version": "==7.2.0" }, "progressbar2": { "hashes": [ - "sha256:57594cc7ff7ff93138d6c09f650f9d31290b5d3bd1cf12339ced96a50c148749", - "sha256:ecf687696dd449067f69ef6730c4d4a0189db1f8d1aad9e376358354631d5b2c" + "sha256:13f228cf357f94cdef933c91c1e771e52e1b1931dbae48267be8fcdc2ae2ce36", + "sha256:27abf038efe5b1b5dd91ecc5f704bc88683c1e2a0b2c0fee04de80a648634a0c" ], - "version": "==3.51.3" + "version": "==3.51.4" }, "psutil": { "hashes": [ @@ -583,6 +593,7 @@ "sha256:e2d0c5b07c6fe5a87fa27b7855017edb0d52ee73b71e6ee368fae268605cc3f5", "sha256:f344ca230dd8e8d5eee16827596f1c22ec0876127c28e800d7ae20ed44c4b310" ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==5.7.0" }, "pybgpranking": { @@ -596,77 +607,80 @@ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.20" }, "pycryptodome": { "hashes": [ - "sha256:07024fc364869eae8d6ac0d316e089956e6aeffe42dbdcf44fe1320d96becf7f", - "sha256:09b6d6bcc01a4eb1a2b4deeff5aa602a108ec5aed8ac75ae554f97d1d7f0a5ad", - "sha256:0e10f352ccbbcb5bb2dc4ecaf106564e65702a717d72ab260f9ac4c19753cfc2", - "sha256:1f4752186298caf2e9ff5354f2e694d607ca7342aa313a62005235d46e28cf04", - "sha256:2fbc472e0b567318fe2052281d5a8c0ae70099b446679815f655e9fbc18c3a65", - "sha256:3ec3dc2f80f71fd0c955ce48b81bfaf8914c6f63a41a738f28885a1c4892968a", - "sha256:426c188c83c10df71f053e04b4003b1437bae5cb37606440e498b00f160d71d0", - "sha256:626c0a1d4d83ec6303f970a17158114f75c3ba1736f7f2983f7b40a265861bd8", - "sha256:767ad0fb5d23efc36a4d5c2fc608ac603f3de028909bcf59abc943e0d0bc5a36", - "sha256:7ac729d9091ed5478af2b4a4f44f5335a98febbc008af619e4569a59fe503e40", - "sha256:83295a3fb5cf50c48631eb5b440cb5e9832d8c14d81d1d45f4497b67a9987de8", - "sha256:8be56bde3312e022d9d1d6afa124556460ad5c844c2fc63642f6af723c098d35", - "sha256:8f06556a8f7ea7b1e42eff39726bb0dca1c251205debae64e6eebea3cd7b438a", - "sha256:9230fcb5d948c3fb40049bace4d33c5d254f8232c2c0bba05d2570aea3ba4520", - "sha256:9378c309aec1f8cd8bad361ed0816a440151b97a2a3f6ffdaba1d1a1fb76873a", - "sha256:9977086e0f93adb326379897437373871b80501e1d176fec63c7f46fb300c862", - "sha256:9a94fca11fdc161460bd8659c15b6adef45c1b20da86402256eaf3addfaab324", - "sha256:9c739b7795ccf2ef1fdad8d44e539a39ad300ee6786e804ea7f0c6a786eb5343", - "sha256:b1e332587b3b195542e77681389c296e1837ca01240399d88803a075447d3557", - "sha256:c109a26a21f21f695d369ff9b87f5d43e0d6c768d8384e10bc74142bed2e092e", - "sha256:c818dc1f3eace93ee50c2b6b5c2becf7c418fa5dd1ba6fc0ef7db279ea21d5e4", - "sha256:cff31f5a8977534f255f729d5d2467526f2b10563a30bbdade92223e0bf264bd", - "sha256:d4f94368ce2d65873a87ad867eb3bf63f4ba81eb97a9ee66d38c2b71ce5a7439", - "sha256:d61b012baa8c2b659e9890011358455c0019a4108536b811602d2f638c40802a", - "sha256:d6e1bc5c94873bec742afe2dfadce0d20445b18e75c47afc0c115b19e5dd38dd", - "sha256:ea83bcd9d6c03248ebd46e71ac313858e0afd5aa2fa81478c0e653242f3eb476", - "sha256:ed5761b37615a1f222c5345bbf45272ae2cf8c7dff88a4f53a1e9f977cbb6d95", - "sha256:f011cd0062e54658b7086a76f8cf0f4222812acc66e219e196ea2d0a8849d0ed", - "sha256:f1add21b6d179179b3c177c33d18a2186a09cc0d3af41ff5ed3f377360b869f2", - "sha256:f655addaaaa9974108d4808f4150652589cada96074c87115c52e575bfcd87d5" + "sha256:02e51e1d5828d58f154896ddfd003e2e7584869c275e5acbe290443575370fba", + "sha256:03d5cca8618620f45fd40f827423f82b86b3a202c8d44108601b0f5f56b04299", + "sha256:0e24171cf01021bc5dc17d6a9d4f33a048f09d62cc3f62541e95ef104588bda4", + "sha256:132a56abba24e2e06a479d8e5db7a48271a73a215f605017bbd476d31f8e71c1", + "sha256:1e655746f539421d923fd48df8f6f40b3443d80b75532501c0085b64afed9df5", + "sha256:2b998dc45ef5f4e5cf5248a6edfcd8d8e9fb5e35df8e4259b13a1b10eda7b16b", + "sha256:360955eece2cd0fa694a708d10303c6abd7b39614fa2547b6bd245da76198beb", + "sha256:39ef9fb52d6ec7728fce1f1693cb99d60ce302aeebd59bcedea70ca3203fda60", + "sha256:4350a42028240c344ee855f032c7d4ad6ff4f813bfbe7121547b7dc579ecc876", + "sha256:50348edd283afdccddc0938cdc674484533912ba8a99a27c7bfebb75030aa856", + "sha256:54bdedd28476dea8a3cd86cb67c0df1f0e3d71cae8022354b0f879c41a3d27b2", + "sha256:55eb61aca2c883db770999f50d091ff7c14016f2769ad7bca3d9b75d1d7c1b68", + "sha256:6276478ada411aca97c0d5104916354b3d740d368407912722bd4d11aa9ee4c2", + "sha256:67dcad1b8b201308586a8ca2ffe89df1e4f731d5a4cdd0610cc4ea790351c739", + "sha256:709b9f144d23e290b9863121d1ace14a72e01f66ea9c903fbdc690520dfdfcf0", + "sha256:8063a712fba642f78d3c506b0896846601b6de7f5c3d534e388ad0cc07f5a149", + "sha256:80d57177a0b7c14d4594c62bbb47fe2f6309ad3b0a34348a291d570925c97a82", + "sha256:a207231a52426de3ff20f5608f0687261a3329d97a036c51f7d4c606a6f30c23", + "sha256:abc2e126c9490e58a36a0f83516479e781d83adfb134576a5cbe5c6af2a3e93c", + "sha256:b56638d58a3a4be13229c6a815cd448f9e3ce40c00880a5398471b42ee86f50e", + "sha256:bcd5b8416e73e4b0d48afba3704d8c826414764dafaed7a1a93c442188d90ccc", + "sha256:bec2bcdf7c9ce7f04d718e51887f3b05dc5c1cfaf5d2c2e9065ecddd1b2f6c9a", + "sha256:c8bf40cf6e281a4378e25846924327e728a887e8bf0ee83b2604a0f4b61692e8", + "sha256:d8074c8448cfd0705dfa71ca333277fce9786d0b9cac75d120545de6253f996a", + "sha256:dd302b6ae3965afeb5ef1b0d92486f986c0e65183cd7835973f0b593800590e6", + "sha256:de6e1cd75677423ff64712c337521e62e3a7a4fc84caabbd93207752e831a85a", + "sha256:ef39c98d9b8c0736d91937d193653e47c3b19ddf4fc3bccdc5e09aaa4b0c5d21", + "sha256:f521178e5a991ffd04182ed08f552daca1affcb826aeda0e1945cd989a9d4345", + "sha256:f78a68c2c820e4731e510a2df3eef0322f24fde1781ced970bf497b6c7d92982", + "sha256:fbe65d5cfe04ff2f7684160d50f5118bdefb01e3af4718eeb618bfed40f19d94" ], - "version": "==3.9.7" + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==3.9.8" }, "pycryptodomex": { "hashes": [ - "sha256:1537d2d15b604b303aef56e7f440895a1c81adbee786b91f1f06eddc34da5314", - "sha256:1d20ab8369b7558168fc014a0745c678613f9f486dae468cca2d68145196b8a4", - "sha256:1ecc9db7409db67765eb008e558879d298406642d33ade43a6488224d23e8081", - "sha256:37033976f72af829fe15f7fe5fe1dbed308cc43a98d9dd9d2a0a76de8ca5ee78", - "sha256:3c3dd9d4c9c1e279d3945ae422895c901f98987333acc132dc094faf52afec35", - "sha256:3c9b3fba037ea52c626060c5a87ee6de7e86c99e8a7c6ee07302539985d2bd64", - "sha256:45ee555fc5e28c119a46d44ce373f5237e54a35c61b750fb3a94446b09855dbc", - "sha256:4c93038ac011b36512cb0bf2ee3e2aec774e8bc81021d015917c89fe02bb0ee5", - "sha256:50163324834edd0c9ce3e4512ded3e221c969086e10fdd5d3fdcaadac5e24a78", - "sha256:59b0ea9cda5490f924771456912a225d8d9e678891f9f986661af718534719b2", - "sha256:5cf306a17cccc327a33cdc3845629fa13f4573a4ec620ed607c79cf6785f2e27", - "sha256:5fff8da399af16a1855f58771223acbbdac720b9969cd03fc5013d2e9a7bd9a4", - "sha256:68650ce5b9f7152b8283302a4617269f821695a612692640dd247bd12ab21c0b", - "sha256:6b3a9a562688996f760b5077714c3ab8b62ca56061b6e9ab7906841e43e19f91", - "sha256:7e938ed51a59e29431ea86fab60423ada2757728db0f78952329fa02a789bd31", - "sha256:87aa70daad6f039e814790a06422a3189311198b674b62f13933a2bdcb6b1bcc", - "sha256:99be3a1df2b2b9f731ebe1c264a2c07c465e71cee68e35e1640b645b5213a755", - "sha256:a3f2908666e6f74b8c4893f86dd02e16170f50e4a78ae7f3468b6208d54bc205", - "sha256:ae3d44a639fd11dbdeca47e35e94febb1ee8bc15daf26673331add37146e0b85", - "sha256:afb4c2fa3c6f492fd9a8b38d76e13f32d429b8e5e1e00238309391b5591cde0d", - "sha256:b1515ce3a8a2c3fa537d137c5ca5f8b7a902044d04e07d7c3aa26c3e026120fb", - "sha256:bf391b377413a197000b43ef2b74359974d8927d329a897c9f5ba7b63dca7b9c", - "sha256:c436919117c23355740c669f89720673578b9aa4569bbfe105f6c10101fc1966", - "sha256:d2c3c280975638e2a2c2fd9cb36ab111980219757fa163a2755594b9448e4138", - "sha256:e585d530764c459cbd5d460aed0288807bb881f376ca9a20e653645217895961", - "sha256:e76e6638ead4a7d93262a24218f0ff3ff74de6b6c823b7e19dccb31b6a481978", - "sha256:ebfc2f885cafda076c31ae30fa0dd81e7e919ec34059a88d3018ed66e83fcce3", - "sha256:f5797a39933a3d41526da60856735e6684b2b71a8ca99d5f79555ca121be2f4b", - "sha256:f7e5fc5e124200b19a14be33fb0099e956e6ebb5e25d287b0829ef0a78ed76c7", - "sha256:fb350e31e55211fec8ddc89fc0256f3b9bc3b44b68a8bde1cf44b3b4e80c0e42" + "sha256:06f5a458624c9b0e04c0086c7f84bcc578567dab0ddc816e0476b3057b18339f", + "sha256:1714675fb4ac29a26ced38ca22eb8ffd923ac851b7a6140563863194d7158422", + "sha256:17272d06e4b2f6455ee2cbe93e8eb50d9450a5dc6223d06862ee1ea5d1235861", + "sha256:2199708ebeed4b82eb45b10e1754292677f5a0df7d627ee91ea01290b9bab7e6", + "sha256:2275a663c9e744ee4eace816ef2d446b3060554c5773a92fbc79b05bf47debda", + "sha256:2710fc8d83b3352b370db932b3710033b9d630b970ff5aaa3e7458b5336e3b32", + "sha256:35b9c9177a9fe7288b19dd41554c9c8ca1063deb426dd5a02e7e2a7416b6bd11", + "sha256:3caa32cf807422adf33c10c88c22e9e2e08b9d9d042f12e1e25fe23113dd618f", + "sha256:48cc2cfc251f04a6142badeb666d1ff49ca6fdfc303fd72579f62b768aaa52b9", + "sha256:4ae6379350a09339109e9b6f419bb2c3f03d3e441f4b0f5b8ca699d47cc9ff7e", + "sha256:4e0b27697fa1621c6d3d3b4edeec723c2e841285de6a8d378c1962da77b349be", + "sha256:58e19560814dabf5d788b95a13f6b98279cf41a49b1e49ee6cf6c79a57adb4c9", + "sha256:8044eae59301dd392fbb4a7c5d64e1aea8ef0be2540549807ecbe703d6233d68", + "sha256:89be1bf55e50116fe7e493a7c0c483099770dd7f81b87ac8d04a43b1a203e259", + "sha256:8fcdda24dddf47f716400d54fc7f75cadaaba1dd47cc127e59d752c9c0fc3c48", + "sha256:914fbb18e29c54585e6aa39d300385f90d0fa3b3cc02ed829b08f95c1acf60c2", + "sha256:93a75d1acd54efed314b82c952b39eac96ce98d241ad7431547442e5c56138aa", + "sha256:9fd758e5e2fe02d57860b85da34a1a1e7037155c4eadc2326fc7af02f9cae214", + "sha256:a2bc4e1a2e6ca3a18b2e0be6131a23af76fecb37990c159df6edc7da6df913e3", + "sha256:a2ee8ba99d33e1a434fcd27d7d0aa7964163efeee0730fe2efc9d60edae1fc71", + "sha256:b2d756620078570d3f940c84bc94dd30aa362b795cce8b2723300a8800b87f1c", + "sha256:c0d085c8187a1e4d3402f626c9e438b5861151ab132d8761d9c5ce6491a87761", + "sha256:c990f2c58f7c67688e9e86e6557ed05952669ff6f1343e77b459007d85f7df00", + "sha256:ccbbec59bf4b74226170c54476da5780c9176bae084878fc94d9a2c841218e34", + "sha256:dc2bed32c7b138f1331794e454a953360c8cedf3ee62ae31f063822da6007489", + "sha256:e070a1f91202ed34c396be5ea842b886f6fa2b90d2db437dc9fb35a26c80c060", + "sha256:e42860fbe1292668b682f6dabd225fbe2a7a4fa1632f0c39881c019e93dea594", + "sha256:e4e1c486bf226822c8dceac81d0ec59c0a2399dbd1b9e04f03c3efa3605db677", + "sha256:ea4d4b58f9bc34e224ef4b4604a6be03d72ef1f8c486391f970205f6733dbc46", + "sha256:f60b3484ce4be04f5da3777c51c5140d3fe21cdd6674f2b6568f41c8130bcdeb" ], - "version": "==3.9.7" + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==3.9.8" }, "pydeep": { "hashes": [ @@ -681,10 +695,11 @@ }, "pyeupi": { "hashes": [ - "sha256:35b0e6b430f23ecd303f7cc7a8fe5147cf2509a5b2254eaf9695392c0af02901" + "sha256:2309c61ac2ef0eafabd6e9f32a0078069ffbba0e113ebc6b51cffc1869094472", + "sha256:a0798a4a52601b0840339449a1bbf2aa2bc180d8f82a979022954e05fcb5bfba" ], "index": "pypi", - "version": "==1.0" + "version": "==1.1" }, "pygeoip": { "hashes": [ @@ -708,10 +723,12 @@ "pymisp": { "editable": true, "extras": [ - "fileobjects,openioc,virustotal,pdfexport" + "fileobjects", + "openioc", + "pdfexport" ], "git": "https://github.com/MISP/PyMISP.git", - "ref": "b5b40ae2c5225a4b349c26294cfc012309a61352" + "ref": "ec28820cf491ca7d385477996afa0547eb6b6830" }, "pyonyphe": { "editable": true, @@ -730,6 +747,7 @@ "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.4.7" }, "pypdns": { @@ -755,16 +773,17 @@ }, "pytesseract": { "hashes": [ - "sha256:1041f83ad3eed768df145d85275bb9a611861d31fcfe30aa4bfeb79d6529b452" + "sha256:afd8a5cdf8ab5d35690efbe71cbf5f89419f668ea8dde7649149815d5c5a899a" ], "index": "pypi", - "version": "==0.3.3" + "version": "==0.3.4" }, "python-dateutil": { "hashes": [ "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.8.1" }, "python-docx": { @@ -829,11 +848,11 @@ }, "pyzipper": { "hashes": [ - "sha256:e77164f37acee2160569896347dfca71f0f9b352c351dfa3981e1595a9ba0902", - "sha256:fb42f41525979ef9ddf8c2b1fdd8cb2216057d8cede250f21d469f0b269479cf" + "sha256:49813f1d415bdd7c87064009b9270c6dd0a96da770cfe57df2c6d2d84a6c085a", + "sha256:bfdc65f616278b38ef03c6ea5a1aca7499caf98cbfcd47fc44f73e68f4307145" ], "markers": "python_version >= '3.5'", - "version": "==0.3.1" + "version": "==0.3.3" }, "rdflib": { "hashes": [ @@ -844,67 +863,68 @@ }, "redis": { "hashes": [ - "sha256:2ef11f489003f151777c064c5dbc6653dfb9f3eade159bcadc524619fddc2242", - "sha256:6d65e84bc58091140081ee9d9c187aab0480097750fac44239307a3bdf0b1251" + "sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2", + "sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24" ], - "version": "==3.5.2" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==3.5.3" }, "reportlab": { "hashes": [ - "sha256:072da175f9586fd0457242d7eb4ccf8284b65f8c4ec33ec4fa39c511ca2c6e10", - "sha256:12b1deee658b6a9766e7aca061dfa52c396e984fb328178480ae11ff7717cda4", - "sha256:28c56f85900bc9632ac6c44f71629a34da3a7da0904a19ecbf69ea7aec976bf3", - "sha256:2ac6bf19ecc60149895273932910b7cde61bcfc6701326094078eee489265de5", - "sha256:31feebbfd476201e82aecf750201acb1ea7d3b29217d2e0ca0a297d1189a78af", - "sha256:330aa2b493c9a42b28c65b5b4c7de4c4f372b1292f082b1a097d56b12e2ba097", - "sha256:39ae8212a07a18f0e3ee0a3bca6e5a37abac470f934e5a1a117209f989618373", - "sha256:3af29daf6681fb1c6abbe8a948c6cdf241c7d9bcdce4b881076323e70b44865c", - "sha256:3d33f934e13263fac098672840f8e0959643b747a516a50792868c3ae7251c37", - "sha256:3ea95bcfcba08eb4030e3b62efc01ff9e547eea7887311f00685c729cabce038", - "sha256:45f4aab315f301b4c184f1ee5fb4234fd1388335b191cf827ea977a98b0158dc", - "sha256:497c8d56d2f98561b78d9e21d9a2a39ab9e2dd81db699f1cddcba744ba455330", - "sha256:4f4463f1591cf66996a292835f04a521470cf9a479724017a9227125f49f7492", - "sha256:553658b979b3e8dd662cd8c37d1955cc832b2c000f4cb6d076d8401d771dd85f", - "sha256:5a8430eed5fc7d15c868fdf5673c94440710e7d1a77ea5bbd4f634e3e6fb5f9c", - "sha256:5cc32b8ce94c9345fe59af2cbf47edb1c1615304b67f522957666485f87694f7", - "sha256:5d851a20981e6ea29b643e59807997ca96ceeded4bf431ba9618171d8e383091", - "sha256:64f7cfa75b9b9a1eebf2a3fe5667a01953e1cb8946b0d14f165b9381ec2fdbaf", - "sha256:650ec96cc3cb86ae27987db5d36abe530ef45ec67032c4633c776dd3ab016ca4", - "sha256:6771e0875203d130f1f9c9c04f26084178cb4720552580af8b393cf70c4943a5", - "sha256:67f5b94ba44a4e764974b0ee9d2f574c593c11ec1cb19aedd17a1bebc35a597e", - "sha256:6d6815a925c071a0b887c968d39527e9b3db962a151d2aabdd954beafd4431ad", - "sha256:6e6e3041b742a73c71c0dc49875524338998cbf6a498077e40d4589f8448f3ed", - "sha256:6fb58a2fdc725a601d225f377b3e1cc3837f8f560cc6c2ceeb8028010031fd65", - "sha256:7c36e52452147e64a48a05ac56340b45aa3f0c64f2b2e38145ea15190c369621", - "sha256:8194698254932234a1164694a5b8c84d8010db6ff71a8985c6133d21ed9767ea", - "sha256:9c21f202697a6cea57b9d716288fc919d99cbabeb30222eebfc7ff77eac32744", - "sha256:9ffbdbac35c084c2026c4d978498017b5433a61adfe6c1e500c506d38707b39c", - "sha256:ab6acd99073081d708339e26475e93fe48139233a2ab7f43fc54560e1e00155a", - "sha256:bd1c855249f5508a50e3ddc7b4e957e4a537597bd41e66e71bdc027bbcfa7534", - "sha256:c14de6b939ad2ea63e4149e3e4eae1089e20afae1ef805345f73193f25ac9e5f", - "sha256:cb24edd3e659c783abee1162559cc2a94537974fc73d73da7e3a7021b1ab9803", - "sha256:d144680292a868cbfe02db25eecbf53623af02e42ff05822439f1434156e7863", - "sha256:db5c44a77f10357f5c2c25545b7fbc009616274f9ac1876b00398693d0fc4324", - "sha256:e326b2d48ccaf17322f86c23cd78900e50facf27b93ce50e4a2902a5f31ac343", - "sha256:e6c3fc2866b853b6b9d4b5d79cfff89c5687fc70a155a05dcfdd278747d441db", - "sha256:ef817701f45bb6974cfc0a488fd9a76c4190948c456234490174d1f2112b0a2c", - "sha256:eff08b53ab4fa2adf4b763e56dd1369d6c1cb2a18d3daee7a5f53b25198c0a36", - "sha256:f18ad0212b7204f5fae37682ec4760a11e1130c294294cfcd900d202d90ed9d9", - "sha256:f7e4e8adc959dd65e127ae0865fb278d40b34ee2ae8e41e2c5fa8dc83cea273b" + "sha256:0f0c2d98e213d51ae527c0301364d3376cb05f6c47251368a9abd4c3197fcefa", + "sha256:1425c7ea60b8691a881ae21ea0f6907a1dc480d84204ccbfea6da41fbee8f594", + "sha256:204f1d245875ab3d076b37c1a18ac8d2e3222842e13cfa282bcd95282be239e5", + "sha256:21627b57249303bf9b5a633099d058ae9f8625fd6f90cfe79348c48fd5a242cd", + "sha256:2e8e3242f80b79f2470f1b5979abbdb41f31b1333543b830749100342f837d40", + "sha256:2eced06dec3f36135c626b9823649ef9cac95c5634d1bc743a15ee470027483b", + "sha256:3472aa0b74a3b2f252dce823f3c3ba6af8a24de0c1729441deaaf50bed6de9f9", + "sha256:3f0353ffefd3afc0061f4794ef608d6c6f32e69816885f4d45c625c20d8eaf5b", + "sha256:4a9f4540a8eddf56d900ceeb8136bd0ca866c208ba3dcbcde73f07405dbadfba", + "sha256:4eea1afb4aa89780734f44175508edff82928fdf460c9bd60bc719dd99041dc3", + "sha256:5803ffebd36de1ada417f50ce65d379ea5a0bf1a2e8f5d5710a031b3b349b726", + "sha256:58f5f72fc8e5932dedcf24789908a81c6b1e13ea4d63bd9a9a39dc698d8c3321", + "sha256:5b588e5f251c76a8d3589023d1c369c7968e0efe2b38ad5948f665edbf6f9e8b", + "sha256:5d922768fe11a58d80694852aba7389d613c15eb1871c5581a2f075996873d57", + "sha256:5d98f297c5cdd5bc0ccf5697c20b03602ee3378c97938d20312662b27cd9a1d6", + "sha256:66d1d96e97a562614943ecb9daf438e392b3d0b033bd5f4a8098ab616dd877da", + "sha256:670650970c7ba7164cf6340bcd182e7e933eff5d65183af98ee77b40cc25a438", + "sha256:67bb95af7bc8ad7925d299f310d15d556d3e7026fe1b60d8e290454604ae0a85", + "sha256:9c999f5d1a600c4970ba293789b6da14e02e3763a8d3d9abe42dcafa8a5318e9", + "sha256:9d62bef5347063a984e63410fa5a69f1d2cc2fdf8d6ed3d0b9d4ea2ccb4b4154", + "sha256:a14a0d603727b6be2e549c52dd42678ab2d06d2721d4580199e3161843e59298", + "sha256:a3a17b46ff1a15eb29370e11796d8914ef4ea67471bdbc4aa9a9eb9284f4e44c", + "sha256:a6d3e20beeba3fd68cec73b8c0785bfa648c06ac76d1f142c60ccb1a8d2506b6", + "sha256:ad7d7003c732f2be42580e3906e92bd9d2aca5e098898c597554be9ca627fad5", + "sha256:af0ee7b50b85543b68b043e61271963ff5671e564e1d620a404c24a24d4f537c", + "sha256:b3eec55274f5ead7e3af2bf0c01b481ffe1b4c6a7dae42b63d85543e9f2f9a0f", + "sha256:b48c21d43a7ab956954591ce3f71db92ce542bb7428db09734425e2b77ac3142", + "sha256:b761905ab85beb79cf7929c9a019f30ad65664e5733d57a30a995e7b9bef06d1", + "sha256:bbae2f054d0f234c3382076efa337802997aca0f3f664e314f65eefb9d694fa9", + "sha256:bd4157d0bc40fb72bb676fc745fdd648022cccaf4ccfbb291af7f48831d0d5d9", + "sha256:bf74cfabf332034f42a54938eb335543cbf92790170300dbe236ba83b7601cd0", + "sha256:c253c8571db2df3886e390a2bfbe917222953054f4643437373b824f64b013cd", + "sha256:ce1277a6acbc62e9966f410f2596ac533ee0cd5df9b69d5fe4406338a169b7d8", + "sha256:ce8f56987e0e456063e311f066a81496b8b9626c846f2cb0ebb554d1a5f40839", + "sha256:d6264a0589ba8032d9c3bdca9a3e87a897ede09b7f6a8ad5e83b57573212e01e", + "sha256:e6fa0c97e3929d00db27e8cf3b2b5771e94f5f179086c4b0e3213dff53637372", + "sha256:f0930f2b6dddd477b3331ec670171a4662336aac1a778e1a30e980a5cbf40b17", + "sha256:f8cb2b4b925ca6b6e4fdefd288a707776ac686c45034f34d4c952f122d11c40b", + "sha256:f9b71539f518323d95850405c49c01fc3d2f0f0b9f3e157de6d2786804fb28a4", + "sha256:fc488e661f99c915362e0373218f8727cecf888eb1b0eb3a8fe1af624a1b9776" ], "index": "pypi", - "version": "==3.5.42" + "version": "==3.5.44" }, "requests": { "extras": [ "security" ], "hashes": [ - "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee", - "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6" + "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b", + "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898" ], "index": "pypi", - "version": "==2.23.0" + "version": "==2.24.0" }, "requests-cache": { "hashes": [ @@ -915,25 +935,26 @@ }, "shodan": { "hashes": [ - "sha256:a9f098c2d24cf685b6d4a4bd46c7f56653c84f777f20d1a853cfd7672f68f35d" + "sha256:31b0740ffaf7c5196a26a0b1edf7d271dffe54ea52bb1b34ba87aa231b5c339b" ], "index": "pypi", - "version": "==1.22.0" + "version": "==1.23.0" }, "sigmatools": { "hashes": [ - "sha256:6b28b30efbaa5cbb967927ea4e31c617cc91a210aad6e0a00cbe11d4ea48c3cd", - "sha256:85dfae6479d245e7e7936f02d754954ea16e2c2f757035d0b329571fa048febc" + "sha256:5453717e452aa7860c5e6ac80bcee4f398d70956fc2ee9859bc7255067da8736", + "sha256:cdfeb8200c09c0a40ea1a015e57f3b8e2ba62a28352ca05fa015674f640871e3" ], "index": "pypi", - "version": "==0.16.0" + "version": "==0.17.0" }, "six": { "hashes": [ - "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", - "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" + "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", + "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" ], - "version": "==1.14.0" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.15.0" }, "socketio-client": { "hashes": [ @@ -946,11 +967,14 @@ "sha256:1634eea42ab371d3d346309b93df7870a88610f0725d47528be902a0d95ecc55", "sha256:a59dc181727e95d25f781f0eb4fd1825ff45590ec8ff49eadfd7f1a537cc0232" ], + "markers": "python_version >= '3.5'", "version": "==2.0.1" }, "sparqlwrapper": { "hashes": [ + "sha256:17ec44b08b8ae2888c801066249f74fe328eec25d90203ce7eadaf82e64484c7", "sha256:357ee8a27bc910ea13d77836dbddd0b914991495b8cc1bf70676578155e962a8", + "sha256:8cf6c21126ed76edc85c5c232fd6f77b9f61f8ad1db90a7147cdde2104aff145", "sha256:c7f9c9d8ebb13428771bc3b6dee54197422507dcc3dea34e30d5dcfc53478dec", "sha256:d6a66b5b8cda141660e07aeb00472db077a98d22cb588c973209c7336850fb3c" ], @@ -984,13 +1008,35 @@ "sha256:c952975c8ba74f546ae6de2e226ab3cc3cc11ae47baf607459a6728585bb542a", "sha256:c98232a3ac391f5faea6821b53db8db461157baa788f5d6222a193e9456e1740" ], + "markers": "python_version >= '3.5'", "version": "==6.0.4" }, + "trustar": { + "hashes": [ + "sha256:73336b94012427b66ee61db65fc3c2cea2ed743beaa56cdd5a4c1674ef1a7660" + ], + "index": "pypi", + "version": "==0.3.29" + }, + "tzlocal": { + "hashes": [ + "sha256:643c97c5294aedc737780a49d9df30889321cbe1204eac2c2ec6134035a92e44", + "sha256:e2cb6c6b5b604af38597403e9852872d7f534962ae2954c7f35efcb1ccacf4a4" + ], + "version": "==2.1" + }, + "unicodecsv": { + "hashes": [ + "sha256:018c08037d48649a0412063ff4eda26eaa81eff1546dbffa51fa5293276ff7fc" + ], + "version": "==0.14.1" + }, "url-normalize": { "hashes": [ "sha256:1709cb4739e496f9f807a894e361915792f273538e250b1ab7da790544a665c3", "sha256:1bd7085349dcdf06e52194d0f75ff99fff2eeed0da85a50e4cc2346452c1b8bc" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", "version": "==1.4.2" }, "urlarchiver": { @@ -1005,12 +1051,13 @@ "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527", "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", "version": "==1.25.9" }, "uwhois": { "editable": true, "git": "https://github.com/Rafiot/uwhoisd.git", - "ref": "411572840eba4c72dc321c549b36a54ed5cea9de", + "ref": "783bba09b5a6964f25566089826a1be4b13f2a22", "subdirectory": "client" }, "validators": { @@ -1038,11 +1085,11 @@ }, "wand": { "hashes": [ - "sha256:598e13e46779e48fcecba7b37fd9d61fcdd1e70007ccba5d5b2e731186a2ec2e", - "sha256:6eaca78e53fbe329b163f0f0b28f104de98edbd69a847268cc5d6a6e392b9b28" + "sha256:d5b75ac13d7485032970926415648586eafeeb1eb62ed6ebd0778358cf9d70e0", + "sha256:df0780b1b54938a43d29279a6588fde11e349550c8958a673d57c26a3e6de7f1" ], "index": "pypi", - "version": "==0.5.9" + "version": "==0.6.1" }, "websocket-client": { "hashes": [ @@ -1067,10 +1114,10 @@ }, "xlsxwriter": { "hashes": [ - "sha256:488e1988ab16ff3a9cd58c7656d0a58f8abe46ee58b98eecea78c022db28656b", - "sha256:97ab487b81534415c5313154203f3e8a637d792b1e6a8201e8f7f71da0203c2a" + "sha256:828b3285fc95105f5b1946a6a015b31cf388bd5378fdc6604e4d1b7839df2e77", + "sha256:82a3b0e73e3913483da23791d1a25e4d2dbb3837d1be4129473526b9a270a5cc" ], - "version": "==1.2.8" + "version": "==1.2.9" }, "yara-python": { "hashes": [ @@ -1109,6 +1156,7 @@ "sha256:d8cdee92bc930d8b09d8bd2043cedd544d9c8bd7436a77678dd602467a993080", "sha256:e15199cdb423316e15f108f51249e44eb156ae5dba232cb73be555324a1d49c2" ], + "markers": "python_version >= '3.5'", "version": "==1.4.2" } }, @@ -1118,14 +1166,15 @@ "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==19.3.0" }, "certifi": { "hashes": [ - "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304", - "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519" + "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3", + "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41" ], - "version": "==2020.4.5.1" + "version": "==2020.6.20" }, "chardet": { "hashes": [ @@ -1136,11 +1185,12 @@ }, "codecov": { "hashes": [ - "sha256:09fb045eb044a619cd2b9dacd7789ae8e322cb7f18196378579fd8d883e6b665", - "sha256:aeeefa3a03cac8a78e4f988e935b51a4689bb1f17f20d4e827807ee11135f845" + "sha256:491938ad774ea94a963d5d16354c7299e90422a33a353ba0d38d0943ed1d5091", + "sha256:b67bb8029e8340a7bf22c71cbece5bd18c96261fdebc2f105ee4d5a005bc8728", + "sha256:d8b8109f44edad03b24f5f189dac8de9b1e3dc3c791fa37eeaf8c7381503ec34" ], "index": "pypi", - "version": "==2.0.22" + "version": "==2.1.7" }, "coverage": { "hashes": [ @@ -1176,29 +1226,24 @@ "sha256:e1ea316102ea1e1770724db01998d1603ed921c54a86a2efcb03428d5417e489", "sha256:f90bfc4ad18450c80b024036eaf91e4a246ae287701aaa88eaebebf150868052" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", "version": "==5.1" }, - "entrypoints": { - "hashes": [ - "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", - "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451" - ], - "version": "==0.3" - }, "flake8": { "hashes": [ - "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb", - "sha256:49356e766643ad15072a789a20915d3c91dc89fd313ccd71802303fd67e4deca" + "sha256:15e351d19611c887e482fb960eae4d44845013cc142d42896e9862f775d8cf5c", + "sha256:f04b9fcbac03b0a3e58c0ab3a0ecc462e023a9faf046d57794184028123aa208" ], "index": "pypi", - "version": "==3.7.9" + "version": "==3.8.3" }, "idna": { "hashes": [ - "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb", - "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa" + "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", + "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" ], - "version": "==2.9" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.10" }, "mccabe": { "hashes": [ @@ -1209,10 +1254,11 @@ }, "more-itertools": { "hashes": [ - "sha256:558bb897a2232f5e4f8e2399089e35aecb746e1f9191b6584a151647e89267be", - "sha256:7818f596b1e87be009031c7653d01acc46ed422e6656b394b0f765ce66ed4982" + "sha256:68c70cc7167bdf5c7c9d8f6954a7837089c6a36bf565383919bb595efb8a17e5", + "sha256:b78134b2063dd214000685165d81c154522c3ee0a1c0d4d113c80361c234c5a2" ], - "version": "==8.3.0" + "markers": "python_version >= '3.5'", + "version": "==8.4.0" }, "nose": { "hashes": [ @@ -1228,6 +1274,7 @@ "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8", "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==20.4" }, "pluggy": { @@ -1235,75 +1282,82 @@ "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.13.1" }, "py": { "hashes": [ - "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa", - "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0" + "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2", + "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342" ], - "version": "==1.8.1" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.9.0" }, "pycodestyle": { "hashes": [ - "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", - "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" + "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367", + "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e" ], - "version": "==2.5.0" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.6.0" }, "pyflakes": { "hashes": [ - "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", - "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2" + "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92", + "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8" ], - "version": "==2.1.1" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.2.0" }, "pyparsing": { "hashes": [ "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.4.7" }, "pytest": { "hashes": [ - "sha256:0e5b30f5cb04e887b91b1ee519fa3d89049595f428c1db76e73bd7f17b09b172", - "sha256:84dde37075b8805f3d1f392cc47e38a0e59518fb46a431cfdaf7cf1ce805f970" + "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1", + "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8" ], "index": "pypi", - "version": "==5.4.1" + "version": "==5.4.3" }, "requests": { "extras": [ "security" ], "hashes": [ - "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee", - "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6" + "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b", + "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898" ], "index": "pypi", - "version": "==2.23.0" + "version": "==2.24.0" }, "six": { "hashes": [ - "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", - "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" + "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", + "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" ], - "version": "==1.14.0" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.15.0" }, "urllib3": { "hashes": [ "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527", "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", "version": "==1.25.9" }, "wcwidth": { "hashes": [ - "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1", - "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1" + "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784", + "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83" ], - "version": "==0.1.9" + "version": "==0.2.5" } } } From 8e4c688dcef5e1ee9808f29fa77b32ec3f45ef51 Mon Sep 17 00:00:00 2001 From: chrisr3d Date: Fri, 3 Jul 2020 10:10:24 +0200 Subject: [PATCH 18/30] fix: Fixed list of sigma backends --- misp_modules/modules/expansion/sigma_queries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misp_modules/modules/expansion/sigma_queries.py b/misp_modules/modules/expansion/sigma_queries.py index b7c871d..d17a100 100644 --- a/misp_modules/modules/expansion/sigma_queries.py +++ b/misp_modules/modules/expansion/sigma_queries.py @@ -12,7 +12,7 @@ mispattributes = {'input': ['sigma'], 'output': ['text']} moduleinfo = {'version': '0.1', 'author': 'Christian Studer', 'module-type': ['expansion', 'hover'], 'description': 'An expansion hover module to display the result of sigma queries.'} moduleconfig = [] -sigma_targets = ('es-dsl', 'es-qs', 'graylog', 'kibana', 'xpack-watcher', 'logpoint', 'splunk', 'grep', 'wdatp', 'splunkxml', 'arcsight', 'qualys') +sigma_targets = ('es-dsl', 'es-qs', 'graylog', 'kibana', 'xpack-watcher', 'logpoint', 'splunk', 'grep', 'mdatp', 'splunkxml', 'arcsight', 'qualys') def handler(q=False): From c91a61110a125bf7fd9369221339694b11011847 Mon Sep 17 00:00:00 2001 From: johannesh Date: Thu, 23 Jul 2020 12:28:56 +0200 Subject: [PATCH 19/30] Add Recorded Future expansion module --- README.md | 1 + misp_modules/modules/expansion/__init__.py | 2 +- .../modules/expansion/recordedfuture.py | 280 ++++++++++++++++++ 3 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 misp_modules/modules/expansion/recordedfuture.py diff --git a/README.md b/README.md index 67573da..77ece38 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ For more information: [Extending MISP with Python modules](https://www.misp-proj * [pptx-enrich](misp_modules/modules/expansion/pptx_enrich.py) - an enrichment module to get text out of PowerPoint document into MISP (using free-text parser). * [qrcode](misp_modules/modules/expansion/qrcode.py) - a module decode QR code, barcode and similar codes from an image and enrich with the decoded values. * [rbl](misp_modules/modules/expansion/rbl.py) - a module to get RBL (Real-Time Blackhost List) values from an attribute. +* [recordedfuture](misp_modules/modules/expansion/recordedfuture.py) - a hover and expansion module for enriching MISP attributes with threat intelligence from Recorded Future. * [reversedns](misp_modules/modules/expansion/reversedns.py) - Simple Reverse DNS expansion service to resolve reverse DNS from MISP attributes. * [securitytrails](misp_modules/modules/expansion/securitytrails.py) - an expansion module for [securitytrails](https://securitytrails.com/). * [shodan](misp_modules/modules/expansion/shodan.py) - a minimal [shodan](https://www.shodan.io/) expansion module. diff --git a/misp_modules/modules/expansion/__init__.py b/misp_modules/modules/expansion/__init__.py index dbd3473..14d5499 100644 --- a/misp_modules/modules/expansion/__init__.py +++ b/misp_modules/modules/expansion/__init__.py @@ -18,4 +18,4 @@ __all__ = ['cuckoo_submit', 'vmray_submit', 'bgpranking', 'circl_passivedns', 'c 'virustotal_public', 'apiosintds', 'urlscan', 'securitytrails', 'apivoid', 'assemblyline_submit', 'assemblyline_query', 'ransomcoindb', 'malwarebazaar', 'lastline_query', 'lastline_submit', 'sophoslabs_intelix', 'cytomic_orion', 'censys_enrich', - 'trustar_enrich'] + 'trustar_enrich', 'recordedfuture'] diff --git a/misp_modules/modules/expansion/recordedfuture.py b/misp_modules/modules/expansion/recordedfuture.py new file mode 100644 index 0000000..c42a42b --- /dev/null +++ b/misp_modules/modules/expansion/recordedfuture.py @@ -0,0 +1,280 @@ +import json +import logging +import requests +from urllib.parse import quote +from pymisp import MISPAttribute, MISPEvent, MISPTag, MISPObject + +moduleinfo = {'version': '1.0', 'author': 'Recorded Future', + 'description': 'Module to retrieve data from Recorded Future', + 'module-type': ['expansion', 'hover']} + +moduleconfig = ['token'] + +misperrors = {'error': 'Error'} + +mispattributes = {'input': ['ip', 'ip-src', 'ip-dst', 'domain', 'hostname', 'md5', 'sha1', 'sha256', + 'uri', 'url', 'vulnerability', 'weakness'], + 'output': ['ip', 'ip-src', 'ip-dst', 'domain', 'hostname', 'md5', 'sha1', 'sha256', + 'uri', 'url', 'vulnerability', 'weakness', 'email-src', 'text'], + 'format': 'misp_standard'} + +LOGGER = logging.getLogger('recorded_future') +LOGGER.setLevel(logging.INFO) + + +def rf_lookup(api_token: str, category: str, ioc: str) -> requests.Response: + """Do a lookup call using Recorded Future's ConnectAPI.""" + auth_header = {"X-RFToken": api_token} + parsed_ioc = quote(ioc, safe='') + url = f'https://api.recordedfuture.com/v2/{category}/{parsed_ioc}?fields=risk%2CrelatedEntities' + response = requests.get(url, headers=auth_header) + response.raise_for_status() + return response + + +class GalaxyFinder: + """A class for finding MISP galaxy matches to Recorded Future data.""" + def __init__(self): + self.session = requests.Session() + self.sources = { + 'RelatedThreatActor': ['https://raw.githubusercontent.com/MISP/misp-galaxy/' + 'main/clusters/threat-actor.json'], + 'RelatedMalware': ['https://raw.githubusercontent.com/MISP/misp-galaxy/main/clusters/banker.json', + 'https://raw.githubusercontent.com/MISP/misp-galaxy/main/clusters/botnet.json', + 'https://raw.githubusercontent.com/MISP/misp-galaxy/main/clusters/exploit-kit.json', + 'https://raw.githubusercontent.com/MISP/misp-galaxy/main/clusters/rat.json', + 'https://raw.githubusercontent.com/MISP/misp-galaxy/main/clusters/ransomware.json', + 'https://raw.githubusercontent.com/MISP/misp-galaxy/main/clusters/malpedia.json'] + } + self.galaxy_clusters = {} + + def pull_galaxy_cluster(self, related_type: str): + """Fetches galaxy clusters for the related_type from the remote json files specified as self.sources.""" + # Only fetch clusters if not fetched previously + if not self.galaxy_clusters.get(related_type): + for source in self.sources.get(related_type): + response = self.session.get(source) + if response.ok: + name = source.split('/')[-1].split('.')[0] + self.galaxy_clusters[related_type] = {name: response.json()} + else: + LOGGER.info(f'pull_galaxy_cluster failed for source: {source},' + f' got response: {response}, {response.reason}.') + + def find_galaxy_match(self, indicator: str, related_type: str) -> str: + """Searches the clusters of the related_type for a match with the indicator. + :returns the first matching galaxy string or an empty string if no galaxy match is found. + """ + self.pull_galaxy_cluster(related_type) + try: + for cluster_name, cluster in self.galaxy_clusters[related_type].items(): + for value in cluster['values']: + try: + if indicator in value['meta']['synonyms'] or indicator in value['value']: + value = value['value'] + return f'misp-galaxy:{cluster_name}="{value}"' + except KeyError: + pass + except KeyError: + pass + return '' + + +class RFColors: + """Class for setting signature RF-colors.""" + def __init__(self): + self.rf_white = '#CCCCCC' + self.rf_yellow = '#FFCE00' + self.rf_red = '#CF0A2C' + + def riskscore_color(self, risk_score: int) -> str: + """Returns appropriate hex-colors according to risk score.""" + risk_score = int(risk_score) + if risk_score < 25: + return self.rf_white + elif risk_score < 65: + return self.rf_yellow + else: + return self.rf_red + + def riskrule_color(self, risk_rule_criticality: int) -> str: + """Returns appropriate hex-colors according to risk rule criticality.""" + risk_rule_criticality = int(risk_rule_criticality) + if risk_rule_criticality == 1: + return self.rf_white + elif risk_rule_criticality == 2: + return self.rf_yellow + else: # risk_rule_criticality == 3 or 4 + return self.rf_red + + +class RFEnricher: + """Class for enriching an attribute with data from Recorded Future. + The enrichment data is returned as a custom MISP object. + """ + def __init__(self, api_token: str, attribute_props: dict): + self.api_token = api_token + self.event = MISPEvent() + self.enrichment_object = MISPObject('Recorded Future Enrichment') + self.enrichment_object.from_dict(**{'meta-category': 'misc', + 'description': 'An object containing the enriched attribute and related ' + 'entities from Recorded Future.', + 'distribution': 0}) + + # Create a copy of enriched attribute to add tags to + temp_attr = MISPAttribute() + temp_attr.from_dict(**attribute_props) + self.enriched_attribute = MISPAttribute() + self.enriched_attribute.from_dict(**{'value': temp_attr.value, 'type': temp_attr.type, 'distribution': 0}) + + self.related_attributes = [] + self.color_picker = RFColors() + self.galaxy_finder = GalaxyFinder() + + # Mapping from MISP-type to RF-type + self.type_to_rf_category = {'ip': 'ip', 'ip-src': 'ip', 'ip-dst': 'ip', + 'domain': 'domain', 'hostname': 'domain', + 'md5': 'hash', 'sha1': 'hash', 'sha256': 'hash', + 'uri': 'url', 'url': 'url', + 'vulnerability': 'vulnerability', 'weakness': 'vulnerability'} + + # Related entities from RF portrayed as related attributes in MISP + self.related_attribute_types = ['RelatedIpAddress', 'RelatedInternetDomainName', 'RelatedHash', + 'RelatedEmailAddress', 'RelatedCyberVulnerability'] + # Related entities from RF portrayed as tags in MISP + self.galaxy_tag_types = ['RelatedMalware', 'RelatedThreatActor'] + + def enrich(self): + """Run the enrichment.""" + category = self.type_to_rf_category.get(self.enriched_attribute.type) + + try: + response = rf_lookup(self.api_token, category, self.enriched_attribute.value) + json_response = json.loads(response.content) + except requests.HTTPError as error: + misperrors['error'] = f'Error when requesting data from Recorded Future. ' \ + f'{error.response} : {error.response.reason}' + raise error + + try: + # Add risk score and risk rules as tags to the enriched attribute + risk_score = json_response['data']['risk']['score'] + hex_color = self.color_picker.riskscore_color(risk_score) + tag_name = f'recorded-future:risk-score="{risk_score}"' + self.add_tag(tag_name, hex_color) + for evidence in json_response['data']['risk']['evidenceDetails']: + risk_rule = evidence['rule'] + criticality = evidence['criticality'] + hex_color = self.color_picker.riskrule_color(criticality) + tag_name = f'recorded-future:risk-rule="{risk_rule}"' + self.add_tag(tag_name, hex_color) + + # Retrieve related entities + for related_entity in json_response['data']['relatedEntities']: + related_type = related_entity['type'] + if related_type in self.related_attribute_types: + # Related entities returned as additional attributes + for related in related_entity['entities']: + if int(related["count"]) > 4: + indicator = related['entity']['name'] + self.add_related_attribute(indicator, related_type) + elif related_type in self.galaxy_tag_types: + # Related entities added as galaxy-tags to the enriched attribute + galaxy_tags = [] + for related in related_entity['entities']: + if int(related["count"]) > 4: + indicator = related['entity']['name'] + galaxy = self.galaxy_finder.find_galaxy_match(indicator, related_type) + # Handle deduplication of galaxy tags + if galaxy and galaxy not in galaxy_tags: + galaxy_tags.append(galaxy) + for galaxy in galaxy_tags: + self.add_tag(galaxy) + except KeyError as error: + misperrors['error'] = 'Unexpected format in Recorded Future api response.' + raise error + + def add_related_attribute(self, indicator: str, related_type: str) -> None: + """Helper method for adding an indicator to the related attribute list.""" + out_type = self.get_output_type(related_type, indicator) + attribute = MISPAttribute() + attribute.from_dict(**{'value': indicator, 'type': out_type, 'distribution': 0}) + self.related_attributes.append((related_type, attribute)) + + def add_tag(self, tag_name: str, hex_color: str = None) -> None: + """Helper method for adding a tag to the enriched attribute.""" + tag = MISPTag() + tag_properties = {'name': tag_name} + if hex_color: + tag_properties['colour'] = hex_color + tag.from_dict(**tag_properties) + self.enriched_attribute.add_tag(tag) + + def get_output_type(self, related_type: str, indicator: str) -> str: + """Helper method for translating a Recorded Future related type to a MISP output type.""" + output_type = 'text' + if related_type == 'RelatedIpAddress': + output_type = 'ip-dst' + elif related_type == 'RelatedInternetDomainName': + output_type = 'domain' + elif related_type == 'RelatedHash': + hash_len = len(indicator) + if hash_len == 64: + output_type = 'sha256' + elif hash_len == 40: + output_type = 'sha1' + elif hash_len == 32: + output_type = 'md5' + elif related_type == 'RelatedEmailAddress': + output_type = 'email-src' + elif related_type == 'RelatedCyberVulnerability': + signature = indicator.split('-')[0] + if signature == 'CVE': + output_type = 'vulnerability' + elif signature == 'CWE': + output_type = 'weakness' + return output_type + + def get_results(self) -> dict: + """Build and return the enrichment results.""" + self.enrichment_object.add_attribute('Enriched attribute', **self.enriched_attribute) + for related_type, attribute in self.related_attributes: + self.enrichment_object.add_attribute(related_type, **attribute) + self.event.add_object(**self.enrichment_object) + event = json.loads(self.event.to_json()) + result = {key: event[key] for key in ['Object'] if key in event} + return {'results': result} + + +def handler(q=False): + """Handle enrichment.""" + if q is False: + return False + request = json.loads(q) + + if request.get('config') and request['config'].get('token'): + token = request['config'].get('token') + else: + misperrors['error'] = 'Missing Recorded Future token.' + return misperrors + + input_attribute = request.get('attribute') + rf_enricher = RFEnricher(token, input_attribute) + try: + rf_enricher.enrich() + except (requests.HTTPError, KeyError): + return misperrors + + return rf_enricher.get_results() + + +def introspection(): + """Returns a dict of the supported attributes.""" + return mispattributes + + +def version(): + """Returns a dict with the version and the associated meta-data + including potential configurations required of the module.""" + moduleinfo['config'] = moduleconfig + return moduleinfo From 8180ecbfa80a9cac3fd5ff9601b00ff913fdc98b Mon Sep 17 00:00:00 2001 From: chrisr3d Date: Mon, 27 Jul 2020 17:20:36 +0200 Subject: [PATCH 20/30] chg: Making use of the Greynoise v2 API --- misp_modules/modules/expansion/greynoise.py | 56 +++++++++++++++------ 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/misp_modules/modules/expansion/greynoise.py b/misp_modules/modules/expansion/greynoise.py index dd54158..4cd89d5 100644 --- a/misp_modules/modules/expansion/greynoise.py +++ b/misp_modules/modules/expansion/greynoise.py @@ -3,35 +3,59 @@ import json misperrors = {'error': 'Error'} mispattributes = {'input': ['ip-dst', 'ip-src'], 'output': ['text']} -moduleinfo = {'version': '0.1', 'author': 'AurĆ©lien Schwab ', 'description': 'Module to access GreyNoise.io API.', 'module-type': ['hover']} -moduleconfig = ['user-agent'] # TODO take this into account in the code +moduleinfo = { + 'version': '0.2', + 'author': 'AurĆ©lien Schwab ', + 'description': 'Module to access GreyNoise.io API.', + 'module-type': ['hover'] +} +moduleconfig = ['api_key'] -greynoise_api_url = 'http://api.greynoise.io:8888/v1/query/ip' -default_user_agent = 'MISP-Module' +greynoise_api_url = 'https://api.greynoise.io/v2/noise/quick/' +codes_mapping = { + '0x00': 'The IP has never been observed scanning the Internet', + '0x01': 'The IP has been observed by the GreyNoise sensor network', + '0x02': 'The IP has been observed scanning the GreyNoise sensor network, but has not completed a full connection, meaning this can be spoofed', + '0x03': 'The IP is adjacent to another host that has been directly observed by the GreyNoise sensor network', + '0x04': 'Reserved', + '0x05': 'This IP is commonly spoofed in Internet-scan activity', + '0x06': 'This IP has been observed as noise, but this host belongs to a cloud provider where IPs can be cycled frequently', + '0x07': 'This IP is invalid', + '0x08': 'This IP was classified as noise, but has not been observed engaging in Internet-wide scans or attacks in over 60 days' +} def handler(q=False): if q is False: return False request = json.loads(q) + if not request.get('config') or not request['config'].get('api_key'): + return {'error': 'Missing Greynoise API key.'} + headers = { + 'Accept': 'application/json', + 'key': request['config']['api_key'] + } for input_type in mispattributes['input']: if input_type in request: ip = request[input_type] break else: - misperrors['error'] = "Unsupported attributes type" + misperrors['error'] = "Unsupported attributes type." return misperrors - data = {'ip': ip} - r = requests.post(greynoise_api_url, data=data, headers={'user-agent': default_user_agent}) # Real request - if r.status_code == 200: # OK (record found) - response = r.text - if response: - return {'results': [{'types': mispattributes['output'], 'values': response}]} - elif r.status_code == 404: # Not found (not an error) - return {'results': [{'types': mispattributes['output'], 'values': 'No data'}]} - else: # Real error - misperrors['error'] = 'GreyNoise API not accessible (HTTP ' + str(r.status_code) + ')' - return misperrors['error'] + response = requests.get(f'{greynoise_api_url}{ip}', headers=headers) # Real request + if response.status_code == 200: # OK (record found) + return {'results': [{'types': mispattributes['output'], 'values': codes_mapping[response.json()['code']]}]} + # There is an error + errors = { + 400: "Bad request.", + 401: "Unauthorized. Please check your API key.", + 429: "Too many requests. You've hit the rate-limit." + } + try: + misperrors['error'] = errors[response.status_code] + except KeyError: + misperrors['error'] = f'GreyNoise API not accessible (HTTP {response.status_code})' + return misperrors['error'] def introspection(): From f7b60bed2982454e922d4e23a33b033413b3dfc3 Mon Sep 17 00:00:00 2001 From: chrisr3d Date: Mon, 27 Jul 2020 17:21:52 +0200 Subject: [PATCH 21/30] chg: Updated Greynoise tests following the latest changes on the expansion module --- tests/test_expansions.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/tests/test_expansions.py b/tests/test_expansions.py index b853c25..a56fbe7 100644 --- a/tests/test_expansions.py +++ b/tests/test_expansions.py @@ -229,11 +229,24 @@ class TestExpansions(unittest.TestCase): self.assertEqual(to_check, 'OK (Not Found)', response) def test_greynoise(self): - query = {"module": "greynoise", "ip-dst": "1.1.1.1"} - response = self.misp_modules_post(query) - value = self.get_values(response) - if value != 'GreyNoise API not accessible (HTTP 429)': - self.assertTrue(value.startswith('{"ip":"1.1.1.1","status":"ok"')) + module_name = 'greynoise' + query = {"module": module_name, "ip-dst": "1.1.1.1"} + if module_name in self.configs: + query['config'] = self.configs[module_name] + response = self.misp_modules_post(query) + try: + self.assertEqual(self.get_values(response), 'This IP is commonly spoofed in Internet-scan activity') + except Exception: + self.assertIn( + self.get_errors(reponse), + ( + "Unauthorized. Please check your API key.", + "Too many requests. You've hit the rate-limit." + ) + ) + else: + response = self.misp_modules_post(query) + self.assertEqual(self.get_errors(response), 'Missing Greynoise API key.') def test_ipasn(self): query = {"module": "ipasn", From 6d528628c7f7aa65ec2e25a1074abc52a0818fab Mon Sep 17 00:00:00 2001 From: chrisr3d Date: Mon, 27 Jul 2020 17:26:07 +0200 Subject: [PATCH 22/30] chg: Updated documentation about the greynoise module --- doc/README.md | 4 +++- doc/expansion/greynoise.json | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/README.md b/doc/README.md index e173ad4..21030d4 100644 --- a/doc/README.md +++ b/doc/README.md @@ -502,13 +502,15 @@ Module to query a local copy of Maxmind's Geolite database. Module to access GreyNoise.io API - **features**: ->The module takes an IP address as input and queries Greynoise for some additional information about it. The result is returned as text. +>The module takes an IP address as input and queries Greynoise for some additional information about it: basically it checks whether a given IP address is ā€œInternet background noiseā€, or has been observed scanning or attacking devices across the Internet. The result is returned as text. - **input**: >An IP address. - **output**: >Additional information about the IP fetched from Greynoise API. - **references**: >https://greynoise.io/, https://github.com/GreyNoise-Intelligence/api.greynoise.io +- **requirements**: +>A Greynoise API key. ----- diff --git a/doc/expansion/greynoise.json b/doc/expansion/greynoise.json index f1f1003..49ba481 100644 --- a/doc/expansion/greynoise.json +++ b/doc/expansion/greynoise.json @@ -1,9 +1,9 @@ { "description": "Module to access GreyNoise.io API", "logo": "logos/greynoise.png", - "requirements": [], + "requirements": ["A Greynoise API key."], "input": "An IP address.", "output": "Additional information about the IP fetched from Greynoise API.", "references": ["https://greynoise.io/", "https://github.com/GreyNoise-Intelligence/api.greynoise.io"], - "features": "The module takes an IP address as input and queries Greynoise for some additional information about it. The result is returned as text." + "features": "The module takes an IP address as input and queries Greynoise for some additional information about it: basically it checks whether a given IP address is ā€œInternet background noiseā€, or has been observed scanning or attacking devices across the Internet. The result is returned as text." } From 3b7a5c4dc2541f3b07baee69a7e8b9694a1627fc Mon Sep 17 00:00:00 2001 From: chrisr3d Date: Tue, 28 Jul 2020 11:47:53 +0200 Subject: [PATCH 23/30] add: Specific error message for misp_standard format expansion modules - Checking if the input format is respected and displaying an error message if it is not --- misp_modules/modules/expansion/__init__.py | 9 +++++++++ misp_modules/modules/expansion/apivoid.py | 7 ++++++- misp_modules/modules/expansion/assemblyline_query.py | 5 +++++ misp_modules/modules/expansion/censys_enrich.py | 7 ++++--- misp_modules/modules/expansion/circl_passivedns.py | 7 ++++--- misp_modules/modules/expansion/circl_passivessl.py | 7 ++++--- misp_modules/modules/expansion/cve_advanced.py | 8 +++++--- misp_modules/modules/expansion/cytomic_orion.py | 6 ++++-- misp_modules/modules/expansion/ipasn.py | 11 ++++++----- misp_modules/modules/expansion/joesandbox_query.py | 5 +++++ misp_modules/modules/expansion/lastline_query.py | 4 +++- misp_modules/modules/expansion/malwarebazaar.py | 5 +++++ misp_modules/modules/expansion/ransomcoindb.py | 5 +++++ misp_modules/modules/expansion/recordedfuture.py | 5 +++++ misp_modules/modules/expansion/sophoslabs_intelix.py | 7 +++++++ misp_modules/modules/expansion/trustar_enrich.py | 5 +++++ misp_modules/modules/expansion/urlhaus.py | 8 +++++++- misp_modules/modules/expansion/virustotal.py | 8 +++++++- misp_modules/modules/expansion/virustotal_public.py | 7 ++++++- misp_modules/modules/expansion/xforceexchange.py | 5 +++++ 20 files changed, 107 insertions(+), 24 deletions(-) diff --git a/misp_modules/modules/expansion/__init__.py b/misp_modules/modules/expansion/__init__.py index 14d5499..af895e3 100644 --- a/misp_modules/modules/expansion/__init__.py +++ b/misp_modules/modules/expansion/__init__.py @@ -19,3 +19,12 @@ __all__ = ['cuckoo_submit', 'vmray_submit', 'bgpranking', 'circl_passivedns', 'c 'assemblyline_submit', 'assemblyline_query', 'ransomcoindb', 'malwarebazaar', 'lastline_query', 'lastline_submit', 'sophoslabs_intelix', 'cytomic_orion', 'censys_enrich', 'trustar_enrich', 'recordedfuture'] + + +minimum_required_fields = ('type', 'uuid', 'value') + +checking_error = 'containing at least a "type" field and a "value" field' +standard_error_message = 'This module requires an "attribute" field as input' + +def check_input_attribute(attribute, requirements=minimum_required_fields): + return all(feature in attribute for feature in requirements) diff --git a/misp_modules/modules/expansion/apivoid.py b/misp_modules/modules/expansion/apivoid.py index 5d6395e..a71b5e6 100755 --- a/misp_modules/modules/expansion/apivoid.py +++ b/misp_modules/modules/expansion/apivoid.py @@ -1,5 +1,6 @@ import json import requests +from . import check_input_attribute, standard_error_message from pymisp import MISPAttribute, MISPEvent, MISPObject misperrors = {'error': 'Error'} @@ -74,7 +75,11 @@ def handler(q=False): request = json.loads(q) if not request.get('config', {}).get('apikey'): return {'error': 'An API key for APIVoid is required.'} - attribute = request.get('attribute') + if not request.get('attribute') or not check_input_attribute(request['attribute']): + return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'} + attribute = request['attribute'] + if attribute['type'] not in mispattributes['input']: + return {'error': 'Unsupported attribute type.'} apikey = request['config']['apikey'] apivoid_parser = APIVoidParser(attribute) apivoid_parser.parse_domain(apikey) diff --git a/misp_modules/modules/expansion/assemblyline_query.py b/misp_modules/modules/expansion/assemblyline_query.py index 226e4dd..67fce45 100644 --- a/misp_modules/modules/expansion/assemblyline_query.py +++ b/misp_modules/modules/expansion/assemblyline_query.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import json +from . import check_input_attribute, standard_error_message from assemblyline_client import Client, ClientError from collections import defaultdict from pymisp import MISPAttribute, MISPEvent, MISPObject @@ -139,6 +140,10 @@ def handler(q=False): if q is False: return False request = json.loads(q) + if not request.get('attribute') or not check_input_attribute(request['attribute']): + return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'} + if request['attribute']['type'] not in mispattributes['input']: + return {'error': 'Unsupported attribute type.'} if not request.get('config'): return {"error": "Missing configuration."} if not request['config'].get('apiurl'): diff --git a/misp_modules/modules/expansion/censys_enrich.py b/misp_modules/modules/expansion/censys_enrich.py index 0fc61ae..d5823ff 100644 --- a/misp_modules/modules/expansion/censys_enrich.py +++ b/misp_modules/modules/expansion/censys_enrich.py @@ -3,6 +3,7 @@ import json import base64 import codecs from dateutil.parser import isoparse +from . import check_input_attribute, standard_error_message from pymisp import MISPAttribute, MISPEvent, MISPObject try: import censys.base @@ -36,11 +37,11 @@ def handler(q=False): api_id = request['config']['api_id'] api_secret = request['config']['api_secret'] - if not request.get('attribute'): - return {'error': 'Unsupported input.'} + if not request.get('attribute') or not check_input_attribute(request['attribute']): + return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'} attribute = request['attribute'] if not any(input_type == attribute['type'] for input_type in mispattributes['input']): - return {'error': 'Unsupported attributes type'} + return {'error': 'Unsupported attribute type.'} attribute = MISPAttribute() attribute.from_dict(**request['attribute']) diff --git a/misp_modules/modules/expansion/circl_passivedns.py b/misp_modules/modules/expansion/circl_passivedns.py index d278a85..5f98314 100755 --- a/misp_modules/modules/expansion/circl_passivedns.py +++ b/misp_modules/modules/expansion/circl_passivedns.py @@ -1,5 +1,6 @@ import json import pypdns +from . import check_input_attribute, standard_error_message from pymisp import MISPAttribute, MISPEvent, MISPObject mispattributes = {'input': ['hostname', 'domain', 'ip-src', 'ip-dst', 'ip-src|port', 'ip-dst|port'], 'format': 'misp_standard'} @@ -58,11 +59,11 @@ def handler(q=False): if not request['config'].get('username') or not request['config'].get('password'): return {'error': 'CIRCL Passive DNS authentication is incomplete, please provide your username and password.'} authentication = (request['config']['username'], request['config']['password']) - if not request.get('attribute'): - return {'error': 'Unsupported input.'} + if not request.get('attribute') or not check_input_attribute(request['attribute']): + return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'} attribute = request['attribute'] if not any(input_type == attribute['type'] for input_type in mispattributes['input']): - return {'error': 'Unsupported attributes type'} + return {'error': 'Unsupported attribute type.'} pdns_parser = PassiveDNSParser(attribute, authentication) pdns_parser.parse() return pdns_parser.get_results() diff --git a/misp_modules/modules/expansion/circl_passivessl.py b/misp_modules/modules/expansion/circl_passivessl.py index 102bed8..65783d7 100755 --- a/misp_modules/modules/expansion/circl_passivessl.py +++ b/misp_modules/modules/expansion/circl_passivessl.py @@ -1,5 +1,6 @@ import json import pypssl +from . import check_input_attribute, standard_error_message from pymisp import MISPAttribute, MISPEvent, MISPObject mispattributes = {'input': ['ip-src', 'ip-dst', 'ip-src|port', 'ip-dst|port'], 'format': 'misp_standard'} @@ -83,11 +84,11 @@ def handler(q=False): if not request['config'].get('username') or not request['config'].get('password'): return {'error': 'CIRCL Passive SSL authentication is incomplete, please provide your username and password.'} authentication = (request['config']['username'], request['config']['password']) - if not request.get('attribute'): - return {'error': 'Unsupported input.'} + if not request.get('attribute') or not check_input_attribute(request['attribute']): + return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'} attribute = request['attribute'] if not any(input_type == attribute['type'] for input_type in mispattributes['input']): - return {'error': 'Unsupported attributes type'} + return {'error': 'Unsupported attribute type.'} pssl_parser = PassiveSSLParser(attribute, authentication) pssl_parser.parse() return pssl_parser.get_results() diff --git a/misp_modules/modules/expansion/cve_advanced.py b/misp_modules/modules/expansion/cve_advanced.py index 86cba8c..bd2d277 100644 --- a/misp_modules/modules/expansion/cve_advanced.py +++ b/misp_modules/modules/expansion/cve_advanced.py @@ -1,7 +1,8 @@ -from collections import defaultdict -from pymisp import MISPEvent, MISPObject import json import requests +from . import check_input_attribute, standard_error_message +from collections import defaultdict +from pymisp import MISPEvent, MISPObject misperrors = {'error': 'Error'} mispattributes = {'input': ['vulnerability'], 'format': 'misp_standard'} @@ -108,7 +109,8 @@ def handler(q=False): if q is False: return False request = json.loads(q) - attribute = request.get('attribute') + if not request.get('attribute') or not check_input_attribute(request['attribute']): + return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'} if attribute.get('type') != 'vulnerability': misperrors['error'] = 'Vulnerability id missing.' return misperrors diff --git a/misp_modules/modules/expansion/cytomic_orion.py b/misp_modules/modules/expansion/cytomic_orion.py index 9723ed6..b730135 100755 --- a/misp_modules/modules/expansion/cytomic_orion.py +++ b/misp_modules/modules/expansion/cytomic_orion.py @@ -7,6 +7,7 @@ An expansion module to enrich attributes in MISP and share indicators of comprom ''' +from . import check_input_attribute, standard_error_message from pymisp import MISPAttribute, MISPEvent, MISPObject import json import requests @@ -146,9 +147,10 @@ def handler(q=False): if not request.get('attribute'): return {'error': 'Unsupported input.'} - attribute = request['attribute'] + if not request.get('attribute') or not check_input_attribute(request['attribute']): + return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'} if not any(input_type == attribute['type'] for input_type in mispattributes['input']): - return {'error': 'Unsupported attributes type'} + return {'error': 'Unsupported attribute type.'} if not request.get('config'): return {'error': 'Missing configuration'} diff --git a/misp_modules/modules/expansion/ipasn.py b/misp_modules/modules/expansion/ipasn.py index 3c6867c..3a32358 100755 --- a/misp_modules/modules/expansion/ipasn.py +++ b/misp_modules/modules/expansion/ipasn.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import json +from . import check_input_attribute, standard_error_message from pyipasnhistory import IPASNHistory from pymisp import MISPAttribute, MISPEvent, MISPObject @@ -34,11 +35,11 @@ def handler(q=False): if q is False: return False request = json.loads(q) - if request.get('attribute') and request['attribute'].get('type') in mispattributes['input']: - toquery = request['attribute']['value'] - else: - misperrors['error'] = "Unsupported attributes type" - return misperrors + if not request.get('attribute') or not check_input_attribute(request['attribute']): + return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'} + if request['attribute']['type'] not in mispattributes['input']: + return {'error': 'Unsupported attribute type.'} + toquery = request['attribute']['value'] ipasn = IPASNHistory() values = ipasn.query(toquery) diff --git a/misp_modules/modules/expansion/joesandbox_query.py b/misp_modules/modules/expansion/joesandbox_query.py index 1ace259..b9c4987 100644 --- a/misp_modules/modules/expansion/joesandbox_query.py +++ b/misp_modules/modules/expansion/joesandbox_query.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import jbxapi import json +from . import check_input_attribute, checking_error, standard_error_message from joe_parser import JoeParser misperrors = {'error': 'Error'} @@ -27,6 +28,10 @@ def handler(q=False): if not apikey: return {'error': 'No API key provided'} + if not request.get('attribute') or not check_input_attribute(request['attribute'], requirements=('type', 'value')): + return {'error': f'{standard_error_message}, {checking_error} that is the link to the Joe Sandbox report.'} + if request['attribute']['type'] != 'link': + return {'error': 'Unsupported attribute type.'} url = request['attribute']['value'] if "/submissions/" not in url: return {'error': "The URL does not point to a Joe Sandbox analysis."} diff --git a/misp_modules/modules/expansion/lastline_query.py b/misp_modules/modules/expansion/lastline_query.py index 4ce4e47..dcabda5 100644 --- a/misp_modules/modules/expansion/lastline_query.py +++ b/misp_modules/modules/expansion/lastline_query.py @@ -3,8 +3,8 @@ Module (type "expansion") to query a Lastline report from an analysis link. """ import json - import lastline_api +from . import check_input_attribute, checking_error, standard_error_message misperrors = { @@ -52,6 +52,8 @@ def handler(q=False): try: config = request["config"] auth_data = lastline_api.LastlineAbstractClient.get_login_params_from_dict(config) + if not request.get('attribute') or not request['attribute'].get('value'): + return {'error': f'{standard_error_message}, {checking_error} that is the link to a Lastline analysis.'} analysis_link = request['attribute']['value'] # The API url changes based on the analysis link host name api_url = lastline_api.get_portal_url_from_task_link(analysis_link) diff --git a/misp_modules/modules/expansion/malwarebazaar.py b/misp_modules/modules/expansion/malwarebazaar.py index 4574b75..60739e8 100644 --- a/misp_modules/modules/expansion/malwarebazaar.py +++ b/misp_modules/modules/expansion/malwarebazaar.py @@ -1,5 +1,6 @@ import json import requests +from . import check_input_attribute, checking_error, standard_error_message from pymisp import MISPEvent, MISPObject mispattributes = {'input': ['md5', 'sha1', 'sha256'], @@ -34,7 +35,11 @@ def handler(q=False): if q is False: return False request = json.loads(q) + if not request.get('attribute') or not check_input_attribute(request['attribute'], requirements=('type', 'value')): + return {'error': f'{standard_error_message}, {checking_error} that is the hash to submit to Malware Bazaar.'} attribute = request['attribute'] + if attribute['type'] not in mispattributes['input']: + return {'error': 'Unsupported attribute type.'} url = 'https://mb-api.abuse.ch/api/v1/' response = requests.post(url, data={'query': 'get_info', 'hash': attribute['value']}).json() query_status = response['query_status'] diff --git a/misp_modules/modules/expansion/ransomcoindb.py b/misp_modules/modules/expansion/ransomcoindb.py index 2b9b566..d9a1712 100644 --- a/misp_modules/modules/expansion/ransomcoindb.py +++ b/misp_modules/modules/expansion/ransomcoindb.py @@ -1,4 +1,5 @@ import json +from . import check_input_attribute, checking_error, standard_error_message from ._ransomcoindb import ransomcoindb from pymisp import MISPObject @@ -28,6 +29,10 @@ def handler(q=False): q = json.loads(q) if "config" not in q or "api-key" not in q["config"]: return {"error": "Ransomcoindb API key is missing"} + if not q.get('attribute') or not check_input_attribute(attribute, requirements=('type', 'value')): + return {'error': f'{standard_error_message}, {checking_error}.'} + if q['attribute']['type'] not in mispattributes['input']: + return {'error': 'Unsupported attribute type.'} api_key = q["config"]["api-key"] r = {"results": []} diff --git a/misp_modules/modules/expansion/recordedfuture.py b/misp_modules/modules/expansion/recordedfuture.py index c42a42b..2f71dbb 100644 --- a/misp_modules/modules/expansion/recordedfuture.py +++ b/misp_modules/modules/expansion/recordedfuture.py @@ -1,6 +1,7 @@ import json import logging import requests +from . import check_input_attribute, checking_error, standard_error_message from urllib.parse import quote from pymisp import MISPAttribute, MISPEvent, MISPTag, MISPObject @@ -257,6 +258,10 @@ def handler(q=False): else: misperrors['error'] = 'Missing Recorded Future token.' return misperrors + if not request.get('attribute') or not check_input_attribute(request['atttribute'], requirements=('type', 'value')): + return {'error': f'{standard_error_message}, {checking_error}.'} + if request['attribute']['type'] not in mispattributes['input']: + return {'error': 'Unsupported attribute type.'} input_attribute = request.get('attribute') rf_enricher = RFEnricher(token, input_attribute) diff --git a/misp_modules/modules/expansion/sophoslabs_intelix.py b/misp_modules/modules/expansion/sophoslabs_intelix.py index 017683a..6c6204a 100644 --- a/misp_modules/modules/expansion/sophoslabs_intelix.py +++ b/misp_modules/modules/expansion/sophoslabs_intelix.py @@ -1,3 +1,4 @@ +from. import check_input_attribute, checking_error, standard_error_message from pymisp import MISPEvent, MISPObject import json import requests @@ -105,6 +106,12 @@ def handler(q=False): misperrors['error'] = "Missing client_id or client_secret value for SOPHOSLabs Intelix. \ It's free to sign up here https://aws.amazon.com/marketplace/pp/B07SLZPMCS." return misperrors + to_check = (('type', 'value'), ('type', 'value1')) + if not request.get('attribute') or not any(check_input_attribute(request['attribute'], requirements=check) for check in to_check): + return {'error': f'{standard_error_message}, {checking_error}.'} + attribute = request['attribute'] + if attribute['type'] not in misp_types_in: + return {'error': 'Unsupported attribute type.'} client = SophosLabsApi(j['config']['client_id'], j['config']['client_secret']) if j['attribute']['type'] == "sha256": client.hash_lookup(j['attribute']['value1']) diff --git a/misp_modules/modules/expansion/trustar_enrich.py b/misp_modules/modules/expansion/trustar_enrich.py index efe7c53..a0d6177 100644 --- a/misp_modules/modules/expansion/trustar_enrich.py +++ b/misp_modules/modules/expansion/trustar_enrich.py @@ -1,5 +1,6 @@ import json import pymisp +from . import check_input_attribute, checking_error, standard_error_message from pymisp import MISPAttribute, MISPEvent, MISPObject from trustar import TruStar @@ -110,7 +111,11 @@ def handler(q=False): misperrors['error'] = "Your TruSTAR API key and secret are required for indicator enrichment." return misperrors + if not request.get('attribute') or not check_input_attribute(request['attribute'], requirements=('type', 'value')): + return {'error': f'{standard_error_message}, {checking_error}.'} attribute = request['attribute'] + if attribute['type'] not in mispattributes['input']: + return {'error': 'Unsupported attribute type.'} trustar_parser = TruSTARParser(attribute, config) try: diff --git a/misp_modules/modules/expansion/urlhaus.py b/misp_modules/modules/expansion/urlhaus.py index baaaaf6..ed13b77 100644 --- a/misp_modules/modules/expansion/urlhaus.py +++ b/misp_modules/modules/expansion/urlhaus.py @@ -1,6 +1,8 @@ -from pymisp import MISPAttribute, MISPEvent, MISPObject +# -*- coding: utf-8 -*- import json import requests +from . import check_input_attribute, standard_error_message +from pymisp import MISPAttribute, MISPEvent, MISPObject misperrors = {'error': 'Error'} mispattributes = {'input': ['domain', 'hostname', 'ip-src', 'ip-dst', 'md5', 'sha256', 'url'], @@ -134,7 +136,11 @@ def handler(q=False): if q is False: return False request = json.loads(q) + if not request.get('attribute') or not check_input_attribute(request['attribute']): + return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'} attribute = request['attribute'] + if attribute['type'] not in mispattributes['input']: + return {'error': 'Unsupported attribute type.'} urlhaus_parser = _misp_type_mapping[attribute['type']](attribute) return urlhaus_parser.query_api() diff --git a/misp_modules/modules/expansion/virustotal.py b/misp_modules/modules/expansion/virustotal.py index b09de81..12f7552 100644 --- a/misp_modules/modules/expansion/virustotal.py +++ b/misp_modules/modules/expansion/virustotal.py @@ -1,6 +1,7 @@ -from pymisp import MISPAttribute, MISPEvent, MISPObject import json import requests +from . import check_input_attribute, standard_error_message +from pymisp import MISPAttribute, MISPEvent, MISPObject misperrors = {'error': 'Error'} mispattributes = {'input': ['hostname', 'domain', "ip-src", "ip-dst", "md5", "sha1", "sha256", "url"], @@ -195,6 +196,11 @@ def handler(q=False): if not request.get('config') or not request['config'].get('apikey'): misperrors['error'] = "A VirusTotal api key is required for this module." return misperrors + if not request.get('attribute') or not check_input_attribute(request['attribute']): + return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'} + if request['attribute']['type'] not in mispattributes['input']: + return {'error': 'Unsupported attribute type.'} + event_limit = request['config'].get('event_limit') if not isinstance(event_limit, int): event_limit = 5 diff --git a/misp_modules/modules/expansion/virustotal_public.py b/misp_modules/modules/expansion/virustotal_public.py index e7c2e96..6ffb7f9 100644 --- a/misp_modules/modules/expansion/virustotal_public.py +++ b/misp_modules/modules/expansion/virustotal_public.py @@ -1,6 +1,7 @@ -from pymisp import MISPAttribute, MISPEvent, MISPObject import json import requests +from . import check_input_attribute, standard_error_message +from pymisp import MISPAttribute, MISPEvent, MISPObject misperrors = {'error': 'Error'} mispattributes = {'input': ['hostname', 'domain', "ip-src", "ip-dst", "md5", "sha1", "sha256", "url"], @@ -174,7 +175,11 @@ def handler(q=False): if not request.get('config') or not request['config'].get('apikey'): misperrors['error'] = "A VirusTotal api key is required for this module." return misperrors + if not request.get('attribute') or not check_input_attribute(request['attribute']): + return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'} attribute = request['attribute'] + if attribute['type'] not in mispattributes['input']: + return {'error': 'Unsupported attribute type.'} query_type, to_call = misp_type_mapping[attribute['type']] parser = to_call(request['config']['apikey'], attribute) query_result = parser.get_query_result(query_type) diff --git a/misp_modules/modules/expansion/xforceexchange.py b/misp_modules/modules/expansion/xforceexchange.py index 7999ce2..936917f 100644 --- a/misp_modules/modules/expansion/xforceexchange.py +++ b/misp_modules/modules/expansion/xforceexchange.py @@ -1,6 +1,7 @@ import requests import json import sys +from . import check_input_attribute, standard_error_message from collections import defaultdict from pymisp import MISPAttribute, MISPEvent, MISPObject from requests.auth import HTTPBasicAuth @@ -160,6 +161,10 @@ def handler(q=False): return misperrors key = request["config"]["apikey"] password = request['config']['apipassword'] + if not request.get('attribute') or not check_input_attribute(request['attribute']): + return {'error': f'{standard_error_message} which should contain at least a type, a value and an uuid.'} + if request['attribute']['type'] not in mispattributes['input']: + return {'error': 'Unsupported attribute type.'} parser = XforceExchange(request['attribute'], key, password) parser.parse() return parser.get_result() From 3ab67b23b66831dc49e6ecd0a346a8b9b52cbdce Mon Sep 17 00:00:00 2001 From: chrisr3d Date: Tue, 28 Jul 2020 11:56:03 +0200 Subject: [PATCH 24/30] fix: Avoid issues with the attribute value field name - The module setup allows 'value1' as attribute value field name, but we want to make sure that users passing standard misp format with 'value' instead, will not have issues, as well as keeping the current setup --- .../modules/expansion/sophoslabs_intelix.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/misp_modules/modules/expansion/sophoslabs_intelix.py b/misp_modules/modules/expansion/sophoslabs_intelix.py index 6c6204a..38d4293 100644 --- a/misp_modules/modules/expansion/sophoslabs_intelix.py +++ b/misp_modules/modules/expansion/sophoslabs_intelix.py @@ -113,12 +113,18 @@ def handler(q=False): if attribute['type'] not in misp_types_in: return {'error': 'Unsupported attribute type.'} client = SophosLabsApi(j['config']['client_id'], j['config']['client_secret']) - if j['attribute']['type'] == "sha256": - client.hash_lookup(j['attribute']['value1']) - if j['attribute']['type'] in ['ip-dst', 'ip-src', 'ip']: - client.ip_lookup(j["attribute"]["value1"]) - if j['attribute']['type'] in ['uri', 'url', 'domain', 'hostname']: - client.url_lookup(j["attribute"]["value1"]) + mapping = { + 'sha256': 'hash_lookup', + 'ip-dst': 'ip_lookup', + 'ip-src': 'ip_lookup', + 'ip': 'ip_lookup', + 'uri': 'url_lookup', + 'url': 'url_lookup', + 'domain': 'url_lookup', + 'hostname': 'url_lookup' + } + attribute_value = attribute['value'] if 'value' in attribute else attribute['value1'] + getattr(client, mapping[attribute['type']])(attribute_value) return client.get_result() From a316e1877f55995df55ad917ca8f8a3a471548e2 Mon Sep 17 00:00:00 2001 From: johannesh Date: Tue, 28 Jul 2020 13:33:48 +0200 Subject: [PATCH 25/30] Add Recorded Future module documentation --- doc/README.md | 18 ++++++++++++++++++ doc/expansion/recordedfuture.json | 9 +++++++++ doc/logos/recordedfuture.png | Bin 0 -> 39310 bytes 3 files changed, 27 insertions(+) create mode 100644 doc/expansion/recordedfuture.json create mode 100644 doc/logos/recordedfuture.png diff --git a/doc/README.md b/doc/README.md index e173ad4..77c1e82 100644 --- a/doc/README.md +++ b/doc/README.md @@ -964,6 +964,24 @@ Module to check an IPv4 address against known RBLs. ----- +#### [recordedfuture](https://github.com/MISP/misp-modules/tree/master/misp_modules/modules/expansion/recordedfuture.py) + + + +Module to enrich attributes with threat intelligence from Recorded Future. +- **features**: +>Enrich an attribute to add a custom enrichment object to the event. The object contains a copy of the enriched attribute with added tags presenting risk score and triggered risk rules from Recorded Future. Malware and Threat Actors related to the enriched indicator in Recorded Future will be matched against MISP's galaxy clusters and applied as galaxy tags. The custom enrichment object will also include a list of related indicators from Recorded Future (IP's, domains, hashes, URL's and vulnerabilities) added as additional attributes. +- **input**: +>A MISP attribute of one of the following types: ip, ip-src, ip-dst, domain, hostname, md5, sha1, sha256, uri, url, vulnerability, weakness. +- **output**: +>A MISP object containing a copy of the enriched attribute with added tags from Recorded Future and a list of new attributes related to the enriched attribute. +- **references**: +>https://www.recordedfuture.com/ +- **requirements**: +>A Recorded Future API token. + +----- + #### [reversedns](https://github.com/MISP/misp-modules/tree/master/misp_modules/modules/expansion/reversedns.py) Simple Reverse DNS expansion service to resolve reverse DNS from MISP attributes. diff --git a/doc/expansion/recordedfuture.json b/doc/expansion/recordedfuture.json new file mode 100644 index 0000000..bbeea07 --- /dev/null +++ b/doc/expansion/recordedfuture.json @@ -0,0 +1,9 @@ +{ + "description": "Module to enrich attributes with threat intelligence from Recorded Future.", + "logo": "logos/recordedfuture.png", + "requirements": ["A Recorded Future API token."], + "input": "A MISP attribute of one of the following types: ip, ip-src, ip-dst, domain, hostname, md5, sha1, sha256, uri, url, vulnerability, weakness.", + "output": "A MISP object containing a copy of the enriched attribute with added tags from Recorded Future and a list of new attributes related to the enriched attribute.", + "references": ["https://www.recordedfuture.com/"], + "features": "Enrich an attribute to add a custom enrichment object to the event. The object contains a copy of the enriched attribute with added tags presenting risk score and triggered risk rules from Recorded Future. Malware and Threat Actors related to the enriched indicator in Recorded Future will be matched against MISP's galaxy clusters and applied as galaxy tags. The custom enrichment object will also include a list of related indicators from Recorded Future (IP's, domains, hashes, URL's and vulnerabilities) added as additional attributes." +} diff --git a/doc/logos/recordedfuture.png b/doc/logos/recordedfuture.png new file mode 100644 index 0000000000000000000000000000000000000000..a208c0453e811fe2f8fefab566158f5d4ca76e9a GIT binary patch literal 39310 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 literal 0 HcmV?d00001 From 988bf3487d4c47b16f9d95d42d85b6158ed4f1a9 Mon Sep 17 00:00:00 2001 From: johannesh Date: Tue, 28 Jul 2020 13:46:43 +0200 Subject: [PATCH 26/30] Improve wording --- doc/README.md | 2 +- doc/expansion/recordedfuture.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/README.md b/doc/README.md index 77c1e82..5e15147 100644 --- a/doc/README.md +++ b/doc/README.md @@ -970,7 +970,7 @@ Module to check an IPv4 address against known RBLs. Module to enrich attributes with threat intelligence from Recorded Future. - **features**: ->Enrich an attribute to add a custom enrichment object to the event. The object contains a copy of the enriched attribute with added tags presenting risk score and triggered risk rules from Recorded Future. Malware and Threat Actors related to the enriched indicator in Recorded Future will be matched against MISP's galaxy clusters and applied as galaxy tags. The custom enrichment object will also include a list of related indicators from Recorded Future (IP's, domains, hashes, URL's and vulnerabilities) added as additional attributes. +>Enrich an attribute to add a custom enrichment object to the event. The object contains a copy of the enriched attribute with added tags presenting risk score and triggered risk rules from Recorded Future. Malware and Threat Actors related to the enriched indicator in Recorded Future is matched against MISP's galaxy clusters and applied as galaxy tags. The custom enrichment object also includes a list of related indicators from Recorded Future (IP's, domains, hashes, URL's and vulnerabilities) added as additional attributes. - **input**: >A MISP attribute of one of the following types: ip, ip-src, ip-dst, domain, hostname, md5, sha1, sha256, uri, url, vulnerability, weakness. - **output**: diff --git a/doc/expansion/recordedfuture.json b/doc/expansion/recordedfuture.json index bbeea07..2fec7eb 100644 --- a/doc/expansion/recordedfuture.json +++ b/doc/expansion/recordedfuture.json @@ -5,5 +5,5 @@ "input": "A MISP attribute of one of the following types: ip, ip-src, ip-dst, domain, hostname, md5, sha1, sha256, uri, url, vulnerability, weakness.", "output": "A MISP object containing a copy of the enriched attribute with added tags from Recorded Future and a list of new attributes related to the enriched attribute.", "references": ["https://www.recordedfuture.com/"], - "features": "Enrich an attribute to add a custom enrichment object to the event. The object contains a copy of the enriched attribute with added tags presenting risk score and triggered risk rules from Recorded Future. Malware and Threat Actors related to the enriched indicator in Recorded Future will be matched against MISP's galaxy clusters and applied as galaxy tags. The custom enrichment object will also include a list of related indicators from Recorded Future (IP's, domains, hashes, URL's and vulnerabilities) added as additional attributes." + "features": "Enrich an attribute to add a custom enrichment object to the event. The object contains a copy of the enriched attribute with added tags presenting risk score and triggered risk rules from Recorded Future. Malware and Threat Actors related to the enriched indicator in Recorded Future is matched against MISP's galaxy clusters and applied as galaxy tags. The custom enrichment object also includes a list of related indicators from Recorded Future (IP's, domains, hashes, URL's and vulnerabilities) added as additional attributes." } From d2661c7a2017f669baf98cfaee5f4b9a7a18bf66 Mon Sep 17 00:00:00 2001 From: chrisr3d Date: Tue, 28 Jul 2020 15:06:25 +0200 Subject: [PATCH 27/30] fix: Fixed pep8 + some copy paste issues introduced with the latest commits --- misp_modules/modules/expansion/__init__.py | 1 + misp_modules/modules/expansion/cve_advanced.py | 1 + misp_modules/modules/expansion/cytomic_orion.py | 1 + misp_modules/modules/expansion/ransomcoindb.py | 2 +- misp_modules/modules/expansion/sophoslabs_intelix.py | 8 ++++---- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/misp_modules/modules/expansion/__init__.py b/misp_modules/modules/expansion/__init__.py index af895e3..1b6d2bb 100644 --- a/misp_modules/modules/expansion/__init__.py +++ b/misp_modules/modules/expansion/__init__.py @@ -26,5 +26,6 @@ minimum_required_fields = ('type', 'uuid', 'value') checking_error = 'containing at least a "type" field and a "value" field' standard_error_message = 'This module requires an "attribute" field as input' + def check_input_attribute(attribute, requirements=minimum_required_fields): return all(feature in attribute for feature in requirements) diff --git a/misp_modules/modules/expansion/cve_advanced.py b/misp_modules/modules/expansion/cve_advanced.py index bd2d277..cd36655 100644 --- a/misp_modules/modules/expansion/cve_advanced.py +++ b/misp_modules/modules/expansion/cve_advanced.py @@ -111,6 +111,7 @@ def handler(q=False): request = json.loads(q) if not request.get('attribute') or not check_input_attribute(request['attribute']): return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'} + attribute = request['attribute'] if attribute.get('type') != 'vulnerability': misperrors['error'] = 'Vulnerability id missing.' return misperrors diff --git a/misp_modules/modules/expansion/cytomic_orion.py b/misp_modules/modules/expansion/cytomic_orion.py index b730135..c13b254 100755 --- a/misp_modules/modules/expansion/cytomic_orion.py +++ b/misp_modules/modules/expansion/cytomic_orion.py @@ -149,6 +149,7 @@ def handler(q=False): if not request.get('attribute') or not check_input_attribute(request['attribute']): return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'} + attribute = request['attribute'] if not any(input_type == attribute['type'] for input_type in mispattributes['input']): return {'error': 'Unsupported attribute type.'} diff --git a/misp_modules/modules/expansion/ransomcoindb.py b/misp_modules/modules/expansion/ransomcoindb.py index d9a1712..0e05855 100644 --- a/misp_modules/modules/expansion/ransomcoindb.py +++ b/misp_modules/modules/expansion/ransomcoindb.py @@ -29,7 +29,7 @@ def handler(q=False): q = json.loads(q) if "config" not in q or "api-key" not in q["config"]: return {"error": "Ransomcoindb API key is missing"} - if not q.get('attribute') or not check_input_attribute(attribute, requirements=('type', 'value')): + if not q.get('attribute') or not check_input_attribute(q['attribute'], requirements=('type', 'value')): return {'error': f'{standard_error_message}, {checking_error}.'} if q['attribute']['type'] not in mispattributes['input']: return {'error': 'Unsupported attribute type.'} diff --git a/misp_modules/modules/expansion/sophoslabs_intelix.py b/misp_modules/modules/expansion/sophoslabs_intelix.py index 38d4293..254437b 100644 --- a/misp_modules/modules/expansion/sophoslabs_intelix.py +++ b/misp_modules/modules/expansion/sophoslabs_intelix.py @@ -1,8 +1,8 @@ -from. import check_input_attribute, checking_error, standard_error_message -from pymisp import MISPEvent, MISPObject import json import requests import base64 +from. import check_input_attribute, checking_error, standard_error_message +from pymisp import MISPEvent, MISPObject from urllib.parse import quote moduleinfo = {'version': '1.0', @@ -107,9 +107,9 @@ def handler(q=False): It's free to sign up here https://aws.amazon.com/marketplace/pp/B07SLZPMCS." return misperrors to_check = (('type', 'value'), ('type', 'value1')) - if not request.get('attribute') or not any(check_input_attribute(request['attribute'], requirements=check) for check in to_check): + if not j.get('attribute') or not any(check_input_attribute(j['attribute'], requirements=check) for check in to_check): return {'error': f'{standard_error_message}, {checking_error}.'} - attribute = request['attribute'] + attribute = j['attribute'] if attribute['type'] not in misp_types_in: return {'error': 'Unsupported attribute type.'} client = SophosLabsApi(j['config']['client_id'], j['config']['client_secret']) From f1dac0c8dfb5aff60611d3dbd439b67feaa1a03e Mon Sep 17 00:00:00 2001 From: chrisr3d Date: Tue, 28 Jul 2020 15:23:24 +0200 Subject: [PATCH 28/30] fix: Fixed pep8 --- misp_modules/modules/expansion/lastline_query.py | 2 +- misp_modules/modules/expansion/sophoslabs_intelix.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/misp_modules/modules/expansion/lastline_query.py b/misp_modules/modules/expansion/lastline_query.py index dcabda5..dbfdf14 100644 --- a/misp_modules/modules/expansion/lastline_query.py +++ b/misp_modules/modules/expansion/lastline_query.py @@ -52,7 +52,7 @@ def handler(q=False): try: config = request["config"] auth_data = lastline_api.LastlineAbstractClient.get_login_params_from_dict(config) - if not request.get('attribute') or not request['attribute'].get('value'): + if not request.get('attribute') or not check_input_attribute(request['attribute'], requirements=('type', 'value')): return {'error': f'{standard_error_message}, {checking_error} that is the link to a Lastline analysis.'} analysis_link = request['attribute']['value'] # The API url changes based on the analysis link host name diff --git a/misp_modules/modules/expansion/sophoslabs_intelix.py b/misp_modules/modules/expansion/sophoslabs_intelix.py index 254437b..4d7c413 100644 --- a/misp_modules/modules/expansion/sophoslabs_intelix.py +++ b/misp_modules/modules/expansion/sophoslabs_intelix.py @@ -1,7 +1,7 @@ import json import requests import base64 -from. import check_input_attribute, checking_error, standard_error_message +from . import check_input_attribute, checking_error, standard_error_message from pymisp import MISPEvent, MISPObject from urllib.parse import quote From 0b869750d75dd170c502fca089ee989cf3a4f14c Mon Sep 17 00:00:00 2001 From: Jesse Hedden Date: Wed, 29 Jul 2020 09:35:08 -0700 Subject: [PATCH 29/30] added description to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index db199a0..17d6f2b 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,7 @@ For more information: [Extending MISP with Python modules](https://www.misp-proj * [STIX2 pattern syntax validator](misp_modules/modules/expansion/stix2_pattern_syntax_validator.py) - a module to check a STIX2 pattern syntax. * [ThreatCrowd](misp_modules/modules/expansion/threatcrowd.py) - an expansion module for [ThreatCrowd](https://www.threatcrowd.org/). * [threatminer](misp_modules/modules/expansion/threatminer.py) - an expansion module to expand from [ThreatMiner](https://www.threatminer.org/). +* [TruSTAR Enrich](misp_modules/modules/expansion/trustar_enrich.py) - an expansion module to enrich MISP data with [TruSTAR](https://www.trustar.co/). * [urlhaus](misp_modules/modules/expansion/urlhaus.py) - Query urlhaus to get additional data about a domain, hash, hostname, ip or url. * [urlscan](misp_modules/modules/expansion/urlscan.py) - an expansion module to query [urlscan.io](https://urlscan.io). * [virustotal](misp_modules/modules/expansion/virustotal.py) - an expansion module to query the [VirusTotal](https://www.virustotal.com/gui/home) API with a high request rate limit required. (More details about the API: [here](https://developers.virustotal.com/reference)) From 85d319e85e1e53349685b3124aa13b020891b382 Mon Sep 17 00:00:00 2001 From: johannesh Date: Fri, 7 Aug 2020 10:36:40 +0200 Subject: [PATCH 30/30] Fix typo error introduced in commit: 3b7a5c4dc2541f3b07baee69a7e8b9694a1627fc --- misp_modules/modules/expansion/recordedfuture.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misp_modules/modules/expansion/recordedfuture.py b/misp_modules/modules/expansion/recordedfuture.py index 2f71dbb..8fdff09 100644 --- a/misp_modules/modules/expansion/recordedfuture.py +++ b/misp_modules/modules/expansion/recordedfuture.py @@ -258,7 +258,7 @@ def handler(q=False): else: misperrors['error'] = 'Missing Recorded Future token.' return misperrors - if not request.get('attribute') or not check_input_attribute(request['atttribute'], requirements=('type', 'value')): + if not request.get('attribute') or not check_input_attribute(request['attribute'], requirements=('type', 'value')): return {'error': f'{standard_error_message}, {checking_error}.'} if request['attribute']['type'] not in mispattributes['input']: return {'error': 'Unsupported attribute type.'}