new: Submit to Pandora button for file URLs

pull/502/head
Raphaël Vinot 2022-08-23 17:48:36 +02:00
parent f232eba662
commit f4dfa0343e
9 changed files with 81 additions and 12 deletions

View File

@ -14,6 +14,11 @@
"autosubmit": false, "autosubmit": false,
"allow_auto_trigger": false "allow_auto_trigger": false
}, },
"Pandora": {
"url": "http://127.0.0.1:6100",
"autosubmit": false,
"allow_auto_trigger": false
},
"SaneJS": { "SaneJS": {
"enabled": true, "enabled": true,
"allow_auto_trigger": 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.", "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.", "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", "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/)" "RiskIQ": "Module to query RiskIQ (https://community.riskiq.com/)"
} }
} }

View File

@ -38,7 +38,7 @@ from .helpers import (CaptureStatus, get_captures_dir, get_email_template,
from .indexing import Indexing from .indexing import Indexing
from .modules import (MISP, PhishingInitiative, UniversalWhois, from .modules import (MISP, PhishingInitiative, UniversalWhois,
UrlScan, VirusTotal, Phishtank, Hashlookup, UrlScan, VirusTotal, Phishtank, Hashlookup,
RiskIQ, RiskIQError) RiskIQ, RiskIQError, Pandora)
class Lookyloo(): class Lookyloo():
@ -90,6 +90,10 @@ class Lookyloo():
if not self.riskiq.available: if not self.riskiq.available:
self.logger.warning('Unable to setup the RiskIQ module') 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.logger.info('Initializing context...')
self.context = Context() self.context = Context()
self.logger.info('Context initialized.') self.logger.info('Context initialized.')

View File

@ -7,6 +7,7 @@ from .sanejs import SaneJavaScript # noqa
from .urlscan import UrlScan # noqa from .urlscan import UrlScan # noqa
from .uwhois import UniversalWhois # noqa from .uwhois import UniversalWhois # noqa
from .vt import VirusTotal # noqa from .vt import VirusTotal # noqa
from .pandora import Pandora # noqa
from .phishtank import Phishtank # noqa from .phishtank import Phishtank # noqa
from .hashlookup import HashlookupModule as Hashlookup # noqa from .hashlookup import HashlookupModule as Hashlookup # noqa
from .riskiq import RiskIQ, RiskIQError # noqa from .riskiq import RiskIQ, RiskIQError # noqa

26
poetry.lock generated
View File

@ -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)"] url = ["pyfaup (>=1.2,<2.0)", "chardet (>=5.0.0,<6.0.0)"]
brotli = ["urllib3[brotli] (>=1.26.11,<2.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]] [[package]]
name = "pyparsing" name = "pyparsing"
version = "3.0.9" version = "3.0.9"
@ -1217,7 +1231,7 @@ python-versions = "*"
[[package]] [[package]]
name = "types-redis" name = "types-redis"
version = "4.3.16" version = "4.3.17"
description = "Typing stubs for redis" description = "Typing stubs for redis"
category = "dev" category = "dev"
optional = false optional = false
@ -1413,7 +1427,7 @@ misp = ["python-magic", "pydeep2"]
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = ">=3.8,<3.11" python-versions = ">=3.8,<3.11"
content-hash = "b813c16a36c8bfd612488d2fdfce36b34234e03fae997dc56a6613672c31d9b4" content-hash = "0dcbbf79ed17ddfa5f0f66c8ffa0b0b6025527aa287761d1730a992be6b42dab"
[metadata.files] [metadata.files]
aiohttp = [ 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-py3-none-any.whl", hash = "sha256:3499dc55819e874eeecd7d1b10229cb957600a52452ca5360db3b32f21714718"},
{file = "pymisp-2.4.160.1.tar.gz", hash = "sha256:d6cf306100d7c936951db9cb1bff53276a94d75b3ff5ae4c35a952f001169021"}, {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 = [ pyparsing = [
{file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
{file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, {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"}, {file = "types_python_dateutil-2.8.19-py3-none-any.whl", hash = "sha256:6284df1e4783d8fc6e587f0317a81333856b872a6669a282f8a325342bce7fa8"},
] ]
types-redis = [ types-redis = [
{file = "types-redis-4.3.16.tar.gz", hash = "sha256:ed53e35eac4303ef70cf7f5c205e210f2238b7fdd9306b7f8676669c1070943e"}, {file = "types-redis-4.3.17.tar.gz", hash = "sha256:03b023c08acf344f4f0821cc1c7e4dbecb7b17bc5483927c3e73d80f7fe1768e"},
{file = "types_redis-4.3.16-py3-none-any.whl", hash = "sha256:41da87dc80f39573a71873e4265f181d9628b0a2a862e850ecc896a0cd6cacd2"}, {file = "types_redis-4.3.17-py3-none-any.whl", hash = "sha256:a34c4e7aafa4b2fb9090d3a7f3ad0ac969089c7b4a05c21dff593a0c37405916"},
] ]
types-requests = [ types-requests = [
{file = "types-requests-2.28.9.tar.gz", hash = "sha256:feaf581bd580497a47fe845d506fa3b91b484cf706ff27774e87659837de9962"}, {file = "types-requests-2.28.9.tar.gz", hash = "sha256:feaf581bd580497a47fe845d506fa3b91b484cf706ff27774e87659837de9962"},

View File

@ -67,6 +67,7 @@ playwrightcapture = "^1.14.3"
passivetotal = "^2.5.9" passivetotal = "^2.5.9"
werkzeug = "2.1.2" werkzeug = "2.1.2"
filetype = "^1.1.0" filetype = "^1.1.0"
pypandora = "^1.0.2"
[tool.poetry.extras] [tool.poetry.extras]
misp = ['python-magic', 'pydeep2'] misp = ['python-magic', 'pydeep2']
@ -74,7 +75,7 @@ misp = ['python-magic', 'pydeep2']
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
mypy = "^0.971" mypy = "^0.971"
ipython = "^8.4.0" ipython = "^8.4.0"
types-redis = "^4.3.16" types-redis = "^4.3.17"
types-requests = "^2.28.9" types-requests = "^2.28.9"
types-Flask = "^1.1.6" types-Flask = "^1.1.6"
types-pkg-resources = "^0.1.3" types-pkg-resources = "^0.1.3"

View File

@ -246,6 +246,7 @@ def hostnode_popup(tree_uuid: str, node_uuid: str):
hostnode_uuid=node_uuid, hostnode_uuid=node_uuid,
hostnode=hostnode, hostnode=hostnode,
urls=urls, urls=urls,
has_pandora=lookyloo.pandora.available,
enable_context_by_users=enable_context_by_users, enable_context_by_users=enable_context_by_users,
uwhois_available=lookyloo.uwhois.available) 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) return render_template('tree_body_hashes.html', tree_uuid=tree_uuid, body_hashes=body_hashes)
@app.route('/tree/<string:tree_uuid>/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 ##### # ##### helpers #####
def index_generic(show_hidden: bool=False, show_error: bool=True, category: Optional[str]=None): def index_generic(show_hidden: bool=False, show_error: bool=True, category: Optional[str]=None):

View File

@ -34,7 +34,7 @@
"stats.css": "/kY943FwWBTne4IIyf7iBROSfbGd82TeBicEXqKkRwawMVRIvM/Pk5MRa7okUyGIxaDjFQGmV/U1vy+PhN6Jbw==", "stats.css": "/kY943FwWBTne4IIyf7iBROSfbGd82TeBicEXqKkRwawMVRIvM/Pk5MRa7okUyGIxaDjFQGmV/U1vy+PhN6Jbw==",
"stats_graph.js": "0OEouA6NAxLG2wMd7D2vtGoMrXKna7My98Euc6ecyfdO4/6mIJS87vzISOS4zSZ8u4ehpa+p7E0nWhsXXE7H/Q==", "stats_graph.js": "0OEouA6NAxLG2wMd7D2vtGoMrXKna7My98Euc6ecyfdO4/6mIJS87vzISOS4zSZ8u4ehpa+p7E0nWhsXXE7H/Q==",
"tree.css": "THJ9LnnSJ91DSTvrYoOCxRrenGgwsgG5zKo+eZLH2rRFHn6lpX9UpmRhRic4th9ZYuM9/NJUS7LqYBDRPPnB1Q==", "tree.css": "THJ9LnnSJ91DSTvrYoOCxRrenGgwsgG5zKo+eZLH2rRFHn6lpX9UpmRhRic4th9ZYuM9/NJUS7LqYBDRPPnB1Q==",
"tree.js": "gHr2HiDbQYfVhBtt95VP6+f7k4neVnfcXV66o4oKg7wB3HVNs/XrTCXpthS3W8yfouySLpZoTVTaPHrAvs5wwg==", "tree.js": "H6ibjUxG7eD+Dz+jFBnERtxTIdR1aPssd86rCrwHH8CHUySn70aCE3mCmGYwNWw0GCpGT1IYWuZ+K0us+selNg==",
"up.jpg": "d1ljZJ9f5JekyM6RLFFH2Ua44j6neiQBdUIXOenRTjGppQr3JaeglpQIH6BjPCJL177+TH52U3UIRNS5YAyKIg==", "up.jpg": "d1ljZJ9f5JekyM6RLFFH2Ua44j6neiQBdUIXOenRTjGppQr3JaeglpQIH6BjPCJL177+TH52U3UIRNS5YAyKIg==",
"up_right.jpg": "OMmz+n+MxR34P8/fn5t4DkqKqdJRzQbXQ7fAi2lhkZIJGhVs2vIyY1f2hpYoBxDAX1OcYsSE2lqIR2vXNDGZsA==", "up_right.jpg": "OMmz+n+MxR34P8/fn5t4DkqKqdJRzQbXQ7fAi2lhkZIJGhVs2vIyY1f2hpYoBxDAX1OcYsSE2lqIR2vXNDGZsA==",
"video.png": "gJtmkfr8I1Kw43pYEKjg6CAjgmhl1vIBKBQ3ZkxCu3wvxQm+6kf93iLrrFiY2WuiXzxEn2Leu52GJzmVN5id0g==", "video.png": "gJtmkfr8I1Kw43pYEKjg6CAjgmhl1vIBKBQ3ZkxCu3wvxQm+6kf93iLrrFiY2WuiXzxEn2Leu52GJzmVN5id0g==",

View File

@ -157,11 +157,7 @@ if (parent_uuid != null) {
}; };
function openTreeInNewTab(capture_uuid, hostnode_uuid=null) { function openURLInNewTab(url) {
let url = `/tree/${capture_uuid}`;
if (hostnode_uuid != null) {
url += `/${hostnode_uuid}`;
}
let win = window.open(url, '_blank'); let win = window.open(url, '_blank');
if (win == null) { if (win == null) {
return false; return false;
@ -170,6 +166,14 @@ function openTreeInNewTab(capture_uuid, hostnode_uuid=null) {
return true; 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) { function open_hostnode_popup(hostnode_uuid) {
let win = window.open(`/tree/${treeUUID}/host/${hostnode_uuid}`, '_blank', 'width=1024,height=768,left=200,top=100'); let win = window.open(`/tree/${treeUUID}/host/${hostnode_uuid}`, '_blank', 'width=1024,height=768,left=200,top=100');
if (win == null) { if (win == null) {

View File

@ -62,6 +62,28 @@
}) })
}); });
</script> </script>
<script>
function submit_pandora(){
fetch("{{ url_for('pandora_submit', tree_uuid=tree_uuid)}}", {
method: "GET",
})
.then(response => response.json())
.then(data => {
openURLInNewTab(data.link)
})
.catch((error) => {
throw new Error(error);
});
};
let openURLInNewTab = (url) => {
let success = window.opener.openURLInNewTab(url);
if (! success) {
alert("Your browser doesn't allow Lookyloo to open a new tab. There should be an icon on the right side of your URL bar *in the main window* to allow it.");
}
}
</script>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
@ -183,9 +205,14 @@
{{ popup_icons_response(url['url_object'], tree_uuid) }} {{ popup_icons_response(url['url_object'], tree_uuid) }}
{% if url['url_object'].has_dl_file %} {% if url['url_object'].has_dl_file %}
{% if has_pandora %}
<button id="pandora_submit_button" type="button" class="btn btn-primary" onclick="submit_pandora()">Submit to Pandora</button>
{% else %}
<a href="{{ url_for('data', tree_uuid=tree_uuid)}}"> <a href="{{ url_for('data', tree_uuid=tree_uuid)}}">
Download {{url['url_object'].downloaded_filename}} Download {{url['url_object'].downloaded_filename}}
</a> ({{sizeof_fmt(url['url_object'].downloaded_filesize)}}) </a> ({{sizeof_fmt(url['url_object'].downloaded_filesize)}})
{% endif%}
{% else %} {% else %}
{% if url['url_object'].rendered_html %} {% if url['url_object'].rendered_html %}
<a href="{{ url_for('urlnode_rendered_content', tree_uuid=tree_uuid, node_uuid=url['url_object'].uuid) }}"> <a href="{{ url_for('urlnode_rendered_content', tree_uuid=tree_uuid, node_uuid=url['url_object'].uuid) }}">