Merge pull request #26 from avast/classification

Classification
pull/27/merge
Thorsten Sick 2 years ago committed by GitHub
commit 516914e195
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,101 @@
#!/usr/bin/env python3
""" Use logic to detect an attack in sensor logs. This is a PROTOTYPE !!!! """
# TODO: Move essential parts to app folder as soon as it is obvious what is required. Maybe even add the code to existing plugins (sensor plugins ?) or create a new plugin type. Mybe ship that with the sensor in the same folder.
import argparse
import json
import re
from pprint import pprint
from datetime import datetime
from collections import defaultdict
DEFAULT_SENSOR_LOG = "loot/2022_01_07___18_36_21/target3/sensors/linux_filebeat/filebeat.json"
class Detector():
"""
An experimental prototype to play with detection and display of events. This code should later be part of plugins.
But until I know where this is going we have this prototype
"""
def __init__(self, args):
self.processed_data = []
as_text = "["
# Filebeat jsons are not valid jsons and have to be fixed
with open(args.sensor_log, "rt") as fh:
new = fh.read()
new = new.replace("}{", "},{")
as_text += new
as_text += "]"
self.data = json.loads(as_text)
def detect(self, bucket_size=10, limit=20):
""" detect
"""
regex = r"^(?P<date>\w*\W*\d{1,2} \d{1,2}:\d{1,2}:\d{1,2}) (?P<target>\w*) (?P<process>\w*)\[(?P<pid>\d*)\]: Failed password for invalid user (?P<user>\w*) from (?P<attacker>\S*) port (?P<attacker_port>\d*)"
detected = set()
self.processed_data = []
histogram = defaultdict(lambda: 0)
for entry in self.data:
if "Failed password" in entry["message"]:
res = re.match(regex, entry["message"])
if res:
data = res.groupdict()
year = entry['@timestamp'].split("-")[0]
pdate = datetime.strptime(f"{year} {data['date']}", "%Y %b %d %H:%M:%S")
data["timestamp_short"] = int(pdate.timestamp())
data["timestamp"] = pdate.timestamp()
data["detections"] = []
self.processed_data.append(data)
histogram[data["timestamp_short"] // bucket_size] += 1
# detect password brute forcing
for akey, value in histogram.items():
if value > limit:
print(akey)
for processed in self.processed_data:
if processed["timestamp_short"] // bucket_size == akey:
processed["detections"].append("pwd_bruteforce")
detected.add("pwd_bruteforce")
pprint(self.processed_data)
pprint(histogram)
return detected
def sequence_diagram(self):
""" Creates a sequence diagram based on processed data (call detect first). Use plantuml to process it: https://plantuml.com/de/sequence-diagram"""
# For pdw_bruteforce
res = "@startuml\n"
for entry in self.processed_data:
if "pwd_bruteforce" in entry["detections"]:
res += f"{entry['attacker']} -> {entry['target']}: to {entry['process']} as {entry['user']}\n"
res += "@enduml\n"
print(res)
def create_parser():
""" Creates the parser for the command line arguments"""
parser = argparse.ArgumentParser("Detects attacks in logs. Can also create diagrams for the part of the logs indicating the attack")
parser.add_argument("--sensor_log", default=DEFAULT_SENSOR_LOG, help="The sensor log to detect in")
# parser.add_argument("--outfile", default="tools/human_readable_documentation/source/contents.rst", help="The default output file")
return parser
if __name__ == "__main__":
arguments = create_parser().parse_args()
detector = Detector(arguments)
if len(detector.detect()) > 0:
detector.sequence_diagram()

@ -56,5 +56,6 @@ class HydraPlugin(AttackPlugin):
attack_name=self.name,
ttp=self.ttp,
logid=logid)
cmd = f"cd {playground};"
return total_res

