@cryptotaxi247 / CoPilot / commits / e76fc72f

etw tampering pipeline rule and registery setting in agent.conf (#273)

taylor_socfortress committed Jul 12, 2024 at 14:22 UTC e76fc72fed406cde4803dbb416879177f82e9a91
6 files changed +93 -1
backend/app/connectors/graylog/schema/pipelines.py
+5
@@ -69,3 +69,8 @@ class CreatePipeline(BaseModel):
69 title: str
70 description: str
71 source: str
72 +
73 +
74 +class ModifyPipeline(BaseModel):
75 + pipeline_id: str
76 + source: str
backend/app/connectors/graylog/services/pipelines.py
+13
@@ -4,11 +4,13 @@ from loguru import logger
4 from app.connectors.graylog.schema.pipelines import CreatePipeline
5 from app.connectors.graylog.schema.pipelines import CreatePipelineRule
6 from app.connectors.graylog.schema.pipelines import GraylogPipelinesResponse
7 +from app.connectors.graylog.schema.pipelines import ModifyPipeline
8 from app.connectors.graylog.schema.pipelines import Pipeline
9 from app.connectors.graylog.schema.pipelines import PipelineRule
10 from app.connectors.graylog.schema.pipelines import PipelineRulesResponse
11 from app.connectors.graylog.utils.universal import send_get_request
12 from app.connectors.graylog.utils.universal import send_post_request
13 +from app.connectors.graylog.utils.universal import send_put_request
14 from app.customer_provisioning.schema.graylog import StreamConnectionToPipelineRequest
15 from app.customer_provisioning.schema.graylog import StreamConnectionToPipelineResponse
16
@@ -144,6 +146,17 @@ async def create_pipeline_graylog(pipeline: CreatePipeline) -> None:
146 await send_post_request(endpoint=endpoint, data=data)
147
148
149 +async def modify_pipeline_graylog(pipeline: ModifyPipeline) -> None:
150 + """
151 + Modifies a pipeline with the given title in Graylog.
152 + """
153 + endpoint = f"/api/system/pipelines/pipeline/{pipeline.pipeline_id}"
154 + data = {
155 + "source": pipeline.source,
156 + }
157 + await send_put_request(endpoint=endpoint, data=data)
158 +
159 +
160 async def get_pipeline_id(subscription: str) -> str:
161 """
162 Retrieves the pipeline ID for a given subscription.
backend/app/connectors/graylog/utils/universal.py
+1 -1
@@ -271,7 +271,7 @@ async def send_put_request(
271 Returns:
272 Dict[str, Any]: The response from the PUT request.
273 """
274 - logger.info(f"Sending PUT request to {endpoint}")
274 + logger.info(f"Sending PUT request to {endpoint} with payload {data}")
275 async with get_db_session() as session: # This will correctly enter the context manager
276 attributes = await get_connector_info_from_db(connector_name, session)
277 if attributes is None:
backend/app/customer_provisioning/templates/windows_agent.conf
+5
@@ -68,6 +68,11 @@
68 <windows_registry arch="both">HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows</windows_registry>
69 <windows_registry arch="both">HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon</windows_registry>
70 <windows_registry arch="both">HKEY_LOCAL_MACHINE\Software\Microsoft\Active Setup\Installed Components</windows_registry>
71 + <!-- Added by SOCFortress For ETW Tampering -->
72 + <windows_registry arch="both">HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WMI\Autologger\EventLog-Security</windows_registry>
73 + <windows_registry arch="both">HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WMI\Autologger\EventLog-Application</windows_registry>
74 + <windows_registry arch="both">HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WMI\Autologger\EventLog-System</windows_registry>
75 + <windows_registry arch="both">HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WMI\Autologger\EventLog-Microsoft-Windows-Sysmon-Operational</windows_registry>
76 <!-- Windows registry entries to ignore. -->
77 <registry_ignore>HKEY_LOCAL_MACHINE\Security\Policy\Secrets</registry_ignore>
78 <registry_ignore>HKEY_LOCAL_MACHINE\Security\SAM\Domains\Account\Users</registry_ignore>
backend/app/stack_provisioning/graylog/routes/provision.py
+2
@@ -9,6 +9,7 @@ from app.stack_provisioning.graylog.schema.provision import (
9 from app.stack_provisioning.graylog.schema.provision import AvailbleContentPacksOverview
10 from app.stack_provisioning.graylog.schema.provision import ProvisionContentPackRequest
11 from app.stack_provisioning.graylog.schema.provision import ProvisionGraylogResponse
12 +from app.stack_provisioning.graylog.services.provision import check_pipeline_rules
13 from app.stack_provisioning.graylog.services.provision import provision_content_pack
14 from app.stack_provisioning.graylog.services.utils import does_content_pack_exist
15 from app.stack_provisioning.graylog.services.utils import system_version_check
@@ -50,6 +51,7 @@ async def provision_content_pack_route(
51 await system_version_check(compatible_version="5.0.13+083613e")
52 await does_content_pack_exist(content_pack_name=content_pack_request.content_pack_name.name)
53 await provision_content_pack(content_pack_request)
54 + await check_pipeline_rules()
55 return ProvisionGraylogResponse(
56 success=True,
57 message=f"{content_pack_request.content_pack_name.name} Content Pack provisioned successfully",
backend/app/stack_provisioning/graylog/services/provision.py
+67
@@ -1,12 +1,18 @@
1 import json
2 +from enum import Enum
3 from pathlib import Path
4 +from typing import List
5 from uuid import uuid4
6
7 from fastapi import HTTPException
8 from loguru import logger
9
10 +from app.connectors.graylog.schema.pipelines import CreatePipelineRule
11 +from app.connectors.graylog.schema.pipelines import PipelineRulesResponse
12 from app.connectors.graylog.services.content_packs import insert_content_pack
13 from app.connectors.graylog.services.content_packs import install_content_pack
14 +from app.connectors.graylog.services.pipelines import create_pipeline_rule
15 +from app.connectors.graylog.services.pipelines import get_pipeline_rules
16 from app.stack_provisioning.graylog.schema.provision import AvailableContentPacks
17 from app.stack_provisioning.graylog.schema.provision import ProvisionContentPackRequest
18 from app.stack_provisioning.graylog.schema.provision import ProvisionGraylogResponse
@@ -173,6 +179,67 @@ async def provision_content_pack(content_pack_request: ProvisionContentPackReque
179 )
180
181
182 +class PipelineRuleTitles(Enum):
183 + ETW = "Set Syslog Level to ALERT for ETW Registry"
184 +
185 +
186 +async def check_pipeline_rules() -> None:
187 + """
188 + Checks if the pipeline rules exist in Graylog. If they don't, create them.
189 + """
190 + pipeline_rules = await get_pipeline_rules()
191 + non_existing_rules = await pipeline_rules_exists(pipeline_rules)
192 + if non_existing_rules:
193 + logger.info(f"Creating pipeline rules: {non_existing_rules}")
194 + await create_pipeline_rules(non_existing_rules)
195 +
196 +
197 +async def pipeline_rules_exists(pipeline_rules: PipelineRulesResponse) -> List[str]:
198 + """
199 + Checks if the pipeline rules exist in Graylog and returns a list of non-existing pipeline rules.
200 + """
201 + return [
202 + rule_title.value
203 + for rule_title in PipelineRuleTitles
204 + if not any(rule.title == rule_title.value for rule in pipeline_rules.pipeline_rules)
205 + ]
206 +
207 +
208 +async def create_pipeline_rules(non_existing_rules: List[str]) -> None:
209 + """
210 + Creates the given pipeline rules.
211 + """
212 + rule_creators = {
213 + "Set Syslog Level to ALERT for ETW Registry": create_etw_rule,
214 + }
215 +
216 + for rule_title in non_existing_rules:
217 + logger.info(f"Creating pipeline rule {rule_title}.")
218 + await rule_creators[rule_title](rule_title)
219 +
220 +
221 +async def create_etw_rule(rule_title: str) -> None:
222 + """
223 + Creates the 'Set Syslog Level to ALERT for ETW Registry' pipeline rule.
224 + """
225 + rule_source = (
226 + f'rule "{rule_title}"\n'
227 + "when\n"
228 + ' has_field("syscheck_path") &&\n'
229 + ' starts_with(to_string($message.syscheck_path), "HKEY_LOCAL_MACHINE\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WMI\\\\Autologger\\\\EventLog")\n'
230 + "then\n"
231 + ' set_field("syslog_level", "ALERT");\n'
232 + "end"
233 + )
234 + await create_pipeline_rule(
235 + CreatePipelineRule(
236 + title=rule_title,
237 + description=rule_title,
238 + source=rule_source,
239 + ),
240 + )
241 +
242 +
243 # ! NETWORK CONNECTOR CONTENT PACKS PROVISIONING ! #
244 async def filter_content_packs(content_packs, protocol_type):
245 if protocol_type == "TCP":