new: use multiple modals instead of changing page in favicons and ressources views

pull/887/head
Raphaël Vinot 2024-02-20 17:01:16 +01:00
parent 15e409340f
commit dcbec2efef
7 changed files with 218 additions and 193 deletions

View File

@ -1046,10 +1046,10 @@ class Lookyloo():
for domain, freq in self.indexing.get_cookie_domains(cookie_name)] for domain, freq in self.indexing.get_cookie_domains(cookie_name)]
return captures, domains return captures, domains
def get_favicon_investigator(self, favicon_sha512: str, /) -> tuple[list[tuple[str, str, str]], bytes | None]: def get_favicon_investigator(self, favicon_sha512: str, /) -> tuple[list[tuple[str, str, str, datetime]], bytes | None]:
'''Returns all the captures related to a cookie name entry, used in the web interface.''' '''Returns all the captures related to a cookie name entry, used in the web interface.'''
cached_captures = self.sorted_capture_cache([uuid for uuid in self.indexing.get_captures_favicon(favicon_sha512)]) cached_captures = self.sorted_capture_cache([uuid for uuid in self.indexing.get_captures_favicon(favicon_sha512)])
captures = [(cache.uuid, cache.title, cache.redirects[-1]) for cache in cached_captures] captures = [(cache.uuid, cache.title, cache.redirects[-1], cache.timestamp) for cache in cached_captures]
favicon = self.indexing.get_favicon(favicon_sha512) favicon = self.indexing.get_favicon(favicon_sha512)
return captures, favicon return captures, favicon

View File

@ -1,3 +1,4 @@
{% if from_popup %}
{% extends "main.html" %} {% extends "main.html" %}
{% from 'bootstrap5/utils.html' import render_messages %} {% from 'bootstrap5/utils.html' import render_messages %}
@ -13,53 +14,59 @@
}); });
</script> </script>
{% if from_popup %}
<script type="text/javascript"> <script type="text/javascript">
function openTreeInNewTab(treeUUID) { function openTreeInNewTab(treeUUID) {
window.opener.openTreeInNewTab(treeUUID); window.opener.openTreeInNewTab(treeUUID);
}; };
</script> </script>
{% endif %}
{% endblock %} {% endblock %}
{%endif%}
{% block content %} {% block content %}
<center>
<h4>{{ body_hash }}</h4> {% if from_popup %}
{% if from_popup %} <button onclick="window.history.back();" class="btn btn-primary" type="button">Go Back</button>
<button onclick="window.history.back();" class="btn btn-primary" type="button">Go Back</button> {%endif%}
{% endif %}
</center> <script type="text/javascript">
<div class="table-responsive"> new DataTable('#bodyHashDetailsTable', {
<table id="table" class="table" style="width:96%"> columnDefs: [{ width: '20%', targets: 0 },
<thead> { width: '80%', targets: 1 }],
<tr> });
<th>Hostname</th> </script>
<th>Frequency</th> <center>
</tr> <h4>{{ body_hash }}</h4>
</thead> </center>
<tbody> <table id="bodyHashDetailsTable" class="table table-striped" style="width:100%">
{% for domain, freq in domains %} <thead>
<tr> <tr>
<td> <th>Hostname</th>
{{ domain }} <th>Frequency</th>
</td> </tr>
<td>{{ freq }}</td> </thead>
</tr> <tbody>
{% endfor %} {% for domain, freq in domains %}
</tbody> <tr>
</table> <td>
</div> {{ domain }}
<p>The same file was seen in these captures:</p> </td>
<ul> <td>{{ freq }}</td>
{% for capture_uuid, title in captures %} </tr>
<li> {% endfor %}
{% if from_popup %} </tbody>
<a href="#/" onclick="openTreeInNewTab('{{ capture_uuid }}')">{{ title }}</a> </table>
{% else %} </div>
<a href="{{ url_for('tree', tree_uuid=capture_uuid) }}")">{{ title }}</a> <p>The same file was seen in these captures:</p>
{% endif %} <ul>
</li> {% for capture_uuid, title in captures %}
{% endfor %} <li>
</ul> {% if from_popup %}
<a href="#/" onclick="openTreeInNewTab('{{ capture_uuid }}')">{{ title }}</a>
{% else %}
<a href="{{ url_for('tree', tree_uuid=capture_uuid) }}">{{ title }}</a>
{% endif %}
</li>
{% endfor %}
</ul>
{% endblock %} {% endblock %}

