diff --git a/lookyloo/helpers.py b/lookyloo/helpers.py index bb22a923..ae8b662a 100644 --- a/lookyloo/helpers.py +++ b/lookyloo/helpers.py @@ -187,15 +187,20 @@ def load_cookies(cookie_pseudofile: Optional[BufferedIOBase]=None) -> List[Dict[ to_return = [] try: for cookie in cookies: - u = urlparse(cookie['Host raw']).netloc.split(':', 1)[0] - to_add = {'path': cookie['Path raw'], - 'name': cookie['Name raw'], - 'httpOnly': cookie['HTTP only raw'] == 'true', - 'secure': cookie['Send for'] == 'Encrypted connections only', - 'expires': (datetime.now() + timedelta(days=10)).strftime('%Y-%m-%dT%H:%M:%S') + 'Z', - 'domain': u, - 'value': cookie['Content raw'] - } + if 'Host raw' in cookie: + # Cookie export format for Cookie Quick Manager + u = urlparse(cookie['Host raw']).netloc.split(':', 1)[0] + to_add = {'path': cookie['Path raw'], + 'name': cookie['Name raw'], + 'httpOnly': cookie['HTTP only raw'] == 'true', + 'secure': cookie['Send for'] == 'Encrypted connections only', + 'expires': (datetime.now() + timedelta(days=10)).strftime('%Y-%m-%dT%H:%M:%S') + 'Z', + 'domain': u, + 'value': cookie['Content raw'] + } + else: + # Cookie from lookyloo/splash + to_add = cookie to_return.append(to_add) except Exception as e: print(f'Unable to load the cookie file: {e}') diff --git a/lookyloo/lookyloo.py b/lookyloo/lookyloo.py index d03a47b1..a6f8ecf6 100644 --- a/lookyloo/lookyloo.py +++ b/lookyloo/lookyloo.py @@ -121,7 +121,7 @@ class Lookyloo(): def get_modules_responses(self, capture_dir: Path) -> Optional[Dict[str, Any]]: ct = self._load_pickle(capture_dir / 'tree.pickle') if not ct: - self.logger.warning('Unable to get the modules responses unless the tree ({capture_dir}) is cached.') + self.logger.warning(f'Unable to get the modules responses unless the tree ({capture_dir}) is cached.') return None to_return: Dict[str, Any] = {} if hasattr(self, 'vt') and self.vt.available: @@ -314,6 +314,9 @@ class Lookyloo(): def get_html(self, capture_dir: Path, all_html: bool=False) -> BytesIO: return self._get_raw(capture_dir, 'html', all_html) + def get_cookies(self, capture_dir: Path, all_cookies: bool=False) -> BytesIO: + return self._get_raw(capture_dir, 'cookies.json', all_cookies) + def get_screenshot(self, capture_dir: Path, all_images: bool=False) -> BytesIO: return self._get_raw(capture_dir, 'png', all_images) @@ -334,7 +337,7 @@ class Lookyloo(): try: ip = socket.gethostbyname(splitted_url.hostname) except socket.gaierror: - self.logger.info(f'Name or service not known') + self.logger.info('Name or service not known') return False if not ipaddress.ip_address(ip).is_global: return False diff --git a/website/web/__init__.py b/website/web/__init__.py index 208b2b28..7b0011fe 100644 --- a/website/web/__init__.py +++ b/website/web/__init__.py @@ -190,6 +190,32 @@ def hostnode_popup(tree_uuid: str, node_uuid: str): keys_request=keys_request) +@app.route('/tree//url//request_cookies', methods=['GET']) +def urlnode_request_cookies(tree_uuid: str, node_uuid: str): + capture_dir = lookyloo.lookup_capture_dir(tree_uuid) + if not capture_dir: + return + urlnode = lookyloo.get_urlnode_from_tree(capture_dir, node_uuid) + if not urlnode.request_cookie: + return + + return send_file(BytesIO(json.dumps(urlnode.request_cookie, indent=2).encode()), + mimetype='text/plain', as_attachment=True, attachment_filename='request_cookies.txt') + + +@app.route('/tree//url//response_cookies', methods=['GET']) +def urlnode_response_cookies(tree_uuid: str, node_uuid: str): + capture_dir = lookyloo.lookup_capture_dir(tree_uuid) + if not capture_dir: + return + urlnode = lookyloo.get_urlnode_from_tree(capture_dir, node_uuid) + if not urlnode.response_cookie: + return + + return send_file(BytesIO(json.dumps(urlnode.response_cookie, indent=2).encode()), + mimetype='text/plain', as_attachment=True, attachment_filename='response_cookies.txt') + + @app.route('/tree//url//posted_data', methods=['GET']) def urlnode_post_request(tree_uuid: str, node_uuid: str): capture_dir = lookyloo.lookup_capture_dir(tree_uuid) @@ -300,6 +326,16 @@ def html(tree_uuid: str): as_attachment=True, attachment_filename='page.html') +@app.route('/tree//cookies', methods=['GET']) +def cookies(tree_uuid: str): + capture_dir = lookyloo.lookup_capture_dir(tree_uuid) + if not capture_dir: + return Response('Not available.', mimetype='text/text') + to_return = lookyloo.get_cookies(capture_dir) + return send_file(to_return, mimetype='application/json', + as_attachment=True, attachment_filename='cookies.json') + + @app.route('/tree//export', methods=['GET']) def export(tree_uuid: str): capture_dir = lookyloo.lookup_capture_dir(tree_uuid) @@ -352,7 +388,7 @@ def tree(tree_uuid: str): cache = lookyloo.capture_cache(capture_dir) if not cache: - flash(f'Invalid cache.', 'error') + flash('Invalid cache.', 'error') return redirect(url_for('index')) if 'error' in cache: diff --git a/website/web/templates/hostname_popup.html b/website/web/templates/hostname_popup.html index 9a18c26d..eaa5336f 100644 --- a/website/web/templates/hostname_popup.html +++ b/website/web/templates/hostname_popup.html @@ -27,7 +27,13 @@
{% for key, path in keys_response.items() %} {% if url[key] %} + {% if key == "response_cookie" %} + + {{ key }} + + {% else %} {{ key }} + {%endif%} {%endif%} {% endfor %}
@@ -60,7 +66,13 @@
{% for key, path in keys_request.items() %} {% if url[key] %} + {% if key == "request_cookie" %} + + {{ key }} + + {% else %} {{ key }} + {%endif%} {%endif%} {% endfor %}