Skip to content

Commit

Permalink
etw tampering pipeline rule and registery setting in agent.conf
Browse files Browse the repository at this point in the history
  • Loading branch information
taylorwalton committed Jul 12, 2024
1 parent f02568e commit 7f13a48
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 1 deletion.
5 changes: 5 additions & 0 deletions backend/app/connectors/graylog/schema/pipelines.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,8 @@ class CreatePipeline(BaseModel):
title: str
description: str
source: str


class ModifyPipeline(BaseModel):
pipeline_id: str
source: str
13 changes: 13 additions & 0 deletions backend/app/connectors/graylog/services/pipelines.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion backend/app/connectors/graylog/utils/universal.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@
<windows_registry arch="both">HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows</windows_registry>
<windows_registry arch="both">HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon</windows_registry>
<windows_registry arch="both">HKEY_LOCAL_MACHINE\Software\Microsoft\Active Setup\Installed Components</windows_registry>
<!-- Added by SOCFortress For ETW Tampering -->
<windows_registry arch="both">HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WMI\Autologger\EventLog-Security</windows_registry>
<windows_registry arch="both">HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WMI\Autologger\EventLog-Application</windows_registry>
<windows_registry arch="both">HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WMI\Autologger\EventLog-System</windows_registry>
<windows_registry arch="both">HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WMI\Autologger\EventLog-Microsoft-Windows-Sysmon-Operational</windows_registry>
<!-- Windows registry entries to ignore. -->
<registry_ignore>HKEY_LOCAL_MACHINE\Security\Policy\Secrets</registry_ignore>
<registry_ignore>HKEY_LOCAL_MACHINE\Security\SAM\Domains\Account\Users</registry_ignore>
Expand Down
2 changes: 2 additions & 0 deletions backend/app/stack_provisioning/graylog/routes/provision.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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",
Expand Down
67 changes: 67 additions & 0 deletions backend/app/stack_provisioning/graylog/services/provision.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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":
Expand Down

0 comments on commit 7f13a48

Please sign in to comment.