mirror of https://github.com/CIRCL/lookyloo
fix: Support rendering non-icon favicons
parent
dcbec2efef
commit
104129bbe2
|
@ -3629,4 +3629,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = ">=3.8.1,<3.13"
|
python-versions = ">=3.8.1,<3.13"
|
||||||
content-hash = "6ed31d5e656cec63bfd4e1402b09b449ea7c3d5edb2ada0ec38e79b4784a38b7"
|
content-hash = "0ae3318c2969c455c7d29bd34a9b28689a17cda4f10ca8352bcb0c7ebcb0a6ec"
|
||||||
|
|
|
@ -80,6 +80,7 @@ urllib3 = [
|
||||||
{version = "^2.0.7", python = ">=3.10"}
|
{version = "^2.0.7", python = ">=3.10"}
|
||||||
]
|
]
|
||||||
pypdns = "^2.2.2"
|
pypdns = "^2.2.2"
|
||||||
|
python-magic = "^0.4.27"
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
mypy = "^1.8.0"
|
mypy = "^1.8.0"
|
||||||
|
|
|
@ -15,6 +15,7 @@ import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import filetype # type: ignore[import-untyped]
|
import filetype # type: ignore[import-untyped]
|
||||||
|
import magic
|
||||||
|
|
||||||
from datetime import date, datetime, timedelta, timezone
|
from datetime import date, datetime, timedelta, timezone
|
||||||
from importlib.metadata import version
|
from importlib.metadata import version
|
||||||
|
@ -838,6 +839,7 @@ def mark_as_legitimate(tree_uuid: str) -> Response:
|
||||||
def tree_favicons(tree_uuid: str) -> str:
|
def tree_favicons(tree_uuid: str) -> str:
|
||||||
favicons = []
|
favicons = []
|
||||||
favicons_zip = lookyloo.get_potential_favicons(tree_uuid, all_favicons=True, for_datauri=False)
|
favicons_zip = lookyloo.get_potential_favicons(tree_uuid, all_favicons=True, for_datauri=False)
|
||||||
|
f = magic.Magic(mime=True)
|
||||||
with ZipFile(favicons_zip, 'r') as myzip:
|
with ZipFile(favicons_zip, 'r') as myzip:
|
||||||
for name in myzip.namelist():
|
for name in myzip.namelist():
|
||||||
if not name.endswith('.ico'):
|
if not name.endswith('.ico'):
|
||||||
|
@ -845,11 +847,12 @@ def tree_favicons(tree_uuid: str) -> str:
|
||||||
favicon = myzip.read(name)
|
favicon = myzip.read(name)
|
||||||
if not favicon:
|
if not favicon:
|
||||||
continue
|
continue
|
||||||
|
mimetype = f.from_buffer(favicon)
|
||||||
favicon_sha512 = hashlib.sha512(favicon).hexdigest()
|
favicon_sha512 = hashlib.sha512(favicon).hexdigest()
|
||||||
frequency = lookyloo.indexing.favicon_frequency(favicon_sha512)
|
frequency = lookyloo.indexing.favicon_frequency(favicon_sha512)
|
||||||
number_captures = lookyloo.indexing.favicon_number_captures(favicon_sha512)
|
number_captures = lookyloo.indexing.favicon_number_captures(favicon_sha512)
|
||||||
b64_favicon = base64.b64encode(favicon).decode()
|
b64_favicon = base64.b64encode(favicon).decode()
|
||||||
favicons.append((favicon_sha512, frequency, number_captures, b64_favicon))
|
favicons.append((favicon_sha512, frequency, number_captures, mimetype, b64_favicon))
|
||||||
return render_template('tree_favicons.html', tree_uuid=tree_uuid, favicons=favicons)
|
return render_template('tree_favicons.html', tree_uuid=tree_uuid, favicons=favicons)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1243,11 +1246,14 @@ def hhh_detail(hhh: str) -> str:
|
||||||
def favicon_detail(favicon_sha512: str) -> str:
|
def favicon_detail(favicon_sha512: str) -> str:
|
||||||
captures, favicon = lookyloo.get_favicon_investigator(favicon_sha512.strip())
|
captures, favicon = lookyloo.get_favicon_investigator(favicon_sha512.strip())
|
||||||
if favicon:
|
if favicon:
|
||||||
|
f = magic.Magic(mime=True)
|
||||||
|
mimetype = f.from_buffer(favicon)
|
||||||
b64_favicon = base64.b64encode(favicon).decode()
|
b64_favicon = base64.b64encode(favicon).decode()
|
||||||
else:
|
else:
|
||||||
b64_favicon = ''
|
b64_favicon = ''
|
||||||
|
mimetype = ''
|
||||||
return render_template('favicon_details.html', favicon_sha512=favicon_sha512,
|
return render_template('favicon_details.html', favicon_sha512=favicon_sha512,
|
||||||
captures=captures, b64_favicon=b64_favicon)
|
captures=captures, mimetype=mimetype, b64_favicon=b64_favicon)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/body_hashes/<string:body_hash>', methods=['GET'])
|
@app.route('/body_hashes/<string:body_hash>', methods=['GET'])
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
"favicon.ico": "KOmrfwRbOQqhhwSeBkNpMRAxSVMmmLg+2kRMg9iSv7OWjE9spJc7x4MKB4AE/hi0knaV7UBVctAU6XZ7AC72ZA==",
|
"favicon.ico": "KOmrfwRbOQqhhwSeBkNpMRAxSVMmmLg+2kRMg9iSv7OWjE9spJc7x4MKB4AE/hi0knaV7UBVctAU6XZ7AC72ZA==",
|
||||||
"font.png": "RwoQkj9dT9SLUL2F7cAA16Nat9t2hDb58eQlHF9ThUar829p0INUXG+5XuDaFOC8SsmCZK5vw2f+YAQ6mLC1Qw==",
|
"font.png": "RwoQkj9dT9SLUL2F7cAA16Nat9t2hDb58eQlHF9ThUar829p0INUXG+5XuDaFOC8SsmCZK5vw2f+YAQ6mLC1Qw==",
|
||||||
"generic.css": "Sh/BcxFMLYYaLdCluVt9efGvJ9CF5d+YJ7lkL2M24PRGu8VZHI9lJiUlFObIocjQgwss3Ve2U5cUAE5WiAdpQQ==",
|
"generic.css": "Sh/BcxFMLYYaLdCluVt9efGvJ9CF5d+YJ7lkL2M24PRGu8VZHI9lJiUlFObIocjQgwss3Ve2U5cUAE5WiAdpQQ==",
|
||||||
"generic.js": "UmFl4fHmB/UjMdUuYdFy9BfzQlJTyeImNHCFyBO4SdLxBCwCGxkF3NQvel1PKqW8JTnoPlPpq/n9d+vCfPeegA==",
|
"generic.js": "h2tLqpn8r1mZ/5FqiBDK6Er6mY5MdRuyir2mS9piT8VUUco2daxdKWSkiEtIsH2Ok+/W+NJb95A1ob5J/6sW4A==",
|
||||||
"html.png": "T7pZrb8MMDsA/JV/51hu+TOglTqlxySuEVY0rpDjTuAEyhzk2v+W4kYrj7vX+Tp3n2d2lvVD08PwhCG62Yfbzg==",
|
"html.png": "T7pZrb8MMDsA/JV/51hu+TOglTqlxySuEVY0rpDjTuAEyhzk2v+W4kYrj7vX+Tp3n2d2lvVD08PwhCG62Yfbzg==",
|
||||||
"ifr.png": "rI5YJypmz1QcULRf9UaOYSqV4tPUSxUdLAycoYzCwywt4Pw4eWzBg9SUr769VyIimoiIyJR+aNuoIA4p5WO2fQ==",
|
"ifr.png": "rI5YJypmz1QcULRf9UaOYSqV4tPUSxUdLAycoYzCwywt4Pw4eWzBg9SUr769VyIimoiIyJR+aNuoIA4p5WO2fQ==",
|
||||||
"img.png": "bknBlmIfSb9qv9/lSaJ2idn2a8bDyvJ2pATj4oOpehRlCdXlWYOyb2jN3wV1QGHFoqyxNqOv5MfCpI0tbqkicg==",
|
"img.png": "bknBlmIfSb9qv9/lSaJ2idn2a8bDyvJ2pATj4oOpehRlCdXlWYOyb2jN3wV1QGHFoqyxNqOv5MfCpI0tbqkicg==",
|
||||||
|
|
|
@ -24,3 +24,18 @@ function checkAllBoxes(name) {
|
||||||
checkboxs[i].checked = !checkboxs[i].checked;
|
checkboxs[i].checked = !checkboxs[i].checked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parameters:
|
||||||
|
// contentType: The content type of your file.
|
||||||
|
// its like application/pdf or application/msword or image/jpeg or
|
||||||
|
// image/png and so on
|
||||||
|
// base64Data: Its your actual base64 data
|
||||||
|
// fileName: Its the file name of the file which will be downloaded.
|
||||||
|
// Source: https://stackoverflow.com/questions/14011021/how-to-download-a-base64-encoded-image
|
||||||
|
function downloadBase64File(contentType, base64Data, fileName) {
|
||||||
|
const linkSource = `data:${contentType};base64,${base64Data}`;
|
||||||
|
const downloadLink = document.createElement("a");
|
||||||
|
downloadLink.href = linkSource;
|
||||||
|
downloadLink.download = fileName;
|
||||||
|
downloadLink.click();
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<center>
|
<center>
|
||||||
<img src="data:image/ico;base64,{{ b64_favicon }}" style="width:64px;height:64px;"/>
|
<img src="data:{{mimetype}};base64,{{ b64_favicon }}" style="width:64px;height:64px;"/>
|
||||||
</center>
|
</center>
|
||||||
<table id="faviconDetailsTable" class="table table-striped" style="width:100%">
|
<table id="faviconDetailsTable" class="table table-striped" style="width:100%">
|
||||||
<thead>
|
<thead>
|
||||||
|
|
|
@ -15,13 +15,14 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for favicon_sha512, freq, number_captures, b64_favicon in favicons %}
|
{% for favicon_sha512, freq, number_captures, mimetype, b64_favicon in favicons %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="#faviconDetailsModal" data-remote="{{ 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">
|
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:{{mimetype}};base64,{{ b64_favicon }}" style="width:32px;height:32px;"/>
|
||||||
</a>
|
</a>
|
||||||
|
<button type="button" class="btn btn-light" onclick="downloadBase64File('{{mimetype}}', '{{b64_favicon}}', 'favicon.ico')">Download favicon</button>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ freq }}</td>
|
<td>{{ freq }}</td>
|
||||||
<td>{{ number_captures }}</td>
|
<td>{{ number_captures }}</td>
|
||||||
|
|
Loading…
Reference in New Issue