Analysis translation test

This commit is contained in:
Félix Aime 2021-02-04 11:33:33 +01:00
parent 2625186b72
commit 96d55c2eca
5 changed files with 360 additions and 126 deletions

View File

@ -2,10 +2,13 @@ import weasyprint
import os import os
import json import json
import hashlib import hashlib
import re
import sys
from weasyprint import HTML from weasyprint import HTML
from pathlib import Path from pathlib import Path
from datetime import datetime from datetime import datetime
from utils import get_config
class Report(object): class Report(object):
@ -28,6 +31,14 @@ class Report(object):
except: except:
self.capture_sha1 = "N/A" self.capture_sha1 = "N/A"
self.userlang = get_config(("frontend", "userlang"))
# Load template language
if not re.match("^[a-z]{2}$", self.userlang):
self.userlang = "en"
with open(os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), "lang/{}.json".format(self.userlang)))as f:
self.template = json.load(f)["report"]
def read_json(self, json_path): def read_json(self, json_path):
""" """
Read and convert a JSON file. Read and convert a JSON file.
@ -59,21 +70,35 @@ class Report(object):
:return: str :return: str
""" """
if len(self.alerts["high"]): if len(self.alerts["high"]):
return "<div class=\"warning high\">Your device seems to be compromised as you have {} high alert(s).</div>".format(self.nb_translate(len(self.alerts["high"]))) msg = "<div class=\"warning high\">"
msg += self.template["high_msg"].format(
self.nb_translate(len(self.alerts["high"])))
msg += "</div>"
return msg
elif len(self.alerts["moderate"]): elif len(self.alerts["moderate"]):
return "<div class=\"warning moderate\">You have {} moderate alert(s), your device might be compromised. Please look at them carefully.</div>".format(self.nb_translate(len(self.alerts["moderate"]))) msg = "<div class=\"warning moderate\">"
msg += self.template["moderate_msg"].format(
self.nb_translate(len(self.alerts["moderate"])))
msg += "</div>"
return msg
elif len(self.alerts["low"]): elif len(self.alerts["low"]):
return "<div class=\"warning low\">You have only {} low alert(s), don't hesitate to check them.</div>".format(self.nb_translate(len(self.alerts["low"]))) msg = "<div class=\"warning low\">"
msg += self.template["low_msg"].format(
self.nb_translate(len(self.alerts["low"])))
msg += "</div>"
return msg
else: else:
return "<div class=\"warning low\">Everything looks fine, zero alerts. Don't hesitate to check the uncategorized communications, if any.</div>" msg = "<div class=\"warning low\">"
msg += self.template["none_msg"]
msg += "</div>"
return msg
def nb_translate(self, nb): def nb_translate(self, nb):
""" """
Translate a number in a string. Translate a number in a string.
:return: str :return: str
""" """
a = ["one", "two", "three", "four", "five", a = self.template["numbers"]
"six", "seven", "height", "nine"]
return a[nb-1] if nb <= 9 else str(nb) return a[nb-1] if nb <= 9 else str(nb)
def generate_suspect_conns_block(self): def generate_suspect_conns_block(self):
@ -85,17 +110,17 @@ class Report(object):
if not len([c for c in self.conns if c["alert_tiggered"] == True]): if not len([c for c in self.conns if c["alert_tiggered"] == True]):
return "" return ""
title = "<h2>Suspect communications</h2>" title = "<h2>{}</h2>".format(self.template["suspect_title"])
table = """<table> table = "<table>"
<thead> table += " <thead>"
<tr> table += " <tr>"
<th>Protocol</th> table += " <th>{}</th>".format(self.template["protocol"])
<th>Domain</th> table += " <th>{}</th>".format(self.template["domain"])
<th>Dst IP Address</th> table += " <th>{}</th>".format(self.template["dst_ip"])
<th>Dst port</th> table += " <th>{}</th>".format(self.template["dst_port"])
</tr> table += " </tr>"
</thead> table += " </thead>"
<tbody>""" table += "<tbody>"
for rec in self.conns: for rec in self.conns:
if rec["alert_tiggered"] == True: if rec["alert_tiggered"] == True:
@ -117,17 +142,17 @@ class Report(object):
if not len([c for c in self.conns if c["alert_tiggered"] == False]): if not len([c for c in self.conns if c["alert_tiggered"] == False]):
return "" return ""
title = "<h2>Uncategorized communications</h2>" title = "<h2>{}</h2>".format(self.template["uncat_title"])
table = """<table> table = "<table>"
<thead> table += " <thead>"
<tr> table += " <tr>"
<th>Protocol</th> table += " <th>{}</th>".format(self.template["protocol"])
<th>Domain</th> table += " <th>{}</th>".format(self.template["domain"])
<th>Dst IP Address</th> table += " <th>{}</th>".format(self.template["dst_ip"])
<th>Dst port</th> table += " <th>{}</th>".format(self.template["dst_port"])
</tr> table += " </tr>"
</thead> table += " </thead>"
<tbody>""" table += "<tbody>"
for rec in self.conns: for rec in self.conns:
if rec["alert_tiggered"] == False: if rec["alert_tiggered"] == False:
@ -149,17 +174,17 @@ class Report(object):
if not len(self.whitelist): if not len(self.whitelist):
return "" return ""
title = "<h2>Whitelisted communications</h2>" title = "<h2>{}</h2>".format(self.template["whitelist_title"])
table = """<table> table = "<table>"
<thead> table += " <thead>"
<tr> table += " <tr>"
<th>Protocol</th> table += " <th>{}</th>".format(self.template["protocol"])
<th>Domain</th> table += " <th>{}</th>".format(self.template["domain"])
<th>Dst IP Address</th> table += " <th>{}</th>".format(self.template["dst_ip"])
<th>Dst port</th> table += " <th>{}</th>".format(self.template["dst_port"])
</tr> table += " </tr>"
</thead> table += " </thead>"
<tbody>""" table += "<tbody>"
for rec in sorted(self.whitelist, key=lambda k: k['resolution']): for rec in sorted(self.whitelist, key=lambda k: k['resolution']):
table += "<tr>" table += "<tr>"
@ -179,17 +204,18 @@ class Report(object):
""" """
header = "<div class=\"header\">" header = "<div class=\"header\">"
header += "<div class=\"logo\"></div>" header += "<div class=\"logo\"></div>"
header += "<p><br /><strong>Device name: {}</strong><br />".format( header += "<p><br /><strong>{}: {}</strong><br />".format(self.template["device_name"],
self.device["name"]) self.device["name"])
header += "Device MAC address: {}<br />".format( header += "{}: {}<br />".format(self.template["device_mac"],
self.device["mac_address"]) self.device["mac_address"])
header += "Report generated on {}<br />".format( header += "{} {}<br />".format(self.template["report_generated_on"],
datetime.now().strftime("%d/%m/%Y at %H:%M:%S")) datetime.now().strftime("%d/%m/%Y - %H:%M:%S"))
header += "Capture duration: {}s<br />".format( header += "{}: {}s<br />".format(self.template["capture_duration"],
self.capinfos["Capture duration"]) self.capinfos["Capture duration"])
header += "Number of packets: {}<br />".format( header += "{}: {}<br />".format(self.template["packets_number"],
self.capinfos["Number of packets"]) self.capinfos["Number of packets"])
header += "Capture SHA1: {}<br />".format(self.capture_sha1) header += "{}: {}<br />".format(
self.template["capture_sha1"], self.capture_sha1)
header += "</p>" header += "</p>"
header += "</div>" header += "</div>"
return header return header
@ -420,16 +446,16 @@ class Report(object):
} }
@page { @page {
@top-center { @top-center {
content: "REPORT_HEADER - Page " counter(page) " of " counter(pages) "."; content: "REPORT_HEADER - Page " counter(page) " / " counter(pages) ".";
font-size:12px; font-size:12px;
color:#CCC; color:#CCC;
} }
@bottom-center { @bottom-center {
content: "This report has been autogenerated by a Tinycheck device. For any question, bug report or feedback, please contact tinycheck@kaspersky.com."; content: REPORT_FOOTER;
font-size:12px; font-size:12px;
color:#CCC; color:#CCC;
} }
} }
</style> </style>
</head> </head>
<body>""".replace("REPORT_HEADER", "Report for the capture {}".format(self.capture_sha1)) <body>""".replace("REPORT_HEADER", "{} {}".format(self.template["report_for_the_capture"], self.capture_sha1)).replace("REPORT_FOOTER", self.template["report_footer"])

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from utils import get_iocs, get_apname, get_device from utils import get_iocs, get_apname, get_device, get_config
import time import time
import os import os
import subprocess as sp import subprocess as sp
@ -20,6 +20,14 @@ class SuricataEngine():
self.rules = [r[0] for r in get_iocs( self.rules = [r[0] for r in get_iocs(
"snort")] + self.generate_contextual_alerts() "snort")] + self.generate_contextual_alerts()
self.userlang = get_config(("frontend", "user_lang"))
# Load template language
if not re.match("^[a-z]{2,3}$", self.userlang):
self.userlang = "en"
with open(os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), "lang/{}.json".format(self.userlang))) as f:
self.template = json.load(f)["alerts"]
def start_suricata(self): def start_suricata(self):
""" """
Launch suricata against the capture.pcap file. Launch suricata against the capture.pcap file.
@ -37,9 +45,8 @@ class SuricataEngine():
s = line.split("[**]")[1].strip() s = line.split("[**]")[1].strip()
m = re.search( m = re.search(
r"\[\d+\:(?P<sid>\d+)\:(?P<rev>\d+)\] (?P<title>[ -~]+)", s) r"\[\d+\:(?P<sid>\d+)\:(?P<rev>\d+)\] (?P<title>[ -~]+)", s)
self.alerts.append({"title": "Suricata rule tiggered: {}".format(m.group('title')), self.alerts.append({"title": self.template["SNORT-01"]["title"].format(m.group('title')),
"description": """A network detection rule has been tiggered. It's likely that your device has been compromised "description": self.template["SNORT-01"]["description"],
or contains a malicious application.""",
"level": "High", "level": "High",
"id": "SNORT-01"}) "id": "SNORT-01"})
# Remove fast.log # Remove fast.log
@ -48,7 +55,7 @@ class SuricataEngine():
def generate_rule_file(self): def generate_rule_file(self):
""" """
Generate the rules file passed to suricata. Generate the rules file passed to suricata.
:return: bool if operation succeed. :return: bool if operation succeed.
""" """
try: try:
with open(self.rules_file, "w+") as f: with open(self.rules_file, "w+") as f:

