lookyloo/website/web/templates/tree.html

655 lines
25 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{% extends "main.html" %}
{% from 'bootstrap/utils.html' import render_messages %}
{% from "macros.html" import shorten_string %}
{% block title %}Capture of {{info['url']}}{% endblock %}
{% block card %}
<meta property="og:title" content="Lookyloo capture" />
<meta property="og:type" content="website"/>
<meta
property="og:description"
content="URL captured: {{info['url']}}"
/>
<meta
property="og:image"
content="https://{{public_domain}}{{ url_for('thumbnail', tree_uuid=tree_uuid, width=1200) }}"
/>
<meta property="og:image:width" content="1200"/>
<meta property="og:image:height" content="630"/>
<meta
property="og:url"
content="https://{{public_domain}}{{ url_for('tree', tree_uuid=tree_uuid) }}"
/>
<meta name="twitter:card" content="summary_large_image">
{% endblock %}
{% block scripts %}
{{ super() }}
<script src='{{ url_for('static', filename='d3.v7.min.js') }}'
integrity="{{get_sri('static', 'd3.v7.min.js')}}"
crossorigin="anonymous"></script>
<script src='{{ url_for('static', filename='tree.js') }}'
integrity="{{get_sri('static', 'tree.js')}}"
crossorigin="anonymous"></script>
<script>
$('#hashlookupModal').on('show.bs.modal', function(e) {
var button = $(e.relatedTarget);
var modal = $(this);
modal.find('.modal-body').load(button.data("remote"));
});
</script>
<script>
$('#modulesModal').on('show.bs.modal', function(e) {
var button = $(e.relatedTarget);
var modal = $(this);
modal.find('.modal-body').load(button.data("remote"));
});
$('.modulesForceRefresh').on('click',function(){
$('#modulesModal .modal-body').load("{{ url_for('trigger_modules', tree_uuid=tree_uuid, force=True) }}", function(){
$('#modulesModal').modal({show:true});
});
});
</script>
<script>
$('#categoriesModal').on('show.bs.modal', function(e) {
var button = $(e.relatedTarget);
var modal = $(this);
modal.find('.modal-body').load(button.data("remote"));
});
$('#searchCategories').submit(function(event){
var query = $("#query").val();
$('.modal-body').load("{{ url_for('categories_capture', tree_uuid=tree_uuid) }}" + query, function() {
$('#categoriesModal').modal({show:true});
});
event.preventDefault();
});
</script>
<script>
$('#statsModal').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) {
var button = $(e.relatedTarget);
var modal = $(this);
modal.find('.modal-body').load(button.data("remote"));
});
</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);
modal.find('.modal-body').load(button.data("remote"));
});
</script>
<script>
{% if urlnode_uuid %}
history.scrollRestoration = "manual";
window.addEventListener('DOMContentLoaded', (event) => {
LocateNode('{{urlnode_uuid}}');
});
{% else %}
window.addEventListener('DOMContentLoaded', (event) => {
let thumbnail = document.getElementById('screenshot_thumbnail');
thumbnail.scrollIntoView({behavior: "smooth", block: "end", inline: "center"});
});
{% endif%}
</script>
{% if auto_trigger_modules %}
<script>
$.get("{{ url_for('trigger_modules', tree_uuid=tree_uuid, auto_trigger=True) }}")
</script>
{% endif%}
{% endblock %}
{% block styles %}
{{ super() }}
<link rel="stylesheet" href="{{ url_for('static', filename='tree.css') }}">
{% endblock %}
{% block content %}
{{super()}}
<script>
var treeUUID = "{{ tree_uuid }}";
var screenshot_thumbnail = "{{ screenshot_thumbnail }}";
var enable_bookmark = {{ enable_bookmark|tojson }};
var treeData = {{ tree_json | safe }};
var parent_uuid = {{ parent_uuid|tojson }};
var capture_starttime = new Date(Date.parse("{{ info['capture_time'] }}"));
window.addEventListener('DOMContentLoaded', (event) => {
document.getElementById("start_time").innerHTML =
`${capture_starttime.getFullYear()}-${("0" + (capture_starttime.getMonth() + 1)).slice(-2)}-${("0" + capture_starttime.getDate()).slice(-2)} ${capture_starttime.toLocaleTimeString()}`;
});
</script>
{{ render_messages(container=True, dismissible=True) }}
<!-- Containers -->
<div id="menu_container_vertical" class="tree-panel-container">
<div id=menu_vertical>
<div class="menu_vertical_header">
<a href="{{ url_for('index') }}" title="Back to captures">
<img src="{{ url_for('static', filename='lookyloo.jpeg') }}" alt="Lookyloo icon"
height="110">
</a>
</div>
<hr/>
<center>
<div>
<button type="button" class="btn btn-link" data-toggle="collapse" data-target="#menu_vertical_content">
<span class="if-collapsed">
<img src="{{ url_for('static', filename='up.jpg') }}" class="arrow-down" alt="Maximize menu" height="25" width="25" title="Expand">
</span>
<span class="if-not-collapsed">
<img src="{{ url_for('static', filename='up.jpg') }}" alt="Minimize menu" height="25" width="25" title="Collapse">
</span>
</button>
</div>
</center>
<hr/>
<div id=menu_vertical_content class="collapse show">
<ul class="list-unstyled components">
<li>
<a href="#detailsModal" data-toggle="modal" data-target="#detailsModal" role="button">Capture Details</a>
</li>
<li>
<a href="https://www.lookyloo.eu/docs/main/usage.html#_investigate_a_capture" role="button">Lookyloo Manual</a>
</li>
<li>
<a href="{{ url_for('index') }}" role="button">Homepage</a>
</li>
</ul>
</div>
</div>
</div>
<div id="menu_container_horizontal" class="tree-panel-container">
<div id=menu_horizontal class="media">
<button type="button" class="btn btn-link mr-3 align-self-center" data-toggle="collapse" data-target="#menu_horizontal_content">
<span class="if-collapsed">
<img src="{{ url_for('static', filename='up.jpg') }}" class="arrow-right" alt="Maximize menu" height="25" width="25" title="Expand">
</span>
<span class="if-not-collapsed">
<img src="{{ url_for('static', filename='up.jpg') }}" class="arrow-left" alt="Minimize menu" height="25" width="25" title="Collapse">
</span>
</button>
<div id="menu_horizontal_content" class="collapse show media-body mt-0 container">
<div class="row">
<hr class="vertical">
<div class="col-sm">
<ul class="list-unstyled components">
<li>
<a href="#screenshotModal" data-toggle="modal" data-target="#screenshotModal" role="button">Page Screenshot</a>
</li>
<li>
<a href="#statsModal" data-remote="{{ url_for('stats', tree_uuid=tree_uuid) }}"
data-toggle="modal" data-target="#statsModal" role="button">Tree Statistics</a>
</li>
<li>
<a href="#modulesModal" data-remote="{{ url_for('trigger_modules', tree_uuid=tree_uuid, force=False) }}"
data-toggle="modal" data-target="#modulesModal" role="button">Third Party Reports</a>
</li>
{% if current_user.is_authenticated %}
<li>
<a href="#hashlookupModal" data-remote="{{ url_for('hashlookup', tree_uuid=tree_uuid) }}"
data-toggle="modal" data-target="#hashlookupModal" role="button">Hashlookup hits</a>
</li>
{% endif %}
</ul>
</div>
<hr class="vertical">
<div class="col-sm">
<ul class="list-unstyled components">
<li>
<a href="#urlsInPageModal" data-remote="{{ url_for('urls_rendered_page', tree_uuid=tree_uuid) }}"
data-toggle="modal" data-target="#urlsInPageModal" role="button">Run Subsequent Captures</a>
</li>
<li>
<a href="{{ url_for('recapture', tree_uuid=tree_uuid) }}" role="button">Re-Capture URL</a>
</li>
{% if has_redirects %}
<li>
<a href="{{ url_for('redirects', tree_uuid=tree_uuid) }}" role="button">Download Redirects list</a>
</li>
{% endif %}
{% if enable_mail_notification %}
<li>
<a href="#emailModal" data-toggle="modal" data-target="#emailModal" role="button">Contact Local Administrator</a>
</li>
{% endif %}
</ul>
</div>
{%if enable_categorization or (current_user.is_authenticated and misp_push) or enable_bookmark or enable_context_by_users %}
<hr class="vertical">
<div class="col-sm">
<ul class="list-unstyled components">
{% if enable_categorization %}
<li>
<a href="#categoriesModal" data-remote="{{ url_for('categories_capture', tree_uuid=tree_uuid) }}"
data-toggle="modal" data-target="#categoriesModal" role="button">Manage categories</a>
</li>
{% endif %}
{% if current_user.is_authenticated and misp_push%}
<li>
<a href="#mispPushModal" data-remote="{{ url_for('web_misp_push_view', tree_uuid=tree_uuid) }}"
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>
</li>
{% endif %}
{% if enable_context_by_users %}
<li>
<a href="#/" role="button" onclick="MarkAsKnown('{{ tree_uuid }}');">Mark all the captures' entries as known</a>
</li>
{% endif %}
</ul>
</div>
{% endif %}
</div>
</div>
</div>
</div>
<div id="legend_container" class="tree-panel-container">
<div id=legend class="collapse show">
<center>
<div style="display: inline">
<b>Legend</b>
</div>
<div style="display: inline;">
<button type="button" class="btn btn-link" data-toggle="collapse" data-target="#legend">
<img src="{{ url_for('static', filename='down.jpg') }}" alt="Minimize legend" height="25" width="25" title="Collapse">
</button>
</div>
</center>
<hr/>
<div title="The node contains at least one insecure (not HTTPS) request">
<img src="{{ url_for('static', filename='insecure.svg') }}" alt="Insecure requests"
height="20" width="20"> Unencrypted requests
</div>
<div title="This node contains only empty responses">
<img src="{{ url_for('static', filename='empty.svg') }}" alt="Empty responses"
height="20" width="20"> Empty responses
</div>
<div title="Number of cookies received in the responses of this node">
<img src="{{ url_for('static', filename='cookie_received.png') }}" alt="Cookie received"
height="20" width="20"> Cookie received
</div>
<div title="Number of cookies sent in the requests of this node">
<img src="{{ url_for('static', filename='cookie_read.png') }}" alt="Cookie read"
height="20" width="20"> Cookie read
</div>
<div title="Number of redirects initiated by the responses of this node">
<img src="{{ url_for('static', filename='redirect.png') }}" alt="Redirect"
height="20" width="20"> Redirect
</div>
<div title="Number of resources loaded from iFrames in the responses in this node">
<img src="{{ url_for('static', filename='ifr.png') }}" alt="iFrame"
height="20" width="20"> iFrame
</div>
<div title="Number of JavaScript in the responses in this node">
<img src="{{ url_for('static', filename='javascript.png') }}" alt="JavaScript"
height="20" width="20"> Javascript
</div>
<div title="Number of fonts in the responses in this node">
<img src="{{ url_for('static', filename='font.png') }}" alt="Font"
height="20" width="20"> Font
</div>
<div title="Number of HTML in the responses in this node">
<img src="{{ url_for('static', filename='html.png') }}" alt="HTML"
height="20" width="20"> HTML
</div>
<div title="Number of JSON in the responses in this node">
<img src="{{ url_for('static', filename='json.png') }}" alt="JSON"
height="20" width="20"> JSON
</div>
<div title="Number of CSS in the responses in this node">
<img src="{{ url_for('static', filename='css.png') }}" alt="CSS"
height="20" width="20"> CSS
</div>
<div title="Number of executables in the responses in this node">
<img src="{{ url_for('static', filename='exe.png') }}" alt="EXE"
height="20" width="20"> EXE
</div>
<div title="Number of images in the responses in this node">
<img src="{{ url_for('static', filename='img.png') }}" alt="Image"
height="20" width="20"> Image
</div>
<div title="Number of videos in the responses in this node">
<img src="{{ url_for('static', filename='video.png') }}" alt="Video"
height="20" width="20"> Video
</div>
<div title="Number of unknown resources in the responses in this node">
<img src="{{ url_for('static', filename='wtf.png') }}" alt="Content type not set/unknown"
height="20" width="20"> Unknown content
</div>
</div>
<div style="width: 70px; float: right;">
<center>
<button type="button" class="btn btn-link" data-toggle="collapse" data-target="#legend">
<img src="{{ url_for('static', filename='up.jpg') }}" alt="Maximize legend" height="40" width="40" title="Expand">
<b>Legend</b>
</button>
</center>
</div>
</div>
<!-- Modals -->
<div class="modal fade" id="detailsModal" 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="detailsModalLabel">Details of the capture at the time it happened</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<dl class="row">
<dt class="col-sm-2">URL captured</dt>
<dd class="col-sm-10">{{ shorten_string(info['url'], 1000) }}</dd>
<dt class="col-sm-2">Page title</dt>
<dd class="col-sm-10">{{ info['title'] }}</dd>
<dt class="col-sm-2">Capture time</dt>
<dd class="col-sm-10" id="start_time"></dd>
<dt class="col-sm-2">User Agent</dt>
<dd class="col-sm-10">{{ info['user_agent'] }}</dd>
{% if 'referer' in info and info['referer'] %}
<dt class="col-sm-2">Referer</dt>
<dd class="col-sm-10">{{ info['referer'] }}</dd>
{%endif%}
{% if meta %}
{% for k, v in meta.items() if k not in ['user_agent'] %}
<dt class="col-sm-2">{{k.title()}}</dt>
<dd class="col-sm-10">{{ v }}</dd>
{% endfor %}
{%endif%}
</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="statsModal" 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="statsModalLabel">Statistics</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
... loading statistics ...
</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="mispPushModal" 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="mispPushModalLabel">MISP Push</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 Push 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="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">
<div class="modal-header">
<h5 class="modal-title" id="screenshotModalLabel">Screenshot</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<center>
{% set screenshot_too_big = screenshot_size > 10 * 1024 * 1024 %}
{% if screenshot_too_big %}
Image too big ({{ sizeof_fmt(screenshot_size) }}) to display in the browser, the screenshot below is cropped.
</br>
{% endif %}
{% if blur_screenshot %}
<button type="button" class="btn btn-info" onclick="$('#screenshot').removeClass('blur')">Unblur</button>
{% endif %}
<a href="{{ url_for('image', tree_uuid=tree_uuid) }}" role="button" class="btn btn-info">Download</a>
</br>
</br>
<img src="{{ url_for('image', tree_uuid=tree_uuid, width=1024 if screenshot_too_big else '') }}" class="img-fluid {{ 'blur' if blur_screenshot else '' }}" id="screenshot"/>
</br>
</center>
</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="modulesModal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-xl" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="modulesModalLabel">
Reports from 3rd party services
</h4>
</br>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
</br>
<center><h5>Note that if you get an error when you click on a
link below, it probably means the capture is still ongoing.
Try reloading the page after a few seconds.</h5></center>
<div class="modal-body">
... loading results from 3rd party modules ...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-success modulesForceRefresh">Re-run all modules</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="hashlookupModal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-xl" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="hashlookupModalLabel">
Hits in Hashlookup
</h4>
</br>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
</br>
<div class="modal-body">
... loading results from hashlookup ...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
{% if enable_context_by_users %}
<div class="modal fade" id="categoriesModal" 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="categoriesModalLabel">Categorize the capture</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
... loading the categorization options ...
</div>
<p>
<form id=searchCategories>
<label for="query">Category to search</label>
<input type="text" class="form-control" name="query" id="query" placeholder="Query">
<button type="submit" class="btn btn-success">Search</button>
</form>
</p>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
{% endif %}
{% if enable_mail_notification %}
<div class="modal fade" id="emailModal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-xl" role="document">
<form role="form" action="{{ tree_uuid }}/send_mail" method=post enctype=multipart/form-data>
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="emailModalLabel">Notify by email</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>A notification of this capture will be sent to the owners of this Lookyloo instance. They may or may not act on it.</p>
<div class="form-group">
<label for="email">Email address - used to get back in touch with you if needed (optional)</label>
<input type="email" class="form-control" name="email" id="email" placeholder="Enter email">
<!-- boat fields -->
<label class="boatymcboat" for="name">Your Name</label>
<input class="boatymcboat" autocomplete="off" type="text" id="name" name="name"
placeholder="Your fav boat name here">
</div>
<div class="form-group">
<label for="comment">Please write a comment (optional)</label>
<textarea class="form-control" name="comment" id=comment rows="3"></textarea>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="confirm" onchange="document.getElementById('btn-notification').disabled = !this.checked;"></input>
<label for="force_push" class="form-check-label">{{ confirm_message }}</label>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-success" id="btn-notification" disabled=true>Send email</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</form>
</div>
</div>
{% endif %}
<div class="modal fade" id="urlsInPageModal" 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="urlsInPageModalLabel">URLs in the rendered page</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
... loading URLs in rendered page ...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
{% endblock content %}