fix: properly wrap file responses when called on broken captures

pull/640/head
Raphaël Vinot 2023-03-17 11:10:01 +01:00
parent a0a23dca20
commit f46a8ae841
1 changed files with 38 additions and 7 deletions

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import calendar import calendar
import functools
import http import http
import json import json
import logging import logging
@ -221,20 +222,33 @@ def after_request(response):
return response return response
def file_response(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except NoValidHarFile:
return send_file(BytesIO(b'The capture is broken and does not contain any HAR files.'),
mimetype='test/plain', as_attachment=True, download_name='error.txt')
except MissingUUID as e:
return send_file(BytesIO(str(e).encode()),
mimetype='test/plain', as_attachment=True, download_name='error.txt')
return wrapper
# ##### Hostnode level methods ##### # ##### Hostnode level methods #####
@app.route('/tree/<string:tree_uuid>/host/<string:node_uuid>/hashes', methods=['GET']) @app.route('/tree/<string:tree_uuid>/host/<string:node_uuid>/hashes', methods=['GET'])
@file_response
def hashes_hostnode(tree_uuid: str, node_uuid: str): def hashes_hostnode(tree_uuid: str, node_uuid: str):
try: hashes = lookyloo.get_hashes(tree_uuid, hostnode_uuid=node_uuid)
hashes = lookyloo.get_hashes(tree_uuid, hostnode_uuid=node_uuid) return send_file(BytesIO('\n'.join(hashes).encode()),
return send_file(BytesIO('\n'.join(hashes).encode()), mimetype='test/plain', as_attachment=True, download_name=f'hashes.{node_uuid}.txt')
mimetype='test/plain', as_attachment=True, download_name=f'hashes.{node_uuid}.txt')
except NoValidHarFile:
return send_file(BytesIO(b'The capture is broken and does not contain any HAR files.'),
mimetype='test/plain', as_attachment=True, download_name=f'hashes.{node_uuid}.txt')
@app.route('/tree/<string:tree_uuid>/host/<string:node_uuid>/text', methods=['GET']) @app.route('/tree/<string:tree_uuid>/host/<string:node_uuid>/text', methods=['GET'])
@file_response
def urls_hostnode(tree_uuid: str, node_uuid: str): def urls_hostnode(tree_uuid: str, node_uuid: str):
hostnode = lookyloo.get_hostnode_from_tree(tree_uuid, node_uuid) hostnode = lookyloo.get_hostnode_from_tree(tree_uuid, node_uuid)
return send_file(BytesIO('\n'.join(url.name for url in hostnode.urls).encode()), return send_file(BytesIO('\n'.join(url.name for url in hostnode.urls).encode()),
@ -484,6 +498,7 @@ def modules(tree_uuid: str):
@app.route('/tree/<string:tree_uuid>/redirects', methods=['GET']) @app.route('/tree/<string:tree_uuid>/redirects', methods=['GET'])
@file_response
def redirects(tree_uuid: str): def redirects(tree_uuid: str):
cache = lookyloo.capture_cache(tree_uuid) cache = lookyloo.capture_cache(tree_uuid)
if not cache or not hasattr(cache, 'redirects'): if not cache or not hasattr(cache, 'redirects'):
@ -499,6 +514,7 @@ def redirects(tree_uuid: str):
@app.route('/tree/<string:tree_uuid>/image', methods=['GET']) @app.route('/tree/<string:tree_uuid>/image', methods=['GET'])
@file_response
def image(tree_uuid: str): def image(tree_uuid: str):
max_width = request.args.get('width') max_width = request.args.get('width')
if max_width: if max_width:
@ -510,6 +526,7 @@ def image(tree_uuid: str):
@app.route('/tree/<string:tree_uuid>/data', methods=['GET']) @app.route('/tree/<string:tree_uuid>/data', methods=['GET'])
@file_response
def data(tree_uuid: str): def data(tree_uuid: str):
filename, data = lookyloo.get_data(tree_uuid) filename, data = lookyloo.get_data(tree_uuid)
if len(filename) == 0: if len(filename) == 0:
@ -526,12 +543,14 @@ def data(tree_uuid: str):
@app.route('/tree/<string:tree_uuid>/thumbnail/', defaults={'width': 64}, methods=['GET']) @app.route('/tree/<string:tree_uuid>/thumbnail/', defaults={'width': 64}, methods=['GET'])
@app.route('/tree/<string:tree_uuid>/thumbnail/<int:width>', methods=['GET']) @app.route('/tree/<string:tree_uuid>/thumbnail/<int:width>', methods=['GET'])
@file_response
def thumbnail(tree_uuid: str, width: int): def thumbnail(tree_uuid: str, width: int):
to_return = lookyloo.get_screenshot_thumbnail(tree_uuid, for_datauri=False, width=width) to_return = lookyloo.get_screenshot_thumbnail(tree_uuid, for_datauri=False, width=width)
return send_file(to_return, mimetype='image/png') return send_file(to_return, mimetype='image/png')
@app.route('/tree/<string:tree_uuid>/html', methods=['GET']) @app.route('/tree/<string:tree_uuid>/html', methods=['GET'])
@file_response
def html(tree_uuid: str): def html(tree_uuid: str):
to_return = lookyloo.get_html(tree_uuid) to_return = lookyloo.get_html(tree_uuid)
return send_file(to_return, mimetype='text/html', return send_file(to_return, mimetype='text/html',
@ -539,6 +558,7 @@ def html(tree_uuid: str):
@app.route('/tree/<string:tree_uuid>/cookies', methods=['GET']) @app.route('/tree/<string:tree_uuid>/cookies', methods=['GET'])
@file_response
def cookies(tree_uuid: str): def cookies(tree_uuid: str):
to_return = lookyloo.get_cookies(tree_uuid) to_return = lookyloo.get_cookies(tree_uuid)
return send_file(to_return, mimetype='application/json', return send_file(to_return, mimetype='application/json',
@ -546,6 +566,7 @@ def cookies(tree_uuid: str):
@app.route('/tree/<string:tree_uuid>/hashes', methods=['GET']) @app.route('/tree/<string:tree_uuid>/hashes', methods=['GET'])
@file_response
def hashes_tree(tree_uuid: str): def hashes_tree(tree_uuid: str):
hashes = lookyloo.get_hashes(tree_uuid) hashes = lookyloo.get_hashes(tree_uuid)
return send_file(BytesIO('\n'.join(hashes).encode()), return send_file(BytesIO('\n'.join(hashes).encode()),
@ -553,6 +574,7 @@ def hashes_tree(tree_uuid: str):
@app.route('/tree/<string:tree_uuid>/export', methods=['GET']) @app.route('/tree/<string:tree_uuid>/export', methods=['GET'])
@file_response
def export(tree_uuid: str): def export(tree_uuid: str):
to_return = lookyloo.get_capture(tree_uuid) to_return = lookyloo.get_capture(tree_uuid)
return send_file(to_return, mimetype='application/zip', return send_file(to_return, mimetype='application/zip',
@ -1108,6 +1130,7 @@ def statsfull():
@app.route('/whois/<string:query>', methods=['GET']) @app.route('/whois/<string:query>', methods=['GET'])
@app.route('/whois/<string:query>/<int:email_only>', methods=['GET']) @app.route('/whois/<string:query>/<int:email_only>', methods=['GET'])
@file_response
def whois(query: str, email_only: int=0): def whois(query: str, email_only: int=0):
to_return = lookyloo.uwhois.whois(query, bool(email_only)) to_return = lookyloo.uwhois.whois(query, bool(email_only))
if isinstance(to_return, str): if isinstance(to_return, str):
@ -1119,6 +1142,7 @@ def whois(query: str, email_only: int=0):
# ##### Methods related to a specific URLNode ##### # ##### Methods related to a specific URLNode #####
@app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/request_cookies', methods=['GET']) @app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/request_cookies', methods=['GET'])
@file_response
def urlnode_request_cookies(tree_uuid: str, node_uuid: str): def urlnode_request_cookies(tree_uuid: str, node_uuid: str):
urlnode = lookyloo.get_urlnode_from_tree(tree_uuid, node_uuid) urlnode = lookyloo.get_urlnode_from_tree(tree_uuid, node_uuid)
if not urlnode.request_cookie: if not urlnode.request_cookie:
@ -1129,6 +1153,7 @@ def urlnode_request_cookies(tree_uuid: str, node_uuid: str):
@app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/response_cookies', methods=['GET']) @app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/response_cookies', methods=['GET'])
@file_response
def urlnode_response_cookies(tree_uuid: str, node_uuid: str): def urlnode_response_cookies(tree_uuid: str, node_uuid: str):
urlnode = lookyloo.get_urlnode_from_tree(tree_uuid, node_uuid) urlnode = lookyloo.get_urlnode_from_tree(tree_uuid, node_uuid)
if not urlnode.response_cookie: if not urlnode.response_cookie:
@ -1139,6 +1164,7 @@ def urlnode_response_cookies(tree_uuid: str, node_uuid: str):
@app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/urls_in_rendered_content', methods=['GET']) @app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/urls_in_rendered_content', methods=['GET'])
@file_response
def urlnode_urls_in_rendered_content(tree_uuid: str, node_uuid: str): def urlnode_urls_in_rendered_content(tree_uuid: str, node_uuid: str):
# Note: we could simplify it with lookyloo.get_urls_rendered_page, but if at somepoint, # Note: we could simplify it with lookyloo.get_urls_rendered_page, but if at somepoint,
# we have multiple page rendered on one tree, it will be a problem. # we have multiple page rendered on one tree, it will be a problem.
@ -1156,6 +1182,7 @@ def urlnode_urls_in_rendered_content(tree_uuid: str, node_uuid: str):
@app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/rendered_content', methods=['GET']) @app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/rendered_content', methods=['GET'])
@file_response
def urlnode_rendered_content(tree_uuid: str, node_uuid: str): def urlnode_rendered_content(tree_uuid: str, node_uuid: str):
urlnode = lookyloo.get_urlnode_from_tree(tree_uuid, node_uuid) urlnode = lookyloo.get_urlnode_from_tree(tree_uuid, node_uuid)
if not urlnode.rendered_html: if not urlnode.rendered_html:
@ -1165,6 +1192,7 @@ def urlnode_rendered_content(tree_uuid: str, node_uuid: str):
@app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/posted_data', methods=['GET']) @app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/posted_data', methods=['GET'])
@file_response
def urlnode_post_request(tree_uuid: str, node_uuid: str): def urlnode_post_request(tree_uuid: str, node_uuid: str):
urlnode = lookyloo.get_urlnode_from_tree(tree_uuid, node_uuid) urlnode = lookyloo.get_urlnode_from_tree(tree_uuid, node_uuid)
if not urlnode.posted_data: if not urlnode.posted_data:
@ -1193,6 +1221,7 @@ def urlnode_post_request(tree_uuid: str, node_uuid: str):
@app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/ressource', methods=['POST', 'GET']) @app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/ressource', methods=['POST', 'GET'])
@file_response
def get_ressource(tree_uuid: str, node_uuid: str): def get_ressource(tree_uuid: str, node_uuid: str):
if request.method == 'POST': if request.method == 'POST':
h_request = request.form.get('ressource_hash') h_request = request.form.get('ressource_hash')
@ -1213,6 +1242,7 @@ def get_ressource(tree_uuid: str, node_uuid: str):
@app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/ressource_preview', methods=['GET']) @app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/ressource_preview', methods=['GET'])
@app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/ressource_preview/<string:h_ressource>', methods=['GET']) @app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/ressource_preview/<string:h_ressource>', methods=['GET'])
@file_response
def get_ressource_preview(tree_uuid: str, node_uuid: str, h_ressource: Optional[str]=None): def get_ressource_preview(tree_uuid: str, node_uuid: str, h_ressource: Optional[str]=None):
ressource = lookyloo.get_ressource(tree_uuid, node_uuid, h_ressource) ressource = lookyloo.get_ressource(tree_uuid, node_uuid, h_ressource)
if not ressource: if not ressource:
@ -1225,6 +1255,7 @@ def get_ressource_preview(tree_uuid: str, node_uuid: str, h_ressource: Optional[
@app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/hashes', methods=['GET']) @app.route('/tree/<string:tree_uuid>/url/<string:node_uuid>/hashes', methods=['GET'])
@file_response
def hashes_urlnode(tree_uuid: str, node_uuid: str): def hashes_urlnode(tree_uuid: str, node_uuid: str):
hashes = lookyloo.get_hashes(tree_uuid, urlnode_uuid=node_uuid) hashes = lookyloo.get_hashes(tree_uuid, urlnode_uuid=node_uuid)
return send_file(BytesIO('\n'.join(hashes).encode()), return send_file(BytesIO('\n'.join(hashes).encode()),