View File

@ -10,6 +10,8 @@ import subprocess as sp
import json import json
import pydig import pydig
import os import os
import re
import sys
class ZeekEngine(object): class ZeekEngine(object):
@ -24,10 +26,17 @@ class ZeekEngine(object):
self.files = [] self.files = []
self.whitelist = [] self.whitelist = []
# Get analysis configuration # Get analysis and userlang configuration
self.heuristics_analysis = get_config(("analysis", "heuristics")) self.heuristics_analysis = get_config(("analysis", "heuristics"))
self.iocs_analysis = get_config(("analysis", "iocs")) self.iocs_analysis = get_config(("analysis", "iocs"))
self.whitelist_analysis = get_config(("analysis", "whitelist")) self.whitelist_analysis = get_config(("analysis", "whitelist"))
self.userlang = get_config(("frontend", "user_lang"))
# Load template language
if not re.match("^[a-z]{2,3}$", self.userlang):
self.userlang = "en"
with open(os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), "lang/{}.json".format(self.userlang))) as f:
self.template = json.load(f)["alerts"]
def fill_dns(self, dir): def fill_dns(self, dir):
""" """
@ -99,47 +108,41 @@ class ZeekEngine(object):
# Check for UDP / ICMP (strange from a smartphone.) # Check for UDP / ICMP (strange from a smartphone.)
if c["proto"] in ["UDP", "ICMP"]: if c["proto"] in ["UDP", "ICMP"]:
c["alert_tiggered"] = True c["alert_tiggered"] = True
self.alerts.append({"title": "{} communication going outside the local network to {}.".format(c["proto"].upper(), c["resolution"]), self.alerts.append({"title": self.template["PROTO-01"]["title"].format(c["proto"].upper(), c["resolution"]),
"description": "The {} protocol is commonly used in internal networks. Please, verify if the host {} leveraged other alerts which may ".format(c["proto"].upper(), c["resolution"]) "description": self.template["PROTO-01"]["description"].format(c["proto"].upper(), c["resolution"]),
+ "indicates a possible malicious behavior.", "host": c["resolution"],
"host": c["resolution"],
"level": "Moderate", "level": "Moderate",
"id": "PROTO-01"}) "id": "PROTO-01"})
# Check for use of ports over 1024. # Check for use of ports over 1024.
if c["port_dst"] >= max_ports: if c["port_dst"] >= max_ports:
c["alert_tiggered"] = True c["alert_tiggered"] = True
self.alerts.append({"title": "{} connection to {} to a port over or equal to {}.".format(c["proto"].upper(), c["resolution"], max_ports), self.alerts.append({"title": self.template["PROTO-02"]["title"].format(c["proto"].upper(), c["resolution"], max_ports),
"description": "{} connections have been seen to {} by using the port {}. The use of non-standard port can be sometimes associated to malicious activities. ".format(c["proto"].upper(), c["resolution"], c["port_dst"]) "description": self.template["PROTO-02"]["description"].format(c["proto"].upper(), c["resolution"], c["port_dst"]),
+ "We recommend to check if this host has a good reputation by looking on other alerts and search it on the internet.", "host": c["resolution"],
"host": c["resolution"],
"level": "Low", "level": "Low",
"id": "PROTO-02"}) "id": "PROTO-02"})
# Check for use of HTTP. # Check for use of HTTP.
if c["service"] == "http" and c["port_dst"] == http_default_port: if c["service"] == "http" and c["port_dst"] == http_default_port:
c["alert_tiggered"] = True c["alert_tiggered"] = True
self.alerts.append({"title": "HTTP communications have been done to the host {}".format(c["resolution"]), self.alerts.append({"title": self.template["PROTO-03"]["title"].format(c["resolution"]),
"description": "Your device exchanged with the host {} by using HTTP, an unencrypted protocol. ".format(c["resolution"]) "description": self.template["PROTO-03"]["description"].format(c["resolution"]),
+ "Even if this behavior is not malicious by itself, it is unusual to see HTTP communications issued from smartphone applications " "host": c["resolution"],
+ "running in the background. Please check the host reputation by searching it on the internet.",
"host": c["resolution"],
"level": "Low", "level": "Low",
"id": "PROTO-03"}) "id": "PROTO-03"})
# Check for use of HTTP on a non standard port. # Check for use of HTTP on a non standard port.
if c["service"] == "http" and c["port_dst"] != http_default_port: if c["service"] == "http" and c["port_dst"] != http_default_port:
c["alert_tiggered"] = True c["alert_tiggered"] = True
self.alerts.append({"title": "HTTP communications have been seen to the host {} on a non standard port ({}).".format(c["resolution"], c["port_dst"]), self.alerts.append({"title": self.template["PROTO-04"]["title"].format(c["resolution"], c["port_dst"]),
"description": "Your device exchanged with the host {} by using HTTP, an unencrypted protocol on the port {}. ".format(c["resolution"], c["port_dst"]) "description": self.template["PROTO-04"]["description"].format(c["resolution"], c["port_dst"]),
+ "This behavior is quite unusual. Please check the host reputation by searching it on the internet.", "host": c["resolution"],
"host": c["resolution"],
"level": "Moderate", "level": "Moderate",
"id": "PROTO-04"}) "id": "PROTO-04"})
# Check for non-resolved IP address. # Check for non-resolved IP address.
if c["ip_dst"] == c["resolution"]: if c["ip_dst"] == c["resolution"]:
c["alert_tiggered"] = True c["alert_tiggered"] = True
self.alerts.append({"title": "The server {} hasn't been resolved by any DNS query during the session".format(c["ip_dst"]), self.alerts.append({"title": self.template["PROTO-05"]["title"].format(c["ip_dst"]),
"description": "It means that the server {} is likely not resolved by any domain name or the resolution has already been cached by ".format(c["ip_dst"]) "description": self.template["PROTO-05"]["description"].format(c["ip_dst"]),
+ "the device. If the host appears in other alerts, please check it.",
"host": c["ip_dst"], "host": c["ip_dst"],
"level": "Low", "level": "Low",
"id": "PROTO-05"}) "id": "PROTO-05"})
@ -159,10 +162,8 @@ class ZeekEngine(object):
for host in bl_hosts: for host in bl_hosts:
if c["ip_dst"] == host[0]: if c["ip_dst"] == host[0]:
c["alert_tiggered"] = True c["alert_tiggered"] = True
self.alerts.append({"title": "A connection has been made to {} ({}) which is tagged as {}.".format(c["resolution"], c["ip_dst"], host[1].upper()), self.alerts.append({"title": self.template["IOC-01"]["title"].format(c["resolution"], c["ip_dst"], host[1].upper()),
"description": "The host {} has been explicitly blacklisted for malicious activities. Your device is likely compromised ".format(c["ip_dst"]) "description": self.template["IOC-01"]["description"].format(c["ip_dst"]),
+ "and needs to be investigated more deeply by IT security professionals.",
"host": c["resolution"], "host": c["resolution"],
"level": "High", "level": "High",
"id": "IOC-01"}) "id": "IOC-01"})
@ -171,10 +172,8 @@ class ZeekEngine(object):
for cidr in bl_cidrs: for cidr in bl_cidrs:
if IPAddress(c["ip_dst"]) in cidr[0]: if IPAddress(c["ip_dst"]) in cidr[0]:
c["alert_tiggered"] = True c["alert_tiggered"] = True
self.alerts.append({"title": "Communication to {} under the CIDR {} which is tagged as {}.".format(c["resolution"], cidr[0], cidr[1].upper()), self.alerts.append({"title": self.template["IOC-02"]["title"].format(c["resolution"], cidr[0], cidr[1].upper()),
"description": "The server {} is hosted under a network which is known to host malicious activities. Even if this behavior is not malicious by itself, ".format(c["resolution"]) "description": self.template["IOC-02"]["description"].format(c["resolution"]),
+ "you need to check if other alerts are also mentioning this host. If you have some doubts, please "
+ "search this host on the internet to see if its legit or not.",
"host": c["resolution"], "host": c["resolution"],
"level": "Moderate", "level": "Moderate",
"id": "IOC-02"}) "id": "IOC-02"})
@ -183,42 +182,37 @@ class ZeekEngine(object):
if c["resolution"].endswith(domain[0]): if c["resolution"].endswith(domain[0]):
if domain[1] != "tracker": if domain[1] != "tracker":
c["alert_tiggered"] = True c["alert_tiggered"] = True
self.alerts.append({"title": "A DNS request have been done to {} which is tagged as {}.".format(c["resolution"], domain[1].upper()), self.alerts.append({"title": self.template["IOC-03"]["title"].format(c["resolution"], domain[1].upper()),
"description": "The domain name {} seen in the capture has been explicitly tagged as malicious. This indicates that ".format(c["resolution"]) "description": self.template["IOC-03"]["description"].format(c["resolution"]),
+ "your device is likely compromised and needs to be investigated deeply.",
"host": c["resolution"], "host": c["resolution"],
"level": "High", "level": "High",
"id": "IOC-03"}) "id": "IOC-03"})
else: else:
c["alert_tiggered"] = True c["alert_tiggered"] = True
self.alerts.append({"title": "A DNS request have been done to {} which is tagged as {}.".format(c["resolution"], domain[1].upper()), self.alerts.append({"title": self.template["IOC-04"]["title"].format(c["resolution"], domain[1].upper()),
"description": "The domain name {} seen in the capture has been explicitly tagged as a Tracker. This ".format(c["resolution"]) "description": self.template["IOC-04"]["description"].format(c["resolution"]),
+ "indicates that one of the active apps is geo-tracking your moves.",
"host": c["resolution"], "host": c["resolution"],
"level": "Moderate", "level": "Moderate",
"id": "IOC-03"}) "id": "IOC-04"})
# Check for blacklisted FreeDNS. # Check for blacklisted FreeDNS.
for domain in bl_freedns: for domain in bl_freedns:
if c["resolution"].endswith("." + domain[0]): if c["resolution"].endswith("." + domain[0]):
c["alert_tiggered"] = True c["alert_tiggered"] = True
self.alerts.append({"title": "A DNS request have been done to the domain {} which is a Free DNS.".format(c["resolution"]), self.alerts.append({"title": self.template["IOC-05"]["title"].format(c["resolution"]),
"description": "The domain name {} is using a Free DNS service. This kind of service is commonly used by cybercriminals ".format(c["resolution"]) "description": self.template["IOC-05"]["description"].format(c["resolution"]),
+ "or state-sponsored threat actors during their operations. It is very suspicious that an application running in background use this kind of service, please investigate.",
"host": c["resolution"], "host": c["resolution"],
"level": "Moderate", "level": "Moderate",
"id": "IOC-04"}) "id": "IOC-05"})
# Check for suspect tlds. # Check for suspect tlds.
for tld in bl_tlds: for tld in bl_tlds:
if c["resolution"].endswith(tld[0]): if c["resolution"].endswith(tld[0]):
c["alert_tiggered"] = True c["alert_tiggered"] = True
self.alerts.append({"title": "A DNS request have been done to the domain {} which contains a suspect TLD.".format(c["resolution"]), self.alerts.append({"title": self.template["IOC-06"]["title"].format(c["resolution"]),
"description": "The domain name {} is using a suspect Top Level Domain ({}). Even not malicious, this non-generic TLD is used regularly by cybercrime ".format(c["resolution"], tld[0]) "description": self.template["IOC-06"]["description"].format(c["resolution"], tld[0]),
+ "or state-sponsored operations. Please check this domain by searching it on an internet search engine. If other alerts are related to this "
+ "host, please consider it as very suspicious.",
"host": c["resolution"], "host": c["resolution"],
"level": "Low", "level": "Low",
"id": "IOC-05"}) "id": "IOC-06"})
# Check for use of suspect nameservers. # Check for use of suspect nameservers.
try: try:
@ -230,13 +224,11 @@ class ZeekEngine(object):
for ns in bl_nameservers: for ns in bl_nameservers:
if name_servers[0].endswith(".{}.".format(ns[0])): if name_servers[0].endswith(".{}.".format(ns[0])):
c["alert_tiggered"] = True c["alert_tiggered"] = True
self.alerts.append({"title": "The domain {} is using a suspect nameserver ({}).".format(c["resolution"], name_servers[0]), self.alerts.append({"title": self.template["IOC-07"]["title"].format(c["resolution"], name_servers[0]),
"description": "The domain name {} is using a nameserver that has been explicitly tagged to be associated to malicious activities. ".format(c["resolution"]) "description": self.template["IOC-07"]["description"].format(c["resolution"]),
+ "Many cybercriminals and state-sponsored threat actors are using this kind of registrars because they allow cryptocurrencies and anonymous payments. It"
+ " is adviced to investigate on this domain and the associated running application by doing a forensic analysis of the phone.",
"host": c["resolution"], "host": c["resolution"],
"level": "Moderate", "level": "Moderate",
"id": "IOC-06"}) "id": "IOC-07"})
def files_check(self, dir): def files_check(self, dir):
""" """
@ -268,12 +260,11 @@ class ZeekEngine(object):
if f["sha1"] == cert[0]: if f["sha1"] == cert[0]:
host = self.resolve(f["ip_dst"]) host = self.resolve(f["ip_dst"])
c["alert_tiggered"] = True c["alert_tiggered"] = True
self.alerts.append({"title": "A certificate associated to {} activities have been found in the communication to {}.".format(cert[1].upper(), host), self.alerts.append({"title": self.template["IOC-08"]["title"].format(cert[1].upper(), host),
"description": "The certificate ({}) associated to {} has been explicitly tagged as malicious. This indicates that ".format(f["sha1"], host) "description": self.template["IOC-08"]["description"].format(f["sha1"], host),
+ "your device is likely compromised and need a forensic analysis.",
"host": host, "host": host,
"level": "High", "level": "High",
"id": "IOC-07"}) "id": "IOC-08"})
def ssl_check(self, dir): def ssl_check(self, dir):
""" """
@ -306,30 +297,24 @@ class ZeekEngine(object):
# Check for non generic SSL port. # Check for non generic SSL port.
if cert["port"] not in ssl_default_ports: if cert["port"] not in ssl_default_ports:
c["alert_tiggered"] = True c["alert_tiggered"] = True
self.alerts.append({"title": "SSL connection done on a non standard port ({}) to {}".format(cert["port"], host), self.alerts.append({"title": self.template["SSL-01"]["title"].format(cert["port"], host),
"description": "It is not common to see SSL connections issued from smartphones using non-standard ports. Even this can be totally legit," "description": self.template["SSL-01"]["description"].format(host),
+ " we recommend to check the reputation of {}, by looking at its WHOIS record, the associated autonomus system, its creation date, and ".format(host)
+ " by searching it the internet.",
"host": host, "host": host,
"level": "Moderate", "level": "Moderate",
"id": "SSL-01"}) "id": "SSL-01"})
# Check Free SSL certificates. # Check Free SSL certificates.
if cert["issuer"] in free_issuers: if cert["issuer"] in free_issuers:
c["alert_tiggered"] = True c["alert_tiggered"] = True
self.alerts.append({"title": "An SSL connection to {} is using a free certificate.".format(host), self.alerts.append({"title": self.template["SSL-02"]["title"].format(host),
"description": "Free certificates — such as Let's Encrypt — are wildly used by command and control servers associated to " "description": self.template["SSL-02"]["description"],
+ "malicious implants or phishing web pages. We recommend to check the host associated to this certificate, "
+ "by looking at the domain name, its creation date, or by checking its reputation on the internet.",
"host": host, "host": host,
"level": "Moderate", "level": "Moderate",
"id": "SSL-02"}) "id": "SSL-02"})
# Check for self-signed certificates. # Check for self-signed certificates.
if cert["validation_status"] == "self signed certificate in certificate chain": if cert["validation_status"] == "self signed certificate in certificate chain":
c["alert_tiggered"] = True c["alert_tiggered"] = True
self.alerts.append({"title": "The certificate associated to {} is self-signed.".format(host), self.alerts.append({"title": self.template["SSL-03"]["title"].format(host),
"description": "The use of self-signed certificates is a common thing for attacker infrastructure. We recommend to check the host {} ".format(host) "description": self.template["SSL-03"]["description"].format(host),
+ "which is associated to this certificate, by looking at the domain name (if any), its WHOIS record, its creation date, and "
+ " by checking its reputation on the internet.",
"host": host, "host": host,
"level": "Moderate", "level": "Moderate",
"id": "SSL-03"}) "id": "SSL-03"})
@ -349,8 +334,8 @@ class ZeekEngine(object):
for host, nb in hosts.items(): for host, nb in hosts.items():
if nb >= get_config(("analysis", "max_alerts")): if nb >= get_config(("analysis", "max_alerts")):
self.alerts.append({"title": "Check alerts for {}".format(host), self.alerts.append({"title": self.template["ADV-01"]["title"].format(host),
"description": "Please, check the reputation of the host {}, this one seems to be malicious as it leveraged {} alerts during the session.".format(host, nb), "description": self.template["ADV-01"]["description"].format(host, nb),
"host": host, "host": host,
"level": "High", "level": "High",
"id": "ADV-01"}) "id": "ADV-01"})