View File

@ -1,39 +1,37 @@
{% extends "main.html" %} <script type="text/javascript">
new DataTable('#faviconDetailsTable', {
columnDefs: [{ width: '40%', targets: 0 },
{ width: '40%', targets: 1 },
{ width: '20%', targets: 2 }],
});
</script>
{% from 'bootstrap5/utils.html' import render_messages %} <center>
<img src="data:image/ico;base64,{{ b64_favicon }}" style="width:64px;height:64px;"/>
{% block title %}Favicon: {{ favicon_sha512 }}{% endblock %} </center>
<table id="faviconDetailsTable" class="table table-striped" style="width:100%">
{% block content %} <thead>
<center> <tr>
<h2>{{ favicon_sha512 }}</h2> <th>Capture Title</th>
<img src="data:image/ico;base64,{{ b64_favicon }}" style="width:32px;height:32px;"/> <th>Landing page</th>
</center> <th>Capture Time</th>
<p>The same favicon was seen in these captures:</p> </tr>
<ul> </thead>
<div class="table-responsive"> <tbody>
<table id="table" class="table"> {% for capture_uuid, title, landing_page, capture_time in captures %}
<thead> <tr>
<tr> <td>
<th>Capture Title</th> <a href="{{ url_for('tree', tree_uuid=capture_uuid) }}">
<th>Landing page</th> {{ title }}
</tr> </a>
</thead> </td>
<tbody> <td>
{% for capture_uuid, title, landing_page in captures %} {{landing_page}}
<tr> </td>
<td> <td>
<a href="{{ url_for('tree', tree_uuid=capture_uuid) }}"> {{capture_time}}
{{ title }} </td>
</a> </tr>
</td> {% endfor %}
<td> </tbody>
{{landing_page}} </table>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</ul>
{% endblock %}

View File

@ -4,68 +4,75 @@
{% if not circl_pdns and not riskiq %} {% if not circl_pdns and not riskiq %}
No historical data available No historical data available
{%else%} {%else%}
{% if circl_pdns %} {% if circl_pdns %}
<center> <script type="text/javascript">
<h1 class="display-4">CIRCL Passive DNS new DataTable('#CIRCL_pdns_table');
<div class="help-tip" title="Click for more details" </script>
onclick="location.href='https://www.circl.lu/services/passive-dns/';"
style="cursor: pointer;"> <center>
</div> <h1 class="display-4">CIRCL Passive DNS
</h1> <div class="help-tip" title="Click for more details"
{% for query, responses in circl_pdns.items() if responses %} onclick="location.href='https://www.circl.lu/services/passive-dns/';"
<div> style="cursor: pointer;">
<h3>{{query}}</h3> </div>
<table class="table"> </h1>
{% for query, responses in circl_pdns.items() if responses %}
<div>
<h3>{{query}}</h3>
<table id= "CIRCL_pdns_table" class="table table-striped" style="width:100%">
<thead>
<tr>
<th class="col-sm-2" scope="col">First seen</th>
<th class="col-sm-2" scope="col">Last seen</th>
<th class="col-sm-1" scope="col">RR Type</th>
<th class="col-sm-2" scope="col">R Data</th>
<th scope="col">RR Name</th>
</thead>
<tbody>
{%for response in responses %}
<tr>
<td>{{response.time_first_datetime}}</td>
<td>{{response.time_last_datetime}}</td>
<td>{{response.rrtype}}</td>
<td>{{response.rdata}}</td>
<td>{{response.rrname}}</td>
</tr>
{% endfor %}
</table>
</div>
{%endfor%}
</center>
{% endif%}
{% if riskiq %}
<hr>
<script type="text/javascript">
new DataTable('#RiskIQ_pdns_table');
</script>
<center>
<h1 class="display-4">RiskIQ</h1>
<div>
<h3>{{riskiq['queryValue']}}</h3>
<h4>{{riskiq['firstSeen']}} - {{ riskiq['lastSeen']}}</h4>
<table id="RiskIQ_pdns_table" class="table table-striped" style="width:100%">
<thead> <thead>
<tr> <tr>
<th class="col-sm-2" scope="col">First seen</th> <th class="col-sm-2" scope="col">First seen</th>
<th class="col-sm-2" scope="col">Last seen</th> <th class="col-sm-2" scope="col">Last seen</th>
<th class="col-sm-1" scope="col">RR Type</th> <th class="col-sm-1" scope="col">Type</th>
<th class="col-sm-2" scope="col">R Data</th> <th scope="col">Resolve</th>
<th scope="col">RR Name</th>
</thead> </thead>
<tbody> <tbody>
{%for response in responses %} {% for entry in riskiq['results'] %}
<tr> <tr>
<td>{{response.time_first_datetime}}</td> <td>{{entry['firstSeen']}}</td>
<td>{{response.time_last_datetime}}</td> <td>{{entry['lastSeen']}}</td>
<td>{{response.rrtype}}</td> <td>{{entry['recordType']}}</td>
<td>{{response.rdata}}</td> <td>{{entry['resolve']}}</td>
<td>{{response.rrname}}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
</div> </div>
{%endfor%} </center>
</center> {% endif%}
{% endif%}
{% if riskiq %}
<hr>
<center>
<h1 class="display-4">RiskIQ</h1>
<div>
<h3>{{riskiq['queryValue']}}</h3>
<h4>{{riskiq['firstSeen']}} - {{ riskiq['lastSeen']}}</h4>
<table class="table">
<thead>
<tr>
<th class="col-sm-2" scope="col">First seen</th>
<th class="col-sm-2" scope="col">Last seen</th>
<th class="col-sm-1" scope="col">Type</th>
<th scope="col">Resolve</th>
</thead>
<tbody>
{% for entry in riskiq['results'] %}
<tr>
<td>{{entry['firstSeen']}}</td>
<td>{{entry['lastSeen']}}</td>
<td>{{entry['recordType']}}</td>
<td>{{entry['resolve']}}</td>
</tr>
{% endfor %}
</table>
</div>
</center>
{% endif%}
{% endif%} {% endif%}
</div> </div>

