From 7f13a48e5d3443f5fbc49fafaab6c2aec8b80368 Mon Sep 17 00:00:00 2001 From: Taylor Date: Fri, 12 Jul 2024 14:20:10 -0500 Subject: [PATCH] etw tampering pipeline rule and registery setting in agent.conf --- .../connectors/graylog/schema/pipelines.py | 5 ++ .../connectors/graylog/services/pipelines.py | 13 ++++ .../app/connectors/graylog/utils/universal.py | 2 +- .../templates/windows_agent.conf | 5 ++ .../graylog/routes/provision.py | 2 + .../graylog/services/provision.py | 67 +++++++++++++++++++ 6 files changed, 93 insertions(+), 1 deletion(-) diff --git a/backend/app/connectors/graylog/schema/pipelines.py b/backend/app/connectors/graylog/schema/pipelines.py index cd53418f..c83b015e 100644 --- a/backend/app/connectors/graylog/schema/pipelines.py +++ b/backend/app/connectors/graylog/schema/pipelines.py @@ -69,3 +69,8 @@ class CreatePipeline(BaseModel): title: str description: str source: str + + +class ModifyPipeline(BaseModel): + pipeline_id: str + source: str diff --git a/backend/app/connectors/graylog/services/pipelines.py b/backend/app/connectors/graylog/services/pipelines.py index 51c6cd36..3012111c 100644 --- a/backend/app/connectors/graylog/services/pipelines.py +++ b/backend/app/connectors/graylog/services/pipelines.py @@ -4,11 +4,13 @@ from app.connectors.graylog.schema.pipelines import CreatePipeline from app.connectors.graylog.schema.pipelines import CreatePipelineRule from app.connectors.graylog.schema.pipelines import GraylogPipelinesResponse +from app.connectors.graylog.schema.pipelines import ModifyPipeline from app.connectors.graylog.schema.pipelines import Pipeline from app.connectors.graylog.schema.pipelines import PipelineRule from app.connectors.graylog.schema.pipelines import PipelineRulesResponse from app.connectors.graylog.utils.universal import send_get_request from app.connectors.graylog.utils.universal import send_post_request +from app.connectors.graylog.utils.universal import send_put_request from app.customer_provisioning.schema.graylog import StreamConnectionToPipelineRequest from app.customer_provisioning.schema.graylog import StreamConnectionToPipelineResponse @@ -144,6 +146,17 @@ async def create_pipeline_graylog(pipeline: CreatePipeline) -> None: await send_post_request(endpoint=endpoint, data=data) +async def modify_pipeline_graylog(pipeline: ModifyPipeline) -> None: + """ + Modifies a pipeline with the given title in Graylog. + """ + endpoint = f"/api/system/pipelines/pipeline/{pipeline.pipeline_id}" + data = { + "source": pipeline.source, + } + await send_put_request(endpoint=endpoint, data=data) + + async def get_pipeline_id(subscription: str) -> str: """ Retrieves the pipeline ID for a given subscription. diff --git a/backend/app/connectors/graylog/utils/universal.py b/backend/app/connectors/graylog/utils/universal.py index 9cba4236..6b0bce99 100644 --- a/backend/app/connectors/graylog/utils/universal.py +++ b/backend/app/connectors/graylog/utils/universal.py @@ -271,7 +271,7 @@ async def send_put_request( Returns: Dict[str, Any]: The response from the PUT request. """ - logger.info(f"Sending PUT request to {endpoint}") + logger.info(f"Sending PUT request to {endpoint} with payload {data}") async with get_db_session() as session: # This will correctly enter the context manager attributes = await get_connector_info_from_db(connector_name, session) if attributes is None: diff --git a/backend/app/customer_provisioning/templates/windows_agent.conf b/backend/app/customer_provisioning/templates/windows_agent.conf index 8c88d791..4b954d35 100644 --- a/backend/app/customer_provisioning/templates/windows_agent.conf +++ b/backend/app/customer_provisioning/templates/windows_agent.conf @@ -68,6 +68,11 @@ HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon HKEY_LOCAL_MACHINE\Software\Microsoft\Active Setup\Installed Components + + HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WMI\Autologger\EventLog-Security + HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WMI\Autologger\EventLog-Application + HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WMI\Autologger\EventLog-System + HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WMI\Autologger\EventLog-Microsoft-Windows-Sysmon-Operational HKEY_LOCAL_MACHINE\Security\Policy\Secrets HKEY_LOCAL_MACHINE\Security\SAM\Domains\Account\Users diff --git a/backend/app/stack_provisioning/graylog/routes/provision.py b/backend/app/stack_provisioning/graylog/routes/provision.py index 61a823fd..6720ca35 100644 --- a/backend/app/stack_provisioning/graylog/routes/provision.py +++ b/backend/app/stack_provisioning/graylog/routes/provision.py @@ -9,6 +9,7 @@ from app.stack_provisioning.graylog.schema.provision import AvailbleContentPacksOverview from app.stack_provisioning.graylog.schema.provision import ProvisionContentPackRequest from app.stack_provisioning.graylog.schema.provision import ProvisionGraylogResponse +from app.stack_provisioning.graylog.services.provision import check_pipeline_rules from app.stack_provisioning.graylog.services.provision import provision_content_pack from app.stack_provisioning.graylog.services.utils import does_content_pack_exist from app.stack_provisioning.graylog.services.utils import system_version_check @@ -50,6 +51,7 @@ async def provision_content_pack_route( await system_version_check(compatible_version="5.0.13+083613e") await does_content_pack_exist(content_pack_name=content_pack_request.content_pack_name.name) await provision_content_pack(content_pack_request) + await check_pipeline_rules() return ProvisionGraylogResponse( success=True, message=f"{content_pack_request.content_pack_name.name} Content Pack provisioned successfully", diff --git a/backend/app/stack_provisioning/graylog/services/provision.py b/backend/app/stack_provisioning/graylog/services/provision.py index 5fc3a7ff..01540229 100644 --- a/backend/app/stack_provisioning/graylog/services/provision.py +++ b/backend/app/stack_provisioning/graylog/services/provision.py @@ -1,12 +1,18 @@ import json +from enum import Enum from pathlib import Path +from typing import List from uuid import uuid4 from fastapi import HTTPException from loguru import logger +from app.connectors.graylog.schema.pipelines import CreatePipelineRule +from app.connectors.graylog.schema.pipelines import PipelineRulesResponse from app.connectors.graylog.services.content_packs import insert_content_pack from app.connectors.graylog.services.content_packs import install_content_pack +from app.connectors.graylog.services.pipelines import create_pipeline_rule +from app.connectors.graylog.services.pipelines import get_pipeline_rules from app.stack_provisioning.graylog.schema.provision import AvailableContentPacks from app.stack_provisioning.graylog.schema.provision import ProvisionContentPackRequest from app.stack_provisioning.graylog.schema.provision import ProvisionGraylogResponse @@ -173,6 +179,67 @@ async def provision_content_pack(content_pack_request: ProvisionContentPackReque ) +class PipelineRuleTitles(Enum): + ETW = "Set Syslog Level to ALERT for ETW Registry" + + +async def check_pipeline_rules() -> None: + """ + Checks if the pipeline rules exist in Graylog. If they don't, create them. + """ + pipeline_rules = await get_pipeline_rules() + non_existing_rules = await pipeline_rules_exists(pipeline_rules) + if non_existing_rules: + logger.info(f"Creating pipeline rules: {non_existing_rules}") + await create_pipeline_rules(non_existing_rules) + + +async def pipeline_rules_exists(pipeline_rules: PipelineRulesResponse) -> List[str]: + """ + Checks if the pipeline rules exist in Graylog and returns a list of non-existing pipeline rules. + """ + return [ + rule_title.value + for rule_title in PipelineRuleTitles + if not any(rule.title == rule_title.value for rule in pipeline_rules.pipeline_rules) + ] + + +async def create_pipeline_rules(non_existing_rules: List[str]) -> None: + """ + Creates the given pipeline rules. + """ + rule_creators = { + "Set Syslog Level to ALERT for ETW Registry": create_etw_rule, + } + + for rule_title in non_existing_rules: + logger.info(f"Creating pipeline rule {rule_title}.") + await rule_creators[rule_title](rule_title) + + +async def create_etw_rule(rule_title: str) -> None: + """ + Creates the 'Set Syslog Level to ALERT for ETW Registry' pipeline rule. + """ + rule_source = ( + f'rule "{rule_title}"\n' + "when\n" + ' has_field("syscheck_path") &&\n' + ' starts_with(to_string($message.syscheck_path), "HKEY_LOCAL_MACHINE\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WMI\\\\Autologger\\\\EventLog")\n' + "then\n" + ' set_field("syslog_level", "ALERT");\n' + "end" + ) + await create_pipeline_rule( + CreatePipelineRule( + title=rule_title, + description=rule_title, + source=rule_source, + ), + ) + + # ! NETWORK CONNECTOR CONTENT PACKS PROVISIONING ! # async def filter_content_packs(content_packs, protocol_type): if protocol_type == "TCP":