mirror of https://github.com/CIRCL/lookyloo
Compare commits
2 Commits
8bbf2bf288
...
4c2620df4c
Author | SHA1 | Date |
---|---|---|
Adrian Maraj | 4c2620df4c | |
Adrian Maraj | c5c1a8adf0 |
|
@ -18,7 +18,6 @@ from lookyloo.default import AbstractManager, get_config
|
|||
from lookyloo.helpers import get_captures_dir
|
||||
|
||||
from lookyloo.modules import FOX
|
||||
from website.web import modules
|
||||
|
||||
logging.config.dictConfig(get_config('logging'))
|
||||
|
||||
|
@ -113,8 +112,8 @@ class AsyncCapture(AbstractManager):
|
|||
settings = json.loads(to_capture['auto_report'])
|
||||
elif isinstance(to_capture['auto_report'], dict):
|
||||
settings = to_capture['auto_report']
|
||||
response_3rd_party = modules(uuid, True)
|
||||
self.lookyloo.send_mail(uuid,response_3rd_party, email=settings.get('email', ''),
|
||||
|
||||
self.lookyloo.send_mail(uuid, email=settings.get('email', ''),
|
||||
comment=settings.get('comment'))
|
||||
|
||||
lazy_cleanup = self.lookyloo.redis.pipeline()
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
{report}
|
||||
|
||||
Dear {recipient},
|
||||
|
||||
Please have a look at this capture on lookyloo:
|
||||
|
@ -9,6 +7,8 @@ Initial URL: {initial_url}
|
|||
|
||||
{redirects}
|
||||
|
||||
{modules}
|
||||
|
||||
{misp}
|
||||
|
||||
{comment}
|
||||
|
|
|
@ -813,7 +813,58 @@ class Lookyloo():
|
|||
result.append(self.takedown_details(rendered_hostnode))
|
||||
return result
|
||||
|
||||
def send_mail(self, capture_uuid: str, /, modules: str, email: str='', comment: str | None=None) -> bool | dict[str, Any]:
|
||||
def modules_filtered(self, capture_uuid: str, /) -> str | None:
|
||||
response = self.get_modules_responses(capture_uuid)
|
||||
if not response:
|
||||
return None
|
||||
modules = set()
|
||||
if 'vt' in response:
|
||||
vt = response.pop('vt')
|
||||
for url, report in vt.items():
|
||||
if not report:
|
||||
continue
|
||||
for vendor, result in report['attributes']['last_analysis_results'].items():
|
||||
if result['category'] == 'malicious':
|
||||
modules.add(vendor)
|
||||
|
||||
if 'pi' in response:
|
||||
pi = response.pop('pi')
|
||||
for url, full_report in pi.items():
|
||||
if not full_report:
|
||||
continue
|
||||
modules.add('Phishing Initiative')
|
||||
|
||||
if 'phishtank' in response:
|
||||
pt = response.pop('phishtank')
|
||||
for url, full_report in pt['urls'].items():
|
||||
if not full_report:
|
||||
continue
|
||||
modules.add('Phishtank')
|
||||
|
||||
if 'urlhaus' in response:
|
||||
uh = response.pop('urlhaus')
|
||||
for url, results in uh['urls'].items():
|
||||
if results:
|
||||
modules.add('URLhaus')
|
||||
|
||||
if 'urlscan' in response and response.get('urlscan'):
|
||||
urlscan = response.pop('urlscan')
|
||||
if 'error' not in urlscan['submission']:
|
||||
if urlscan['submission'] and urlscan['submission'].get('result'):
|
||||
if urlscan['result']:
|
||||
if (urlscan['result'].get('verdicts')
|
||||
and urlscan['result']['verdicts'].get('overall')):
|
||||
if urlscan['result']['verdicts']['overall'].get('malicious'):
|
||||
modules.add('urlscan')
|
||||
else:
|
||||
# unable to run the query, probably an invalid key
|
||||
pass
|
||||
if len(modules) == 0:
|
||||
return f"Capture does not seem to be malicious"
|
||||
|
||||
return f"Malicious capture according to {len(modules)} module(s) {modules}"
|
||||
|
||||
def send_mail(self, capture_uuid: str, /, email: str='', comment: str | None=None) -> bool | dict[str, Any]:
|
||||
'''Send an email notification regarding a specific capture'''
|
||||
if not get_config('generic', 'enable_mail_notification'):
|
||||
return {"error": "Unable to send mail: mail notification disabled"}
|
||||
|
@ -857,6 +908,7 @@ class Lookyloo():
|
|||
if diff.days < 1: # MISP event should not be older than 24hours
|
||||
misp += f"\n{ts.isoformat()} : {misp_url}events/{event_id}"
|
||||
break # some events have more than just one timestamp, we just take the first one
|
||||
modules = self.modules_filtered(capture_uuid)
|
||||
msg = EmailMessage()
|
||||
msg['From'] = email_config['from']
|
||||
if email:
|
||||
|
@ -866,13 +918,13 @@ class Lookyloo():
|
|||
body = get_email_template()
|
||||
body = body.format(
|
||||
recipient=msg['To'].addresses[0].display_name,
|
||||
modules=modules if modules else '',
|
||||
domain=self.public_domain,
|
||||
uuid=capture_uuid,
|
||||
initial_url=initial_url,
|
||||
redirects=redirects,
|
||||
comment=comment if comment else '',
|
||||
misp=f"MISP occurrences from the last 24h: {misp}" if misp else '',
|
||||
report= modules if modules else '',
|
||||
sender=msg['From'].addresses[0].display_name,
|
||||
)
|
||||
msg.set_content(body)
|
||||
|
|
|
@ -817,7 +817,7 @@ def web_misp_push_view(tree_uuid: str) -> str | WerkzeugResponse | Response | No
|
|||
|
||||
|
||||
@app.route('/tree/<string:tree_uuid>/modules', methods=['GET'])
|
||||
def modules(tree_uuid: str, mail: bool = False) -> str | WerkzeugResponse | Response:
|
||||
def modules(tree_uuid: str) -> str | WerkzeugResponse | Response:
|
||||
modules_responses = lookyloo.get_modules_responses(tree_uuid)
|
||||
if not modules_responses:
|
||||
return redirect(url_for('tree', tree_uuid=tree_uuid))
|
||||
|
@ -894,21 +894,6 @@ def modules(tree_uuid: str, mail: bool = False) -> str | WerkzeugResponse | Resp
|
|||
else:
|
||||
# unable to run the query, probably an invalid key
|
||||
pass
|
||||
if mail:
|
||||
short_results = {"vt": vt_short_result, "pi": pi_short_result, "urlscan": urlscan_to_display, "phishtank": phishtank_short_result, "urlhaus": urlhaus_short_result}
|
||||
# iterate through the results because if they are empty, there is no hit within the 3rd party modules
|
||||
for module in short_results:
|
||||
if short_results[module]: # some might have more values which have to be checked if they are empty
|
||||
for data in short_results[module]:
|
||||
if short_results[module][data]: # if true we can consider that there is a hit and the capture might be malicious
|
||||
return str("**************************************************\n"
|
||||
" Malicious capture according to 3rd party modules \n"
|
||||
"**************************************************")
|
||||
|
||||
return str('********************************************\n'
|
||||
' Capture doesn\'t seem to be malicious\n'
|
||||
'********************************************')
|
||||
|
||||
return render_template('modules.html', uuid=tree_uuid, vt=vt_short_result,
|
||||
pi=pi_short_result, urlscan=urlscan_to_display,
|
||||
phishtank=phishtank_short_result,
|
||||
|
@ -1121,8 +1106,7 @@ def send_mail(tree_uuid: str) -> WerkzeugResponse:
|
|||
# skip clearly incorrect emails
|
||||
email = ''
|
||||
comment: str = request.form['comment'] if request.form.get('comment') else ''
|
||||
response_3rd_party = modules(tree_uuid, True)
|
||||
lookyloo.send_mail(tree_uuid, response_3rd_party, email, comment)
|
||||
lookyloo.send_mail(tree_uuid, email, comment)
|
||||
flash("Email notification sent", 'success')
|
||||
return redirect(url_for('tree', tree_uuid=tree_uuid))
|
||||
|
||||
|
|
|
@ -389,9 +389,7 @@ class CaptureReport(Resource): # type: ignore[misc]
|
|||
@api.param('comment', 'Description of the URL, will be given to the analyst.') # type: ignore[misc]
|
||||
def post(self, capture_uuid: str) -> bool | dict[str, Any]:
|
||||
parameters: dict[str, Any] = request.get_json(force=True)
|
||||
from . import modules
|
||||
report = modules(capture_uuid, True)
|
||||
return lookyloo.send_mail(capture_uuid, report, parameters.get('email', ''), parameters.get('comment'))
|
||||
return lookyloo.send_mail(capture_uuid, parameters.get('email', ''), parameters.get('comment'))
|
||||
|
||||
|
||||
auto_report_model = api.model('AutoReportModel', {
|
||||
|
|
Loading…
Reference in New Issue