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,
"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/)"
}
}

View File

@ -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.')

View File

@ -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

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)"]
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"},

View File

@ -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"

View File

@ -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/<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 #####
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_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==",

View File

@ -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) {

View File

@ -62,6 +62,28 @@
})
});
</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 %}
{% block content %}
@ -183,9 +205,14 @@
{{ popup_icons_response(url['url_object'], tree_uuid) }}
{% 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)}}">
Download {{url['url_object'].downloaded_filename}}
</a> ({{sizeof_fmt(url['url_object'].downloaded_filesize)}})
{% endif%}
{% else %}
{% if url['url_object'].rendered_html %}
<a href="{{ url_for('urlnode_rendered_content', tree_uuid=tree_uuid, node_uuid=url['url_object'].uuid) }}">