108
analysis/lang/en.json Normal file
View File

@ -0,0 +1,108 @@
{
"alerts": {
"PROTO-01": {
"title": "{} communication going outside the local network to {}.",
"description": "The {} protocol is commonly used in internal networks. Please, verify if the host {} leveraged other alerts which may indicates a possible malicious behavior."
},
"PROTO-02": {
"title": "{} connection to {} to a port over or equal to {}.",
"description": "{} connections have been seen to {} by using the port {}. The use of non-standard port can be sometimes associated to malicious activities. We recommend to check if this host has a good reputation by looking on other alerts and search it on the internet."
},
"PROTO-03": {
"title": "HTTP communications have been done to the host {}",
"description": "Your device exchanged with the host {} by using HTTP, an unencrypted protocol. Even if this behavior is not malicious by itself, it is unusual to see HTTP communications issued from smartphone applications running in the background. Please check the host reputation by searching it on the internet."
},
"PROTO-04": {
"title": "HTTP communications have been seen to the host {} on a non standard port ({}).",
"description": "Your device exchanged with the host {} by using HTTP, an unencrypted protocol on the port {}. This behavior is quite unusual. Please check the host reputation by searching it on the internet."
},
"PROTO-05": {
"title": "The server {} hasn't been resolved by any DNS query during the session",
"description": "It means that the server {} is likely not resolved by any domain name or the resolution has already been cached by the device. If the host appears in other alerts, please check it."
},
"IOC-01": {
"title": "A connection has been made to {} ({}) which is tagged as {}.",
"description": "The host {} has been explicitly blacklisted for malicious activities. Your device is likely compromised and needs to be investigated more deeply by IT security professionals."
},
"IOC-02": {
"title": "Communication to {} under the CIDR {} which is tagged as {}.",
"description": "The server {} is hosted under a network which is known to host malicious activities. Even if this behavior is not malicious by itself, you need to check if other alerts are also mentioning this host. If you have some doubts, please search this host on the internet to see if its legit or not."
},
"IOC-03": {
"title": "A DNS request have been done to {} which is tagged as {}.",
"description": "The domain name {} seen in the capture has been explicitly tagged as malicious. This indicates that your device is likely compromised and needs to be investigated deeply."
},
"IOC-04": {
"title": "A DNS request have been done to {} which is tagged as {}.",
"description": "The domain name {} seen in the capture has been explicitly tagged as a Tracker. This indicates that one of the active apps is geo-tracking your moves."
},
"IOC-05": {
"title": "A DNS request have been done to the domain {} which is a Free DNS.",
"description": "The domain name {} is using a Free DNS service. This kind of service is commonly used by cybercriminals or state-sponsored threat actors during their operations. It is very suspicious that an application running in background use this kind of service, please investigate.",
},
"IOC-06": {
"title": "A DNS request have been done to the domain {} which contains a suspect TLD.",
"description": "The domain name {} is using a suspect Top Level Domain ({}). Even not malicious, this non-generic TLD is used regularly by cybercrime or state-sponsored operations. Please check this domain by searching it on an internet search engine. If other alerts are related to this host, please consider it as very suspicious."
},
"IOC-07": {
"title": "The domain {} is using a suspect nameserver ({}).",
"description": "The domain name {} is using a nameserver that has been explicitly tagged to be associated to malicious activities. Many cybercriminals and state-sponsored threat actors are using this kind of registrars because they allow cryptocurrencies and anonymous payments. It is adviced to investigate on this domain and the associated running application by doing a forensic analysis of the phone."
},
"IOC-08": {
"title": "A certificate associated to {} activities have been found in the communication to {}.",
"description": "The certificate ({}) associated to {} has been explicitly tagged as malicious. This indicates that your device is likely compromised and need a forensic analysis."
},
"SSL-01": {
"title": "SSL connection done on a non standard port ({}) to {}",
"description": "It is not common to see SSL connections issued from smartphones using non-standard ports. Even this can be totally legit, we recommend to check the reputation of {}, by looking at its WHOIS record, the associated autonomus system, its creation date, and by searching it the internet.",
},
"SSL-02": {
"title": "An SSL connection to {} is using a free certificate.",
"description": "Free certificates — such as Let's Encrypt — are wildly used by command and control servers associated to malicious implants or phishing web pages. We recommend to check the host associated to this certificate, by looking at the domain name, its creation date, or by checking its reputation on the internet."
},
"SSL-03": {
"title": "The certificate associated to {} is self-signed.",
"description": "The use of self-signed certificates is a common thing for attacker infrastructure. We recommend to check the host {} which is associated to this certificate, by looking at the domain name (if any), its WHOIS record, its creation date, and by checking its reputation on the internet."
},
"ADV-01": {
"title": "Check the alerts for {}",
"description": "Please, check the reputation of the host {}, this one seems to be malicious as it leveraged {} alerts during the session."
},
"SNORT-01": {
"title": "Suricata rule tiggered: {}",
"description": "A network detection rule has been triggered. It's likely that your device has been compromised or have some suspect behaviour."
},
},
"report": {
"numbers": [
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine"
],
"suspect_title": "Suspect communications",
"uncat_title": "Uncategorized communications",
"whitelist_title": "Whitelisted communications",
"protocol": "Protocol",
"domain": "Domain",
"dst_ip": "Dst IP address",
"dst_port": "Dst port number",
"device_name": "Device name",
"device_mac": "Device MAC address",
"report_generated_on": "Report generated on",
"capture_duration": "Capture duration",
"packets_number": "Number of packets",
"capture_sha1": "Capture SHA1",
"report_for_the_capture": "Report for the capture",
"report_footer": "This report has been autogenerated by a Tinycheck device. For any question, bug report or feedback, please contact tinycheck@kaspersky.com.",
"high_msg": "Your device seems to be compromised as you have {} high alert(s).",
"moderate_msg": "You have {} moderate alert(s), your device might be compromised. Please look at them carefully.",
"low_msg": "You have only {} low alert(s), don't hesitate to check them.",
"none_msg": "Everything looks fine, zero alerts. Don't hesitate to check the uncategorized communications, if any."
}
}