View File

@ -91,6 +91,13 @@
}); });
</script> </script>
<script> <script>
$('#faviconDetailsModal').on('show.bs.modal', function(e) {
var button = $(e.relatedTarget);
var modal = $(this);
modal.find('.modal-body').load(button.data("remote"));
});
</script>
<script>
$('#bodyHashesModal').on('show.bs.modal', function(e) { $('#bodyHashesModal').on('show.bs.modal', function(e) {
var button = $(e.relatedTarget); var button = $(e.relatedTarget);
var modal = $(this); var modal = $(this);
@ -98,6 +105,13 @@
}); });
</script> </script>
<script> <script>
$('#bodyHashDetailsModal').on('show.bs.modal', function(e) {
var button = $(e.relatedTarget);
var modal = $(this);
modal.find('.modal-body').load(button.data("remote"));
});
</script>
<script>
$('#mispPushModal').on('show.bs.modal', function(e) { $('#mispPushModal').on('show.bs.modal', function(e) {
var button = $(e.relatedTarget); var button = $(e.relatedTarget);
var modal = $(this); var modal = $(this);
@ -537,6 +551,26 @@
</div> </div>
</div> </div>
<div class="modal fade" id="faviconDetailsModal" 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="faviconDetailsModalLabel">Other occurrences of the favicon</h5>
<button type="button" class="btn btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
... loading favicon details ...
</div>
<div class="modal-footer">
<a class="btn btn-primary" href="#faviconsModal"
data-remote="{{ url_for('tree_favicons', tree_uuid=tree_uuid) }}"
data-bs-toggle="modal" data-bs-target="#faviconsModal" role="button">Back to capture's favicons</a>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="bodyHashesModal" tabindex="-1" role="dialog"> <div class="modal fade" id="bodyHashesModal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-xl" role="document"> <div class="modal-dialog modal-xl" role="document">
<div class="modal-content"> <div class="modal-content">
@ -554,6 +588,26 @@
</div> </div>
</div> </div>
<div class="modal fade" id="bodyHashDetailsModal" 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="bodyHashDetailsModalLabel">Other occurrences of the ressource</h5>
<button type="button" class="btn btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
... loading ressource details ...
</div>
<div class="modal-footer">
<a class="btn btn-primary" href="#bodyHashesModal"
data-remote="{{ url_for('tree_body_hashes', tree_uuid=tree_uuid) }}"
data-bs-toggle="modal" data-bs-target="#bodyHashesModal" role="button">Back to capture's ressources</a>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="mispPushModal" tabindex="-1" role="dialog"> <div class="modal fade" id="mispPushModal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-xl" role="document"> <div class="modal-dialog modal-xl" role="document">
<div class="modal-content"> <div class="modal-content">

View File

@ -1,35 +1,13 @@
<script type="text/javascript"> <script type="text/javascript">
$('#bodyHashesTable') new DataTable('#bodyHashesTable', {
.on('order.dt', () => { columnDefs: [{ width: '10%', targets: 0 },
$(function () { { width: '10%', targets: 1 },
$('[data-bs-toggle="tooltip"]').tooltip() { width: '60%', targets: 2 },
}) { width: '20%', targets: 3 }],
}) });
.on('search.dt', () => {
$(function () {
$('[data-bs-toggle="tooltip"]').tooltip()
})
})
.on('page.dt', () => {
$(function () {
$('[data-bs-toggle="tooltip"]').tooltip()
})
})
.DataTable( {
"order": [[ 1, "desc" ]],
"pageLength": 50
});
</script> </script>
{% if from_popup %} <table id="bodyHashesTable" class="table table-striped" style="width:100%">
<script type="text/javascript">
function openTreeInNewTab(treeUUID) {
window.opener.openTreeInNewTab(treeUUID);
};
</script>
{% endif %}
<table id="bodyHashesTable" class="table w-auto">
<thead> <thead>
<tr> <tr>
<th>File type</th> <th>File type</th>
@ -60,7 +38,10 @@
<td><p class="text-break">{{ info['node'].name }}</p></td> <td><p class="text-break">{{ info['node'].name }}</p></td>
<td> <td>
<span class="d-inline-block text-truncate" style="max-width: 200px;"> <span class="d-inline-block text-truncate" style="max-width: 200px;">
<a href="{{ url_for('body_hash_details', body_hash=body_hash) }}">{{body_hash}}</a> <a href="#bodyHashDetailsModal" data-remote="{{ url_for('body_hash_details', body_hash=body_hash) }}"
data-bs-toggle="modal" data-bs-target="#bodyHashDetailsModal" role="button">
{{body_hash}}
</a>
</span> </span>
</td> </td>
</tr> </tr>

View File

@ -1,35 +1,12 @@
<script type="text/javascript"> <script type="text/javascript">
$('#faviconsTable') new DataTable('#faviconsTable', {
.on('order.dt', () => { columnDefs: [{ width: '20%', targets: 0 },
$(function () { { width: '40%', targets: 1 },
$('[data-bs-toggle="tooltip"]').tooltip() { width: '40%', targets: 2 }],
}) });
})
.on('search.dt', () => {
$(function () {
$('[data-bs-toggle="tooltip"]').tooltip()
})
})
.on('page.dt', () => {
$(function () {
$('[data-bs-toggle="tooltip"]').tooltip()
})
})
.DataTable( {
"order": [[ 1, "desc" ]],
"pageLength": 50
});
</script> </script>
{% if from_popup %} <table id="faviconsTable" class="table table-striped" style="width:100%">
<script type="text/javascript">
function openTreeInNewTab(treeUUID) {
window.opener.openTreeInNewTab(treeUUID);
};
</script>
{% endif %}
<table id="faviconsTable" class="table w-auto">
<thead> <thead>
<tr> <tr>
<th>Favicon</th> <th>Favicon</th>
@ -41,7 +18,8 @@
{% for favicon_sha512, freq, number_captures, b64_favicon in favicons %} {% for favicon_sha512, freq, number_captures, b64_favicon in favicons %}
<tr> <tr>
<td> <td>
<a href="{{ url_for('favicon_detail', favicon_sha512=favicon_sha512) }}"> <a href="#faviconDetailsModal" data-remote="{{ url_for('favicon_detail', favicon_sha512=favicon_sha512) }}"
data-bs-toggle="modal" data-bs-target="#faviconDetailsModal" role="button">
<img src="data:image/ico;base64,{{ b64_favicon }}" style="width:32px;height:32px;"/> <img src="data:image/ico;base64,{{ b64_favicon }}" style="width:32px;height:32px;"/>
</a> </a>
</td> </td>