@ -1,3 +1,131 @@
xvefdxjuqk
kvwflcmiqa
yhxnhlqwtx
ouemazgzmb
twwhgsiofq
jbofrkhrnn
dwpzoogxsw
lozrjyqnls
hvgrgknatd
xrpjllxtyo
nanqmrnkks
csnpxuuxfb
yiljmjpocp
zyfczzfvwh
dlqcdyahnz
ehxfcbeijg
jkpmbpcxnj
ltjtbxpamg
eyrajqnuut
dapjegddax
eouifybuhl
ibwvvdflzd
fkwnnmqfyo
vcjxqrxtva
eyifkppnky
ysdcwndhea
xvdkwbqoji
vnpoudewpo
nsbaoqycbi
vuwkudxvfb
pvohjnufds
vtxhlvxznf
cmqnywqpjh
gsquplthrj
tfnrakwtiy
gitllmexga
dvbxkbehml
pnorflbeck
asacllxlwk
rqvostegmt
lsvqkpgyzg
gvwbvpilqw
eedoziepoe
kycwkkirxl
qrivxifdij
tavotpkspl
kjirpjnked
helaayxgwt
jtuooqdfsc
sghskzybja
tziamzckhq
defaqhtbey
jxbrysrozn
wygslrurew
rjgagkgzmn
wsezgkypcr
atigwhtfvl
kifozivamt
hzllpwvksz
afolruiwbp
zpptgbtjqw
ohcnltaufb
sxlxvgowsb
vwjjodasay
qaebjwrccw
ldsqykstmi
gtdnytalcz
cqoslsepnt
lvgdetcmno
hdhlymtrne
rtzgfhpjsu
xcfoisbbny
wuxaqvfpvi
yugwtitfxb
yjuihpgqpk
behpgnnjiq
gvsanlarla
ntggcwhzez
dzbyasmoni
xqbstvhrbv
snupvltvlo
enwiqyjnau
kibypdumkk
prrddhqlfs
xhsbshhmba
nfbrqxmdfg
frgqhcdkqg
kvqrfdhyvv
pwootxogtr
vsnyxeoxuu
amtvaepfav
fflegmisbl
ulucqdvido
abwftzqlud
sbmezxoidz
zigaehmkof
fixdalasyk
ewrvfuiukl
vpgnwjhutk
ncrpjcodvg
ntpsqfborm
abcphtoyge
oxpgalzoec
fdtevjulsm
dspmmlfbtf
hucvyrlzwz
ychsetjmxr
qiaqhmhksj
bpjnvhklgr
cqoxdifygi
gqvqgfggfj
ylhvukeqhg
lpxutcvcmn
lwbmfwteod
fnqlcbmriv
lqaqwnkjmp
flkrzmiujr
hlmqbkpjog
burqlqzqsm
upbekwehbt
lktdviabid
yehszqkaut
klhnmbamqt
kavsmnqlld
kivpjuysxr
kqsynlnokn
ajsiaqtyxw
crjoljcshx
12345
qwert
qwertz

@ -1,5 +1,4 @@
test
root
password
nonexistend_user_1
nonexistend_user_2
nonexistend_user_1

@ -8,7 +8,7 @@ filter {}
output {
file {
path => "{{playground}}/filebeat.json"
path => "/tmp/filebeat_collection.json"
codec => json
id => "id_filebeat"
create_if_deleted => true

@ -62,8 +62,10 @@ class LinuxFilebeatPlugin(SensorPlugin):
# Cleanup
self.run_cmd(f"rm {pg}/filebeat.json")
self.run_cmd(f"touch {pg}/filebeat.json")
self.run_cmd(f"chmod o+w {pg}/filebeat.json")
# self.run_cmd(f"touch {pg}/filebeat.json")
# self.run_cmd(f"chmod o+w {pg}/filebeat.json")
self.run_cmd("touch /tmp/filebeat_collection.json")
self.run_cmd("sudo chown logstash:logstash /tmp/filebeat_collection.json")
return False
@ -75,11 +77,18 @@ class LinuxFilebeatPlugin(SensorPlugin):
def start(self):
self.run_cmd("sudo filebeat modules enable system iptables")
self.run_cmd("sudo filebeat setup --pipelines --modules iptables,system,")
self.run_cmd("sudo filebeat setup --pipelines --modules iptables,system,") # check with sudo filebeat modules list
# self.run_cmd("sudo systemctl start logstash.service")
self.run_cmd("sudo nohup /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/filebeat.conf &", disown=True)
# self.run_cmd("sudo nohup /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/filebeat.conf &", disown=True)
self.run_cmd("sudo chown logstash:logstash filebeat.json") # check with: systemctl status logstash.service
self.run_cmd("sudo systemctl start logstash") # check with: systemctl status logstash.service
self.run_cmd("sudo systemctl enable logstash") # check with: systemctl status logstash.service
time.sleep(20)
self.run_cmd("sudo service filebeat start")
self.run_cmd("sudo systemctl start filebeat") # check with: systemctl status filebeat.service
self.run_cmd("sudo systemctl enable filebeat") # check with: systemctl status filebeat.service
# Check the logs: sudo journalctl -u filebeat.service
# Check the logs: sudo journalctl -u logstash.service
return None
@ -90,7 +99,7 @@ class LinuxFilebeatPlugin(SensorPlugin):
def collect(self, path):
""" Collect sensor data """
pg = self.get_playground()
dst = os.path.join(path, "filebeat.json")
self.get_from_machine(f"{pg}/filebeat.json", dst) # nosec
# self.get_from_machine(f"{pg}/filebeat.json", dst) # nosec
self.get_from_machine("/tmp/filebeat_collection.json", dst) # nosec
return [dst]

Loading…
Cancel
Save