108
analysis/lang/fr.json Normal file
View File

@ -0,0 +1,108 @@
{
"alerts": {
"PROTO-01": {
"title": "Une communication {} va à l'extérieur du réseau jusqu'à {}.",
"description": "Le protocole {} est généralement utilisé dans des réseaux internes. Vérifiez si le serveur {} a soulevé d'autres alertes. Ceci pourrait indiquer la présence d'une possible application malveillante."
},
"PROTO-02": {
"title": "Connexion {} vers {} sur un port au dessus ou égal à {}.",
"description": "Des connexions {} vers {} ont été vues utilisant le port {}. L'utilisation d'un numéro de port non standard peut être associé à des activités malveillantes. Nous recommandons de vérifier si ce serveur possède une bonne réputation en regardant les autres alertes et en le cherchant sur Internet."
},
"PROTO-03": {
"title": "Des communications HTTP on été réalisées vers {}",
"description": "Votre appareil a communiqué avec le serveur {} en utilisant HTTP, un protocole non chiffré. Même si ce n'est pas malveillant en tant que tel, il est rare de voir des communications HTTP issues d'applications installées sur des smartphones exécutées en arrière plan. Il est conseillé de vérifier la réputation du serveur en le recherchant sur Internet."
},
"PROTO-04": {
"title": "Des communications HTTP ont été réalisées vers {} sur un port non standard ({}).",
"description": "Votre appareil a communiqué vers le serveur {} en utilisant HTTP, un protocole non chiffré sur le port {}. Ce type de communication peut être signe d'une activité malveillante sur votre appareil car il est très rare qu'HTTP utilise ce port. Il est conseillé de vérifier la réputation du serveur en le recherchant sur Internet."
},
"PROTO-05": {
"title": "Le serveur {} n'a pas été résolu par le protocole DNS durant la session",
"description": "Cela signifie que le serveur {} ne possède pas de nom de domaine associé ou que sa résolution a déjà été mise en cache par votre appareil. Si le serveur apparait dans d'autres alertes, merci de vérifier sa réputation."
},
"IOC-01": {
"title": "Connexion vers {} ({}) qui est tagué en tant que {}.",
"description": "Le serveur {} est connu pour être associé à des activités malveillantes. Votre appareil est surement compromis et doit être investigué plus en détails par une équipe professionnelle."
},
"IOC-02": {
"title": "Connexion vers {} appartenant au bloc réseau {} qui est tagué en tant que {}.",
"description": "Le serveur {} est hébergé dans un réseau qui est connu pour abriter des activités malveillantes. Même si ce n'est pas malveillant en tant que tel, vous devez regarder si d'autres alertes mentionnent ce serveur. Si vous avez certains doutes, recherchez sur Internet ce serveur pour savoir s'il semble être légitime ou non."
},
"IOC-03": {
"title": "Requête DNS vers le domaine {} qui est tagué en tant que {}.",
"description": "Le serveur {} vers lequel communique votre appareil a été explicitement catégorisé en tant que malveillant. Votre appareil est sûrement compromis et doit être investigué plus en détails par une équipe professionnelle."
},
"IOC-04": {
"title": "Requête DNS vers le domaine {} qui est tagué en tant que {}.",
"description": "Le nom de domaine {} vers lequel communique votre appareil a été explicitement catégorisé comme un tracker. Ceci indique d'une application active sur votre appareil est entrain de vous géo-localiser."
},
"IOC-05": {
"title": "Requête DNS vers le domaine {} qui est un domaine gratuit.",
"description": "Le nom de domaine {} utilise un service de noms de domaine gratuits. Ce type de service est couramment utilisé par les cybercriminels ou des acteurs associés à des États au cours de leurs opérations d'espionnage. Il est très suspect qu'une application exécutée en arrière-plan utilise ce type de service, veuillez enquêter."
},
"IOC-06": {
"title": "Requête DNS vers le domaine {} contenant une extension suspecte.",
"description": "Le nom de domaine {} utilise une extension suspecte ({}). Même si cela n'est pas malveillant en-soi, l'utilisation d'une extension non générique est l'apanage d'acteurs cybercriminels et étatiques durant leurs opérations. Veuillez vérifier la pertinance de ce domaine en le recherchant sur un moteur de recherche Internet. Si d'autres alertes sont liées à ce dernier, veuillez le considérer comme très suspect."
},
"IOC-07": {
"title": "Le domaine {} utilise un serveur de noms suspect ({}).",
"description": "Le nom de domaine {} utilise un server de nom qui a été explicitement catégorisé comme associé à des activités malveillantes. Plusieurs cybercriminels et acteurs étatiques utilisent ce type de serveurs de noms car ils autorisent les paiements anonymes grâce aux cryptomonnaies. Il est conseillé d'investiguer sur ce domaine et l'application s'y connectant en réalisant une analyse post-mortem de l'appareil analysé."
},
"IOC-08": {
"title": "Un certificat associé à des activités de {} a été vu lors de communications vers {}.",
"description": "Le certificat ({}) associé au serveur {} a été explicitement catégorisé comme malveillant. Votre appareil est sûrement compromis et doit être investigué plus en détails par une équipe professionnelle."
},
"SSL-01": {
"title": "Connexion SSL utilisant un port non standard ({}) vers {}",
"description": "Il n'est pas commun de voir des connexions SSL issues de smartphones utiliser des ports non standards. Même si cela peut être totalement légitime, il est recommandé d'évaluer la réputation du serveur {}, en regardant son enregistrement WHOIS, son système autonome, sa date de création et en le recherchant sur Internet."
},
"SSL-02": {
"title": "Une connexion SSL vers {} utilise un certificat gratuit.",
"description": "Les certificats gratuits — tels que Let's Encrypt - sont largement utilisés par des serveurs de commande et de contrôle associés à des implants malveillants ou à des pages Web de phishing. Nous vous recommandons de vérifier le serveur associé à ce certificat, en regardant le nom de domaine, sa date de création, ou en vérifiant sa réputation sur Internet."
},
"SSL-03": {
"title": "Le certificat associé à {} est auto-signé.",
"description": "L'utilisation de certificats auto-signés est une chose courante pour des infrastructures d'attaque associées à des activités malveillantes. Nous vous recommandons de vérifier le serveur {} qui est associé à ce certificat, en regardant le nom de domaine (le cas échéant), son enregistrement WHOIS, sa date de création, et en vérifiant sa réputation sur Internet."
},
"ADV-01": {
"title": "Vérifiez les alertes liées au serveur {}",
"description": "Merci de vérifier la réputation et les alertes liées au serveur {}, ce dernier semble malveillant, ayant engendré {} alertes durant la session de capture."
},
"SNORT-01": {
"title": "Règle suricata déclanchée : {}",
"description": "Une règle de détection de réseau a été déclenchée. Il est probable que votre appareil ait été compromis ou présente un comportement suspect."
}
},
"report": {
"numbers": [
"un",
"deux",
"trois",
"quatre",
"cinq",
"six",
"sept",
"huit",
"neuf"
],
"suspect_title": "Communications suspectes",
"uncat_title": "Communications non catégorisées",
"whitelist_title": "Communications légitimes",
"protocol": "Protocole",
"domain": "Domaine",
"dst_ip": "Adresse IP",
"dst_port": "Port",
"device_name": "Nom de l'appareil",
"device_mac": "Adresse MAC de l'appareil",
"report_generated_on": "Rapport généré le ",
"capture_duration": "Durée de la capture",
"packets_number": "Nombre de paquets",
"capture_sha1": "SHA1 de la capture",
"report_for_the_capture": "Rapport pour la capture",
"report_footer": "Ce rapport a été automatiquement généré par une instance de TinyCheck. Pour toute question et retours, n'hésitez pas à contacter tinycheck@kaspersky.com.",
"high_msg": "Votre appareil semble être compromis car vous avez {} alerte(s) élevée(s).",
"moderate_msg": "Vous avez {} alerte(s) modérée(s), votre appareil peut être compromis. Regardez ces alertes en détail.",
"low_msg": "Vous avez uniquement {} alerte(s) faibles, n'hésitez pas à les regarder, on ne sait jamais...",
"none_msg": "Toute semble normal, vous avez aucune alerte. Cependant, n'hésitez pas à regarder les communications non catégorisées."
}
}