From f4dfa0343e6c0f3df12ed6992a622b7dc074b8a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Tue, 23 Aug 2022 17:48:36 +0200 Subject: [PATCH] new: Submit to Pandora button for file URLs --- config/modules.json.sample | 6 +++++ lookyloo/lookyloo.py | 6 ++++- lookyloo/modules/__init__.py | 1 + poetry.lock | 26 ++++++++++++++++++---- pyproject.toml | 3 ++- website/web/__init__.py | 8 +++++++ website/web/sri.txt | 2 +- website/web/static/tree.js | 14 +++++++----- website/web/templates/hostname_popup.html | 27 +++++++++++++++++++++++ 9 files changed, 81 insertions(+), 12 deletions(-) diff --git a/config/modules.json.sample b/config/modules.json.sample index f4f607f..3ada48a 100644 --- a/config/modules.json.sample +++ b/config/modules.json.sample @@ -14,6 +14,11 @@ "autosubmit": false, "allow_auto_trigger": false }, + "Pandora": { + "url": "http://127.0.0.1:6100", + "autosubmit": false, + "allow_auto_trigger": false + }, "SaneJS": { "enabled": true, "allow_auto_trigger": true @@ -70,6 +75,7 @@ "Phishtank": "Module to query Phishtank Lookup (https://github.com/Lookyloo/phishtank-lookup). URL set to none means querying the public instance.", "Hashlookup": "Module to query Hashlookup (https://github.com/adulau/hashlookup-server). URL set to none means querying the public instance.", "FOX": "Submission only interface by and for CCCS", + "Pandora": "Submission only interface for https://github.com/pandora-analysis/", "RiskIQ": "Module to query RiskIQ (https://community.riskiq.com/)" } } diff --git a/lookyloo/lookyloo.py b/lookyloo/lookyloo.py index 47c7e36..a6766dc 100644 --- a/lookyloo/lookyloo.py +++ b/lookyloo/lookyloo.py @@ -38,7 +38,7 @@ from .helpers import (CaptureStatus, get_captures_dir, get_email_template, from .indexing import Indexing from .modules import (MISP, PhishingInitiative, UniversalWhois, UrlScan, VirusTotal, Phishtank, Hashlookup, - RiskIQ, RiskIQError) + RiskIQ, RiskIQError, Pandora) class Lookyloo(): @@ -90,6 +90,10 @@ class Lookyloo(): if not self.riskiq.available: self.logger.warning('Unable to setup the RiskIQ module') + self.pandora = Pandora(get_config('modules', 'Pandora')) + if not self.pandora.available: + self.logger.warning('Unable to setup the Pandora module') + self.logger.info('Initializing context...') self.context = Context() self.logger.info('Context initialized.') diff --git a/lookyloo/modules/__init__.py b/lookyloo/modules/__init__.py index fef59b2..c7dfc61 100644 --- a/lookyloo/modules/__init__.py +++ b/lookyloo/modules/__init__.py @@ -7,6 +7,7 @@ from .sanejs import SaneJavaScript # noqa from .urlscan import UrlScan # noqa from .uwhois import UniversalWhois # noqa from .vt import VirusTotal # noqa +from .pandora import Pandora # noqa from .phishtank import Phishtank # noqa from .hashlookup import HashlookupModule as Hashlookup # noqa from .riskiq import RiskIQ, RiskIQError # noqa diff --git a/poetry.lock b/poetry.lock index 50de5fe..a1702a2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -903,6 +903,20 @@ pdfexport = ["reportlab (>=3.6.11,<4.0.0)"] url = ["pyfaup (>=1.2,<2.0)", "chardet (>=5.0.0,<6.0.0)"] brotli = ["urllib3[brotli] (>=1.26.11,<2.0.0)"] +[[package]] +name = "pypandora" +version = "1.0.2" +description = "Python CLI and module for pandora" +category = "main" +optional = false +python-versions = ">=3.8,<4.0" + +[package.dependencies] +requests = ">=2.28.1,<3.0.0" + +[package.extras] +docs = ["Sphinx (>=5.1.1,<6.0.0)"] + [[package]] name = "pyparsing" version = "3.0.9" @@ -1217,7 +1231,7 @@ python-versions = "*" [[package]] name = "types-redis" -version = "4.3.16" +version = "4.3.17" description = "Typing stubs for redis" category = "dev" optional = false @@ -1413,7 +1427,7 @@ misp = ["python-magic", "pydeep2"] [metadata] lock-version = "1.1" python-versions = ">=3.8,<3.11" -content-hash = "b813c16a36c8bfd612488d2fdfce36b34234e03fae997dc56a6613672c31d9b4" +content-hash = "0dcbbf79ed17ddfa5f0f66c8ffa0b0b6025527aa287761d1730a992be6b42dab" [metadata.files] aiohttp = [ @@ -2276,6 +2290,10 @@ pymisp = [ {file = "pymisp-2.4.160.1-py3-none-any.whl", hash = "sha256:3499dc55819e874eeecd7d1b10229cb957600a52452ca5360db3b32f21714718"}, {file = "pymisp-2.4.160.1.tar.gz", hash = "sha256:d6cf306100d7c936951db9cb1bff53276a94d75b3ff5ae4c35a952f001169021"}, ] +pypandora = [ + {file = "pypandora-1.0.2-py3-none-any.whl", hash = "sha256:520801d7e6488ae474e6e1e713db52e12a220749ace68361f863ab1de3f29a96"}, + {file = "pypandora-1.0.2.tar.gz", hash = "sha256:d8603d68cdd41e5ce9f2b5fcd9a7db0e25bbf3d6bcb99b26d90bfc28ecac81cd"}, +] pyparsing = [ {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, @@ -2484,8 +2502,8 @@ types-python-dateutil = [ {file = "types_python_dateutil-2.8.19-py3-none-any.whl", hash = "sha256:6284df1e4783d8fc6e587f0317a81333856b872a6669a282f8a325342bce7fa8"}, ] types-redis = [ - {file = "types-redis-4.3.16.tar.gz", hash = "sha256:ed53e35eac4303ef70cf7f5c205e210f2238b7fdd9306b7f8676669c1070943e"}, - {file = "types_redis-4.3.16-py3-none-any.whl", hash = "sha256:41da87dc80f39573a71873e4265f181d9628b0a2a862e850ecc896a0cd6cacd2"}, + {file = "types-redis-4.3.17.tar.gz", hash = "sha256:03b023c08acf344f4f0821cc1c7e4dbecb7b17bc5483927c3e73d80f7fe1768e"}, + {file = "types_redis-4.3.17-py3-none-any.whl", hash = "sha256:a34c4e7aafa4b2fb9090d3a7f3ad0ac969089c7b4a05c21dff593a0c37405916"}, ] types-requests = [ {file = "types-requests-2.28.9.tar.gz", hash = "sha256:feaf581bd580497a47fe845d506fa3b91b484cf706ff27774e87659837de9962"}, diff --git a/pyproject.toml b/pyproject.toml index df4fd08..fd26301 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,6 +67,7 @@ playwrightcapture = "^1.14.3" passivetotal = "^2.5.9" werkzeug = "2.1.2" filetype = "^1.1.0" +pypandora = "^1.0.2" [tool.poetry.extras] misp = ['python-magic', 'pydeep2'] @@ -74,7 +75,7 @@ misp = ['python-magic', 'pydeep2'] [tool.poetry.dev-dependencies] mypy = "^0.971" ipython = "^8.4.0" -types-redis = "^4.3.16" +types-redis = "^4.3.17" types-requests = "^2.28.9" types-Flask = "^1.1.6" types-pkg-resources = "^0.1.3" diff --git a/website/web/__init__.py b/website/web/__init__.py index 0f98e04..bafeb7f 100644 --- a/website/web/__init__.py +++ b/website/web/__init__.py @@ -246,6 +246,7 @@ def hostnode_popup(tree_uuid: str, node_uuid: str): hostnode_uuid=node_uuid, hostnode=hostnode, urls=urls, + has_pandora=lookyloo.pandora.available, enable_context_by_users=enable_context_by_users, uwhois_available=lookyloo.uwhois.available) @@ -713,6 +714,13 @@ def tree_body_hashes(tree_uuid: str): return render_template('tree_body_hashes.html', tree_uuid=tree_uuid, body_hashes=body_hashes) +@app.route('/tree//pandora', methods=['GET']) +def pandora_submit(tree_uuid: str): + filename, content = lookyloo.get_data(tree_uuid) + response = lookyloo.pandora.submit_file(content, filename) + return jsonify(response) + + # ##### helpers ##### def index_generic(show_hidden: bool=False, show_error: bool=True, category: Optional[str]=None): diff --git a/website/web/sri.txt b/website/web/sri.txt index 1d25e9e..e3d3c17 100644 --- a/website/web/sri.txt +++ b/website/web/sri.txt @@ -34,7 +34,7 @@ "stats.css": "/kY943FwWBTne4IIyf7iBROSfbGd82TeBicEXqKkRwawMVRIvM/Pk5MRa7okUyGIxaDjFQGmV/U1vy+PhN6Jbw==", "stats_graph.js": "0OEouA6NAxLG2wMd7D2vtGoMrXKna7My98Euc6ecyfdO4/6mIJS87vzISOS4zSZ8u4ehpa+p7E0nWhsXXE7H/Q==", "tree.css": "THJ9LnnSJ91DSTvrYoOCxRrenGgwsgG5zKo+eZLH2rRFHn6lpX9UpmRhRic4th9ZYuM9/NJUS7LqYBDRPPnB1Q==", - "tree.js": "gHr2HiDbQYfVhBtt95VP6+f7k4neVnfcXV66o4oKg7wB3HVNs/XrTCXpthS3W8yfouySLpZoTVTaPHrAvs5wwg==", + "tree.js": "H6ibjUxG7eD+Dz+jFBnERtxTIdR1aPssd86rCrwHH8CHUySn70aCE3mCmGYwNWw0GCpGT1IYWuZ+K0us+selNg==", "up.jpg": "d1ljZJ9f5JekyM6RLFFH2Ua44j6neiQBdUIXOenRTjGppQr3JaeglpQIH6BjPCJL177+TH52U3UIRNS5YAyKIg==", "up_right.jpg": "OMmz+n+MxR34P8/fn5t4DkqKqdJRzQbXQ7fAi2lhkZIJGhVs2vIyY1f2hpYoBxDAX1OcYsSE2lqIR2vXNDGZsA==", "video.png": "gJtmkfr8I1Kw43pYEKjg6CAjgmhl1vIBKBQ3ZkxCu3wvxQm+6kf93iLrrFiY2WuiXzxEn2Leu52GJzmVN5id0g==", diff --git a/website/web/static/tree.js b/website/web/static/tree.js index 9e2b1b5..3619cff 100644 --- a/website/web/static/tree.js +++ b/website/web/static/tree.js @@ -157,11 +157,7 @@ if (parent_uuid != null) { }; -function openTreeInNewTab(capture_uuid, hostnode_uuid=null) { - let url = `/tree/${capture_uuid}`; - if (hostnode_uuid != null) { - url += `/${hostnode_uuid}`; - } +function openURLInNewTab(url) { let win = window.open(url, '_blank'); if (win == null) { return false; @@ -170,6 +166,14 @@ function openTreeInNewTab(capture_uuid, hostnode_uuid=null) { return true; } +function openTreeInNewTab(capture_uuid, hostnode_uuid=null) { + let url = `/tree/${capture_uuid}`; + if (hostnode_uuid != null) { + url += `/${hostnode_uuid}`; + } + openURLInNewTab(url); +} + function open_hostnode_popup(hostnode_uuid) { let win = window.open(`/tree/${treeUUID}/host/${hostnode_uuid}`, '_blank', 'width=1024,height=768,left=200,top=100'); if (win == null) { diff --git a/website/web/templates/hostname_popup.html b/website/web/templates/hostname_popup.html index 21f9b6a..250b14e 100644 --- a/website/web/templates/hostname_popup.html +++ b/website/web/templates/hostname_popup.html @@ -62,6 +62,28 @@ }) }); + + {% endblock %} {% block content %} @@ -183,9 +205,14 @@ {{ popup_icons_response(url['url_object'], tree_uuid) }} {% if url['url_object'].has_dl_file %} + {% if has_pandora %} + + {% else %} Download {{url['url_object'].downloaded_filename}} ({{sizeof_fmt(url['url_object'].downloaded_filesize)}}) + {% endif%} + {% else %} {% if url['url_object'].rendered_html %}