mirror of https://github.com/CIRCL/lookyloo
chg: Improve and normalize hostnode popup
parent
489bb52e12
commit
a8b0464afa
|
@ -279,6 +279,7 @@ def get_icon(icon_id: str) -> Icon | None:
|
|||
|
||||
|
||||
app.jinja_env.globals.update(get_icon=get_icon)
|
||||
app.jinja_env.globals.update(generic_type=mimetype_to_generic)
|
||||
|
||||
|
||||
def get_tz_info() -> tuple[str | None, str, set[str]]:
|
||||
|
@ -366,8 +367,7 @@ def get_all_body_hashes(capture_uuid: str, /) -> dict[str, dict[str, int | str |
|
|||
continue
|
||||
if node.body_hash not in to_return:
|
||||
total_captures = get_indexing(flask_login.current_user).get_captures_body_hash_count(node.body_hash)
|
||||
generic_type = mimetype_to_generic(node.mimetype)
|
||||
to_return[node.body_hash] = {'total_captures': total_captures, 'generic_type': generic_type, 'nodes': []}
|
||||
to_return[node.body_hash] = {'total_captures': total_captures, 'mimetype': node.mimetype, 'nodes': []}
|
||||
to_return[node.body_hash]['nodes'].append((node, False)) # type: ignore[union-attr]
|
||||
# get embedded retources (if any) - need their type too
|
||||
if 'embedded_ressources' in node.features:
|
||||
|
@ -375,8 +375,7 @@ def get_all_body_hashes(capture_uuid: str, /) -> dict[str, dict[str, int | str |
|
|||
for h, blob in blobs:
|
||||
if h not in to_return:
|
||||
total_captures = get_indexing(flask_login.current_user).get_captures_body_hash_count(h)
|
||||
generic_type = mimetype_to_generic(mimetype)
|
||||
to_return[h] = {'total_captures': total_captures, 'generic_type': generic_type, 'nodes': []}
|
||||
to_return[h] = {'total_captures': total_captures, 'mimetype': mimetype, 'nodes': []}
|
||||
to_return[h]['nodes'].append((node, True)) # type: ignore[union-attr]
|
||||
return to_return
|
||||
|
||||
|
@ -548,7 +547,7 @@ def get_hostnode_investigator(capture_uuid: str, /, node_uuid: str) -> tuple[Hos
|
|||
# Index lookup
|
||||
# %%% Full body %%%
|
||||
if freq := get_indexing(flask_login.current_user).get_captures_body_hash_count(url.body_hash):
|
||||
to_append['body_hash_details'] = {'hash_freq': freq}
|
||||
to_append['body_hash_freq'] = freq
|
||||
|
||||
# %%% Embedded ressources %%%
|
||||
if hasattr(url, 'embedded_ressources') and url.embedded_ressources:
|
||||
|
@ -1778,7 +1777,18 @@ def favicon_detail(favicon_sha512: str) -> str:
|
|||
@app.route('/body_hashes/<string:body_hash>', methods=['GET'])
|
||||
def body_hash_details(body_hash: str) -> str:
|
||||
from_popup = True if (request.args.get('from_popup') and request.args.get('from_popup') == 'True') else False
|
||||
return render_template('body_hash.html', body_hash=body_hash, from_popup=from_popup)
|
||||
filename = ''
|
||||
mimetype = ''
|
||||
b64 = ''
|
||||
if uuids := get_indexing(flask_login.current_user).get_hash_uuids(body_hash):
|
||||
# got UUIDs for this hash
|
||||
capture_uuid, urlnode_uuid = uuids
|
||||
if ressource := lookyloo.get_ressource(capture_uuid, urlnode_uuid, body_hash):
|
||||
filename, body, mimetype = ressource
|
||||
if mimetype_to_generic(mimetype) == 'image':
|
||||
b64 = base64.b64encode(body.read()).decode()
|
||||
return render_template('body_hash.html', body_hash=body_hash, from_popup=from_popup,
|
||||
filename=filename, mimetype=mimetype, b64=b64)
|
||||
|
||||
|
||||
@app.route('/urls/<string:url>', methods=['GET'])
|
||||
|
|
|
@ -128,8 +128,10 @@ def get_indexing(user: User | None) -> Indexing:
|
|||
return get_indexing_cache(full=bool(user and user.is_authenticated))
|
||||
|
||||
|
||||
def mimetype_to_generic(mimetype: str) -> str:
|
||||
if 'javascript' in mimetype or 'ecmascript' in mimetype or mimetype.startswith('js'):
|
||||
def mimetype_to_generic(mimetype: str | None) -> str:
|
||||
if not mimetype or mimetype == 'none':
|
||||
return 'unset_mimetype'
|
||||
elif 'javascript' in mimetype or 'ecmascript' in mimetype or mimetype.startswith('js'):
|
||||
return 'js'
|
||||
elif (mimetype.startswith('image')
|
||||
or mimetype.startswith('img')
|
||||
|
@ -180,7 +182,5 @@ def mimetype_to_generic(mimetype: str) -> str:
|
|||
elif ('application/gzip' in mimetype
|
||||
or 'application/zip' in mimetype):
|
||||
return 'archive'
|
||||
elif not mimetype or mimetype == 'none':
|
||||
return 'unset_mimetype'
|
||||
else:
|
||||
return 'unknown_mimetype'
|
||||
|
|
|
@ -17,8 +17,24 @@
|
|||
{%endif%}
|
||||
|
||||
<center>
|
||||
<h6>{{ body_hash }}</h6>
|
||||
<a href="{{ url_for('ressource_by_hash', sha512=body_hash) }}">Download</a>
|
||||
<p class="lead">
|
||||
{% if filename %}
|
||||
Filename: <b title="The file may have different names across the captures, this is one of them.">{{ filename }}</b><br>
|
||||
{% endif %}
|
||||
{% if mimetype %}
|
||||
Mimetype: <b>{{ mimetype }}</b><br>
|
||||
{% endif %}
|
||||
Hash:<br> <span style="font-size: 70%;">{{ body_hash }}</span><br>
|
||||
{% if b64 %}
|
||||
Preview:<br>
|
||||
<a href="{{ url_for('ressource_by_hash', sha512=body_hash) }}">
|
||||
<img class="border rounded border-3" src="data:{{mimetype}};base64,{{ b64 }}" style="max-width: 256px;max-height: 256px;"
|
||||
title="Click to download"/>
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{{ url_for('ressource_by_hash', sha512=body_hash) }}">Download</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
</center>
|
||||
|
||||
<table id="bodyHashDetailsTable" class="table table-striped" style="width:100%" data-bodyhash="{{body_hash}}">
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
{% from "macros.html" import known_content_details %}
|
||||
{% from "macros.html" import ressource_legitimacy_details %}
|
||||
{% from "macros.html" import indexed_cookies %}
|
||||
{% from "macros.html" import popup_icons_request %}
|
||||
{% from "macros.html" import popup_icons_response %}
|
||||
{% from "macros.html" import request_cookies_icon %}
|
||||
{% from "macros.html" import response_cookies_icon %}
|
||||
{% from "macros.html" import hash_info%}
|
||||
{% from "macros.html" import redirect_response %}
|
||||
{% from "macros.html" import shorten_string %}
|
||||
{% from "macros.html" import other_captures_table %}
|
||||
{% from "macros.html" import get_ressource_button %}
|
||||
{% from "macros.html" import context_form %}
|
||||
{% from "macros.html" import pandora_submit %}
|
||||
|
||||
|
@ -127,7 +128,7 @@
|
|||
</div>
|
||||
<br>
|
||||
{# Start list of URLs #}
|
||||
<ul class="list-group-flush">
|
||||
<ul class="list-group list-group-flush">
|
||||
{% for url in urls %}
|
||||
{# URL Display #}
|
||||
<li class="list-group-item">
|
||||
|
@ -156,34 +157,47 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
{% if url['url_object'].security_details %}
|
||||
<div>TLS certificate details:
|
||||
<ul>
|
||||
{% for k, v in url['url_object'].security_details.items() %}
|
||||
<li><b>{{k}}</b>: {{v}}</li>
|
||||
{% endfor%}
|
||||
</ul>
|
||||
<div class="accordion accordion-flush" id="accordionTLS_{{url['url_object'].uuid}}">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTLS_{{url['url_object'].uuid}}" aria-expanded="false" aria-controls="collapseTLS">
|
||||
Show certificate details
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseTLS_{{url['url_object'].uuid}}" class="accordion-collapse collapse" data-bs-parent="#accordionTLS_{{url['url_object'].uuid}}">
|
||||
<div class="accordion-body">
|
||||
<ul>
|
||||
{% for k, v in url['url_object'].security_details.items() %}
|
||||
<li><b>{{k}}</b>: {{v}}</li>
|
||||
{% endfor%}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div></div>
|
||||
<ul class="list-group">
|
||||
|
||||
{% if url['url_object'].posted_data or url['cookies_sent'] %}
|
||||
<li class="list-group-item">
|
||||
<p class="h4">Request</p>
|
||||
{{ popup_icons_request(url['url_object'], tree_uuid) }}
|
||||
<p class="h4">Request {{ request_cookies_icon(url['url_object'], tree_uuid) }}</p>
|
||||
<hr>
|
||||
|
||||
<div class="d-grid gap-2">
|
||||
{% if url['url_object'].posted_data %}
|
||||
<div>
|
||||
<a href="{{ url_for('urlnode_post_request', tree_uuid=tree_uuid, node_uuid=url['url_object'].uuid) }}">
|
||||
Download posted data
|
||||
</a><br>
|
||||
{% if url['url_object'].posted_data is string %}
|
||||
Posted data size: {{ sizeof_fmt(url['url_object'].posted_data|length) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if url['cookies_sent'] %}
|
||||
<div>
|
||||
<p class="h5">This request contains cookies.
|
||||
<button class="btn btn-primary collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#request_cookies_full_list_{{ url['url_object'].uuid }}" aria-expanded="false" aria-controls="collapseExample">
|
||||
<p>
|
||||
<button class="btn btn-primary btn-sm collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#request_cookies_full_list_{{ url['url_object'].uuid }}" aria-expanded="false" aria-controls="collapseExample">
|
||||
<span class="if-collapsed">Show cookies sent.</span>
|
||||
<span class="if-not-collapsed">Hide cookies sent.</span>
|
||||
</button>
|
||||
|
@ -195,7 +209,9 @@
|
|||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li class="list-group-item">
|
||||
{# Details of the response #}
|
||||
|
@ -206,9 +222,37 @@
|
|||
</span>
|
||||
-
|
||||
<span>Load time: {{ url['url_object'].time.total_seconds() }}s</span>
|
||||
<span>{{response_cookies_icon(url['url_object'], tree_uuid)}}</span>
|
||||
</small>
|
||||
</p>
|
||||
{{ popup_icons_response(url['url_object'], tree_uuid) }}
|
||||
<hr>
|
||||
{% if url['url_object'].rendered_html %}
|
||||
<div>
|
||||
<a href="{{ url_for('urlnode_rendered_content', tree_uuid=tree_uuid, node_uuid=url['url_object'].uuid) }}">
|
||||
Download rendered HTML page
|
||||
</a>({{ sizeof_fmt(url['url_object'].rendered_html.getbuffer().nbytes)}})
|
||||
<br>
|
||||
<a href="{{ url_for('urlnode_urls_in_rendered_content', tree_uuid=tree_uuid, node_uuid=url['url_object'].uuid) }}">
|
||||
Download URLs in rendered HTML page
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{{ redirect_response(url['url_object'], tree_uuid) }}
|
||||
{% if url['url_object'].empty_response %}
|
||||
Empty HTML body.
|
||||
{% else %}
|
||||
{{ hash_info(tree_uuid, url['url_object'].uuid, url['url_object'].mimetype,
|
||||
url['url_object'].body_hash, url['url_object'].body.getbuffer().nbytes,
|
||||
url.get('body_hash_freq', 0), has_pandora) }}
|
||||
{{ ressource_legitimacy_details(url.get('legitimacy')) }}
|
||||
{{ known_content_details(url.get('known_content')) }}
|
||||
|
||||
{% if enable_context_by_users %}
|
||||
{{ context_form(tree_uuid, url['url_object'].uuid,
|
||||
url['url_object'].body_hash, 'hostnode_popup') }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if url['url_object'].downloaded_filename %}
|
||||
<div>
|
||||
|
@ -223,65 +267,19 @@
|
|||
</div>
|
||||
{% endif%}
|
||||
|
||||
{% if url['url_object'].rendered_html %}
|
||||
<div>
|
||||
<a href="{{ url_for('urlnode_rendered_content', tree_uuid=tree_uuid, node_uuid=url['url_object'].uuid) }}">
|
||||
Download rendered HTML page
|
||||
</a>({{ sizeof_fmt(url['url_object'].rendered_html.getbuffer().nbytes)}})
|
||||
<br>
|
||||
<a href="{{ url_for('urlnode_urls_in_rendered_content', tree_uuid=tree_uuid, node_uuid=url['url_object'].uuid) }}">
|
||||
Download URLs in rendered HTML page
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
{% if url['url_object'].empty_response %}
|
||||
Empty HTML body.
|
||||
{% else %}
|
||||
{{ ressource_legitimacy_details(url['legitimacy'], url['url_object'].body.getbuffer().nbytes) }}
|
||||
{% if has_pandora %}
|
||||
{{ pandora_submit(tree_uuid, url['url_object'].uuid) }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
{% if url['known_content'] %}
|
||||
{{ known_content_details(url['known_content']) }}
|
||||
{% endif %}
|
||||
|
||||
{# Everything we know about the response content #}
|
||||
{% if url['body_hash_details'] and url['body_hash_details']['hash_freq'] %}
|
||||
<div>
|
||||
This file can be found <b>{{ url['body_hash_details']['hash_freq'] }}</b> times
|
||||
across all the captures on this lookyloo instance.
|
||||
|
||||
<p>
|
||||
<a href="{{ url_for('body_hash_details', body_hash=url['url_object'].body_hash, from_popup=True) }}">
|
||||
Show more information about this response body.
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
{% if url['url_object'].hhhash %}
|
||||
<p>
|
||||
<a href="{{ url_for('hhh_detail', hhh=url['url_object'].hhhash, from_popup=True) }}">
|
||||
See other captures with the same HTTP Headers Hash
|
||||
Show other captures with the same HTTP Headers Hash
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
{% if enable_context_by_users %}
|
||||
<br>
|
||||
{{ context_form(tree_uuid, url['url_object'].uuid,
|
||||
url['url_object'].body_hash, 'hostnode_popup') }}
|
||||
{% endif %}
|
||||
|
||||
<div class="d-grid gap-2">
|
||||
{% if url['embedded_ressources'] %}
|
||||
{# Details on embedded resources #}
|
||||
<div><b>This response contains embedded ressources</b>
|
||||
<button class="btn btn-primary collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#embedded_full_list_{{ url['url_object'].uuid }}" aria-expanded="false" aria-controls="collapseExample">
|
||||
<div>
|
||||
<button class="btn btn-primary btn-sm collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#embedded_full_list_{{ url['url_object'].uuid }}" aria-expanded="false" aria-controls="collapseExample">
|
||||
<span class="if-collapsed">Show embedded resources.</span>
|
||||
<span class="if-not-collapsed">Hide embedded resources.</span>
|
||||
</button>
|
||||
|
@ -290,28 +288,12 @@
|
|||
<div class="card card-body">
|
||||
{% for hash, details in url['embedded_ressources'].items() %}
|
||||
<div>
|
||||
{% if details['known_content'] %}
|
||||
{{ known_content_details(details['known_content']) }}
|
||||
{% endif %}
|
||||
{{ ressource_legitimacy_details(details['legitimacy'], details['body_size']) }}
|
||||
</div>
|
||||
{% if has_pandora %}
|
||||
{{ pandora_submit(tree_uuid, url['url_object'].uuid, hash) }}
|
||||
{% endif %}
|
||||
<div>
|
||||
This file {% if details['type'] %}(<b>{{ details['type'] }}</b>){% endif %} can be found <b>{{ details['hash_freq'] }}</b> times
|
||||
across all the captures on this lookyloo instance.
|
||||
{{ get_ressource_button(tree_uuid, url['url_object'].uuid, hash,
|
||||
'Download the embedded ressource',
|
||||
details['type'] and details['type'].startswith('image')) }}
|
||||
<br>
|
||||
{{hash_info(tree_uuid, url['url_object'].uuid, details['type'], hash, details['body_size'], details['hash_freq'] ) }}<br>
|
||||
{{ ressource_legitimacy_details(details.get('legitimacy')) }}
|
||||
{{ known_content_details(details.get('known_content')) }}
|
||||
{% if enable_context_by_users %}
|
||||
{{ context_form(tree_uuid, url['url_object'].uuid, hash, 'hostnode_popup') }}
|
||||
{% endif %}
|
||||
|
||||
<p><a href="{{ url_for('body_hash_details', body_hash=url['url_object'].body_hash, from_popup=True) }}">
|
||||
Show more information about this embedded content.
|
||||
</a></p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
@ -320,8 +302,8 @@
|
|||
|
||||
{% if url['cookies_received'] %}
|
||||
<div>
|
||||
<p class="h5">This response contains cookies.
|
||||
<button class="btn btn-primary collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#response_cookies_full_list_{{ url['url_object'].uuid }}" aria-expanded="false" aria-controls="collapseExample">
|
||||
<p>
|
||||
<button class="btn btn-primary btn-sm collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#response_cookies_full_list_{{ url['url_object'].uuid }}" aria-expanded="false" aria-controls="collapseExample">
|
||||
<span class="if-collapsed">Show cookies received.</span>
|
||||
<span class="if-not-collapsed">Hide cookies received.</span>
|
||||
</button>
|
||||
|
@ -335,6 +317,7 @@
|
|||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
|
|
@ -81,21 +81,23 @@
|
|||
|
||||
|
||||
{% macro known_content_details(details) %}
|
||||
<div>
|
||||
{% if details is string %}
|
||||
<b>{{ details }} </b>
|
||||
{% else %}
|
||||
This file is known as part of <b>{{ details[0] }}</b>
|
||||
version <b>{{ details[1] }}</b>: <b>{{ details[2] }}</b>.
|
||||
{% if details[3] > 1%}
|
||||
It is also present in <b>{{ details[3] -1 }}</b> other libraries.
|
||||
{% if details %}
|
||||
<div>
|
||||
{% if details is string %}
|
||||
<b>{{ details }} </b>
|
||||
{% else %}
|
||||
This file is known as part of <b>{{ details[0] }}</b>
|
||||
version <b>{{ details[1] }}</b>: <b>{{ details[2] }}</b>.
|
||||
{% if details[3] > 1%}
|
||||
It is also present in <b>{{ details[3] -1 }}</b> other libraries.
|
||||
{%endif%}
|
||||
{%endif%}
|
||||
</div>
|
||||
{%endif%}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro context_form(tree_uuid, urlnode_uuid, hash, callback_str) %}
|
||||
<button class="btn btn-primary collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#context_response_{{ urlnode_uuid }}" aria-expanded="false" aria-controls="collapseContextForm">
|
||||
<button class="btn btn-primary btn-sm collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#context_response_{{ urlnode_uuid }}" aria-expanded="false" aria-controls="collapseContextForm">
|
||||
<span class="if-collapsed">Add context</span>
|
||||
<span class="if-not-collapsed">Hide context form</span>
|
||||
</button>
|
||||
|
@ -150,22 +152,10 @@
|
|||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro get_ressource_button(capture_uuid, urlnode_uuid, hash, text, can_preview=False) %}
|
||||
<form method="post" action="{{ url_for('get_ressource', tree_uuid=capture_uuid, node_uuid=urlnode_uuid) }}">
|
||||
<button class="btn btn-primary" name="ressource_hash" value="{{ hash }}"
|
||||
{% if can_preview %}
|
||||
data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-html="true"
|
||||
title='<img class="ressource_preview" src="{{ url_for('get_ressource_preview', tree_uuid=capture_uuid, node_uuid=urlnode_uuid, h_ressource=hash) }}"/>'
|
||||
{% endif %}
|
||||
>{{ text }}</button>
|
||||
</form>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro ressource_legitimacy_details(details, ressource_size) %}
|
||||
{% macro ressource_legitimacy_details(details) %}
|
||||
{% if details and details[0] == False %}
|
||||
<img src="/static/bomb.svg" title="Known malicious content in the response." width="21" height="21"/>
|
||||
{%endif%}
|
||||
<b>Body size</b> (in the HTTP response): {{ sizeof_fmt(ressource_size) }}
|
||||
{% if details %}
|
||||
{% if details[0] %}
|
||||
- This file is known <b>legitimate</b> on the following domains: {{ ', '.join(details[1]) }}.
|
||||
|
@ -215,17 +205,15 @@
|
|||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro popup_icons_request(urlnode, tree_uuid) %}
|
||||
<div>
|
||||
{% macro request_cookies_icon(urlnode, tree_uuid) %}
|
||||
{% if urlnode.request_cookie %}
|
||||
{% set icon_info = get_icon("request_cookie") %}
|
||||
<a href="{{ url_for('urlnode_request_cookies', tree_uuid=tree_uuid, node_uuid=urlnode.uuid) }}"
|
||||
title="Download all the cookies in the request to the server">
|
||||
<a href="{{ url_for('urlnode_request_cookies', tree_uuid=tree_uuid, node_uuid=urlnode.uuid) }}">
|
||||
<img src="{{ url_for('static', filename=icon_info['icon']) }}" alt="{{ icon_info['tooltip'] }}"
|
||||
width="21" height="21"/>
|
||||
width="21" height="21"/
|
||||
title="Download all the cookies in the request to the server">
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
|
@ -241,47 +229,57 @@
|
|||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro hash_icon(tree_uuid, urlnode_uuid, generic_type, hash) %}
|
||||
{% if generic_type in ["js", "exe", "css", "font", "html", "json", "image", "video",
|
||||
"unknown_mimetype", "text", "unset_mimetype", "octet-stream",
|
||||
"livestream"] %}
|
||||
{% set icon_info = get_icon(generic_type) %}
|
||||
<a href="{{ url_for('get_ressource', tree_uuid=tree_uuid, node_uuid=urlnode_uuid) }}">
|
||||
<img src="{{ url_for('static', filename=icon_info['icon']) }}" alt="{{ icon_info['tooltip'] }}"
|
||||
width="21" height="21"
|
||||
{% if generic_type == "image" %}
|
||||
data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-html="true"
|
||||
title='<img class="ressource_preview" src="{{ url_for('get_ressource_preview', tree_uuid=tree_uuid, node_uuid=urlnode_uuid, h_ressource=hash) }}"/> <br>Click to download.'
|
||||
{% else %}
|
||||
data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-html="true"
|
||||
title="{{icon_info['tooltip']}} <br/>Click to download."
|
||||
{% endif %}
|
||||
/>
|
||||
</a>
|
||||
{%endif%}
|
||||
{% macro hash_info(tree_uuid, urlnode_uuid, mimetype, hash, ressource_size,
|
||||
nb_occurrences, has_pandora)%}
|
||||
|
||||
{{ hash_icon(tree_uuid, urlnode_uuid, mimetype, hash) }}
|
||||
|
||||
<b>Body size</b> (in the HTTP response): {{ sizeof_fmt(ressource_size) }}
|
||||
|
||||
{% if nb_occurrences > 0 %}
|
||||
<div>
|
||||
This file can be found <b>{{ nb_occurrences }}</b> times across all the captures on this lookyloo instance.
|
||||
<p>
|
||||
<a href="{{ url_for('body_hash_details', body_hash=hash, from_popup=True) }}">
|
||||
Show more information about this ressource.
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if has_pandora %}
|
||||
{{ pandora_submit(tree_uuid, urlnode_uuid, hash) }}
|
||||
{% endif %}
|
||||
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
{% macro popup_icons_response(urlnode, tree_uuid) %}
|
||||
<div>
|
||||
{% if urlnode.generic_type in ["js", "exe", "css", "font", "html", "json", "image", "video",
|
||||
"unknown_mimetype", "text", "unset_mimetype", "octet-stream",
|
||||
"livestream"] %}
|
||||
{% set icon_info = get_icon(urlnode.generic_type) %}
|
||||
<a href="{{ url_for('get_ressource', tree_uuid=tree_uuid, node_uuid=urlnode.uuid) }}">
|
||||
{% macro hash_icon(tree_uuid, urlnode_uuid, mimetype, hash) %}
|
||||
{% if mimetype %}
|
||||
{% set gt = generic_type(mimetype) %}
|
||||
{% if gt in ["js", "exe", "css", "font", "html", "json", "image", "video",
|
||||
"unknown_mimetype", "text", "unset_mimetype", "octet-stream",
|
||||
"livestream"] %}
|
||||
{% set icon_info = get_icon(gt) %}
|
||||
<a href="{{ url_for('get_ressource', tree_uuid=tree_uuid, node_uuid=urlnode_uuid) }}">
|
||||
<img src="{{ url_for('static', filename=icon_info['icon']) }}" alt="{{ icon_info['tooltip'] }}"
|
||||
width="21" height="21"
|
||||
{% if urlnode.generic_type == "image" %}
|
||||
{% if gt == "image" %}
|
||||
data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-html="true"
|
||||
title='<img class="ressource_preview" src="{{ url_for('get_ressource_preview', tree_uuid=tree_uuid, node_uuid=urlnode.uuid) }}"/> <br>Click to download.'
|
||||
title='<img class="ressource_preview" src="{{ url_for('get_ressource_preview', tree_uuid=tree_uuid, node_uuid=urlnode_uuid, h_ressource=hash) }}"/> <br>Click to download.'
|
||||
{% else %}
|
||||
data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-html="true"
|
||||
title="{{icon_info['tooltip']}} <br/>Click to download."
|
||||
{% endif %}
|
||||
/>
|
||||
</a>
|
||||
<small>Mimetype: <b>{{mimetype}}</b></small>
|
||||
<br>
|
||||
{%endif%}
|
||||
{%endif%}
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
{% macro response_cookies_icon(urlnode, tree_uuid) %}
|
||||
{% if urlnode.response_cookie %}
|
||||
{% set icon_info = get_icon("response_cookie") %}
|
||||
<a href="{{ url_for('urlnode_response_cookies', tree_uuid=tree_uuid, node_uuid=urlnode.uuid) }}"
|
||||
|
@ -290,10 +288,9 @@
|
|||
width="21" height="21"/>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% macro redirect_response(urlnode, tree_uuid) %}
|
||||
{% if urlnode["redirect"] %}
|
||||
{% set icon_info = get_icon('redirect') %}
|
||||
{% for child in urlnode.children if child.name == urlnode.redirect_url %}
|
||||
|
@ -309,7 +306,6 @@
|
|||
width="21" height="21"/>
|
||||
{% endfor %}
|
||||
{%endif%}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro shorten_string(string, cut_length, with_title=False) %}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
{% from 'bootstrap5/utils.html' import render_messages %}
|
||||
{% from 'macros.html' import shorten_string %}
|
||||
{% from 'macros.html' import get_ressource_button %}
|
||||
{% from 'macros.html' import hash_icon %}
|
||||
{% from 'macros.html' import context_form %}
|
||||
|
||||
{% block title %}Ressources{% endblock %}
|
||||
|
@ -42,7 +42,7 @@
|
|||
<tr>
|
||||
<td>
|
||||
<a href="{{ url_for('body_hash_details', body_hash=h) }}">{{ shorten_string(h, 10) }}</a><br>
|
||||
{{ get_ressource_button(capture_uuid, urlnode_uuid, h, 'Download sample', mimetype and mimetype.startswith('image')) }}
|
||||
{{ hash_icon(capture_uuid, urlnode_uuid, mimetype, h) }}
|
||||
</td>
|
||||
<td>{{ freq }}</td>
|
||||
<td> {{ context['type'] }} - {{ context['details'] }}<br>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<tr>
|
||||
<td>{{ info['total_captures'] }}</td>
|
||||
<td data-order="{{info['generic_type']}}">
|
||||
{{hash_icon(tree_uuid, info['nodes'][0][0].uuid, info['generic_type'], body_hash)}}
|
||||
{{hash_icon(tree_uuid, info['nodes'][0][0].uuid, info['mimetype'], body_hash)}}
|
||||
</td>
|
||||
<td>
|
||||
<ul>
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
{% from "macros.html" import popup_icons_response %}
|
||||
|
||||
<table id="hostnamesTable" class="table table-striped" style="width:100%">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
Loading…
Reference in New Issue