new: Add MISP lookup

pull/210/head
Raphaël Vinot 2021-06-01 15:31:14 -07:00
parent 53ef253c94
commit 3071a1a7c9
4 changed files with 73 additions and 1 deletions

View File

@ -414,6 +414,20 @@ class Lookyloo():
to_return['pi'][ct.root_hartree.har.root_url] = self.pi.get_url_lookup(ct.root_hartree.har.root_url)
return to_return
def get_misp_occurrences(self, capture_uuid: str, /) -> Optional[Dict[str, Any]]:
if not self.misp.available:
return None
try:
ct = self.get_crawled_tree(capture_uuid)
except LookylooException:
self.logger.warning(f'Unable to get the modules responses unless the tree ({capture_uuid}) is cached.')
return None
nodes_to_lookup = ct.root_hartree.rendered_node.get_ancestors()
events = {}
for node in nodes_to_lookup:
events[node.name] = self.misp.lookup(node, ct.root_hartree.get_host_node_by_uuid(node.hostnode_uuid))
return events
def _set_capture_cache(self, capture_dir: Path, force: bool=False, redis_pipeline: Optional[Redis]=None) -> None:
'''Populate the redis cache for a capture. Mostly used on the index page.'''
if force or not self.redis.exists(str(capture_dir)):

View File

@ -19,7 +19,7 @@ from pysanejs import SaneJS
from pyeupi import PyEUPI
from pymisp import PyMISP, MISPEvent, MISPAttribute
from har2tree import CrawledTree, HostNode
from har2tree import CrawledTree, HostNode, URLNode
class MISP():
@ -121,6 +121,20 @@ class MISP():
return event
return None
def lookup(self, node: URLNode, hostnode: HostNode) -> Union[List[str], Dict]:
if self.available and self.enable_lookup:
to_lookup = [node.name, node.hostname] + hostnode.resolved_ips
if hasattr(hostnode, 'cnames'):
to_lookup += hostnode.cnames
if attributes := self.client.search(controller='attributes', value=to_lookup, pythonify=True):
if isinstance(attributes, list):
return list(set(attribute.event_id for attribute in attributes))
else:
return attributes
return []
else:
return {'error': 'Module not available or lookup not enabled.'}
class UniversalWhois():

View File

@ -338,6 +338,17 @@ def stats(tree_uuid: str):
return render_template('statistics.html', uuid=tree_uuid, stats=stats)
@app.route('/tree/<string:tree_uuid>/misp_lookup', methods=['GET'])
@flask_login.login_required
def web_misp_lookup_view(tree_uuid: str):
hits = lookyloo.get_misp_occurrences(tree_uuid)
if hits:
misp_root_url = lookyloo.misp.client.root_url
else:
misp_root_url = None
return render_template('misp_lookup.html', uuid=tree_uuid, hits=hits, misp_root_url=misp_root_url)
@app.route('/tree/<string:tree_uuid>/modules', methods=['GET'])
def modules(tree_uuid: str):
modules_responses = lookyloo.get_modules_responses(tree_uuid)
@ -551,6 +562,7 @@ def tree(tree_uuid: str, node_uuid: Optional[str]=None):
enable_categorization=enable_categorization,
enable_bookmark=enable_bookmark,
misp_push=lookyloo.misp.available and lookyloo.misp.enable_push,
misp_lookup=lookyloo.misp.available and lookyloo.misp.enable_lookup,
blur_screenshot=blur_screenshot, urlnode_uuid=hostnode_to_highlight,
auto_trigger_modules=auto_trigger_modules,
confirm_message=confirm_message if confirm_message else 'Tick to confirm.',

View File

@ -73,6 +73,13 @@
});
</script>
<script>
$('#mispLookupModal').on('show.bs.modal', function(e) {
var button = $(e.relatedTarget);
var modal = $(this);
modal.find('.modal-body').load(button.data("remote"));
});
</script>
<script>
$('#urlsInPageModal').on('show.bs.modal', function(e) {
var button = $(e.relatedTarget);
var modal = $(this);
@ -229,6 +236,12 @@
data-toggle="modal" data-target="#mispPushModal" role="button">Prepare push to MISP</a>
</li>
{% endif %}
{% if current_user.is_authenticated and misp_lookup%}
<li>
<a href="#mispLookupModal" data-remote="{{ url_for('web_misp_lookup_view', tree_uuid=tree_uuid) }}"
data-toggle="modal" data-target="#mispLookupModal" role="button">Search events on MISP</a>
</li>
{% endif %}
{% if enable_bookmark %}
<li>
<a href="#/" role="button" onclick="UnbookmarkAllNodes();">Unbookmark all nodes</a>
@ -392,6 +405,25 @@
</div>
</div>
<div class="modal fade" id="mispLookupModal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-xl" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="mispLookupModalLabel">MISP Lookup</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
... loading MISP Lookup view ...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="screenshotModal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-xl" role="document">
<div class="modal-content">