From f4cdde677612e3c04e408174b70c18f6dc900764 Mon Sep 17 00:00:00 2001 From: Thorsten Sick Date: Mon, 17 May 2021 09:37:02 +0200 Subject: [PATCH] Added linux filebeat sensor and template feature for config files --- plugins/base/plugin_base.py | 14 ++- .../default/sensors/linux_filebeat/README.md | 12 ++ .../linux_filebeat/filebeat_template.conf | 19 ++++ .../linux_filebeat/linux_filebeat_plugin.py | 103 ++++++++++++++++++ 4 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 plugins/default/sensors/linux_filebeat/README.md create mode 100644 plugins/default/sensors/linux_filebeat/filebeat_template.conf create mode 100644 plugins/default/sensors/linux_filebeat/linux_filebeat_plugin.py diff --git a/plugins/base/plugin_base.py b/plugins/base/plugin_base.py index abc813f..475ba9e 100644 --- a/plugins/base/plugin_base.py +++ b/plugins/base/plugin_base.py @@ -38,9 +38,16 @@ class BasePlugin(): """ Set the attack logger for this machine """ self.attack_logger = attack_logger + def process_templates(self): + """ A method you can optionally implement to transfer your jinja2 templates into the files yo want to send to the target. See 'required_files' """ + + return + def setup(self): """ Prepare everything for the plugin """ + self.process_templates() + for a_file in self.required_files: src = os.path.join(os.path.dirname(self.plugin_path), a_file) self.vprint(src, 3) @@ -128,10 +135,15 @@ class BasePlugin(): raise NotImplementedError + def get_plugin_path(self): + """ Returns the path the plugin file(s) are stored in """ + + return os.path.join(os.path.dirname(self.plugin_path)) + def get_default_config_filename(self): """ Generate the default filename of the default configuration file """ - return os.path.join(os.path.dirname(self.plugin_path), self.default_config_name) + return os.path.join(self.get_plugin_path(), self.default_config_name) def get_raw_default_config(self): """ Returns the default config as string. Usable as an example and for documentation """ diff --git a/plugins/default/sensors/linux_filebeat/README.md b/plugins/default/sensors/linux_filebeat/README.md new file mode 100644 index 0000000..848b21f --- /dev/null +++ b/plugins/default/sensors/linux_filebeat/README.md @@ -0,0 +1,12 @@ +# Filebeat plugin + +Basic demo plugin for a linux filebeat sensor. + +## Important feature + +The sensor demos a feature to create config files based on a template before the file is deployed to the target. + + +## Current state + +Basic functionality is working. The logging is not optimized. Will come back to it as soon as we have more attacks. \ No newline at end of file diff --git a/plugins/default/sensors/linux_filebeat/filebeat_template.conf b/plugins/default/sensors/linux_filebeat/filebeat_template.conf new file mode 100644 index 0000000..249d6be --- /dev/null +++ b/plugins/default/sensors/linux_filebeat/filebeat_template.conf @@ -0,0 +1,19 @@ +input { + beats { + port => 5044 + } +} + +filter {} + +output { + file { + path => "{{playground}}/filebeat.json" + codec => json + id => "id_filebeat" + create_if_deleted => true + write_behavior => "append" + } + + stdout{} +} \ No newline at end of file diff --git a/plugins/default/sensors/linux_filebeat/linux_filebeat_plugin.py b/plugins/default/sensors/linux_filebeat/linux_filebeat_plugin.py new file mode 100644 index 0000000..9f6c717 --- /dev/null +++ b/plugins/default/sensors/linux_filebeat/linux_filebeat_plugin.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 + +# A plugin to experiment with Linux logstash filebeat sensors + +from plugins.base.sensor import SensorPlugin +import os +import time +from jinja2 import Environment, FileSystemLoader, select_autoescape + + +class LinuxFilebeatPlugin(SensorPlugin): + # Boilerplate + name = "linux_filebeat" + description = "Linux filebeat plugin" + + required_files = ["filebeat.conf", + "filebeat.yml", + ] + + def __init__(self): + super().__init__() + self.plugin_path = __file__ + + self.debugit = False + + def process_templates(self): + """ process jinja2 templates of the config files and insert own config """ + + # TODO: Implement + + env = Environment( + loader=FileSystemLoader(self.get_plugin_path(), encoding='utf-8', followlinks=False), + autoescape=select_autoescape() + ) + template = env.get_template("filebeat_template.conf") + dest = os.path.join(self.get_plugin_path(), "filebeat.conf") + with open(dest, "wt") as fh: + res = template.render({"playground": self.get_playground()}) + fh.write(res) + + def prime(self): + """ Hard-core install. Requires a reboot """ + + # For reference: This is the core config we will need. In addition there are two reg files to apply to the registry + # sc control aswbidsagent 255 + # timeout /t 5 + # 'copy /y "cd %userprofile% & aswidptestdll.dll" "c:\Program Files\Avast Software\Avast\"' + # reg.exe add "HKLM\SOFTWARE\Avast Software\Avast\properties\IDP\Setting" /v debug_channel.enabled /t REG_DWORD /d 1 /f + # timeout /t 2 + # sc start aswbidsagent + + # Important: AV must be 21.2 + # dll_name = self.conf["dll_name"] + + # idp_tool_folder = self.conf["idp_tool_folder"] + + pg = self.get_playground() + + self.vprint("Installing Linux filebeat sensor", 3) + + self.run_cmd(f"sudo wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -") + self.run_cmd('sudo echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-7.x.list') + self.run_cmd("sudo apt update") + self.run_cmd("sudo apt -y install default-jre") + self.run_cmd("sudo apt -y install logstash") + self.run_cmd("sudo apt -y install filebeat") + + # Copy config + self.run_cmd(f"sudo cp {pg}/filebeat.yml /etc/filebeat/filebeat.yml") + self.run_cmd(f"sudo cp {pg}/filebeat.conf /etc/logstash/conf.d") + + # 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") + + return False + + def install(self): + """ Installs the filebeat sensor """ + + return + + 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 systemctl enable filebeat") + self.run_cmd("sudo systemctl start filebeat") + self.run_cmd("sudo systemctl enable logstash.service") + self.run_cmd("sudo systemctl start logstash.service") + + return None + + def stop(self): + """ Stop the sensor """ + return + + def collect(self, path): + """ Collect sensor data """ + + pg = self.get_playground() + self.get_from_machine(f"{pg}/filebeat.json", os.path.join(path, "filebeat.json")) # nosec \ No newline at end of file