mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-09-13 03:31:31 +03:00
feat: add 5 new cybersecurity skills - RDP brute force, Covenant C2, Calico network policies, heap spray analysis, T1098 hunting
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Mahipal
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
name: hunting-for-t1098-account-manipulation
|
||||
description: Hunt for MITRE ATT&CK T1098 account manipulation including shadow admin creation, SID history injection, group membership changes, and credential modifications using Windows Security Event Logs.
|
||||
domain: cybersecurity
|
||||
subdomain: threat-hunting
|
||||
tags: [threat-hunting, mitre-attack, t1098, account-manipulation, active-directory, persistence]
|
||||
version: "1.0"
|
||||
author: mahipal
|
||||
license: MIT
|
||||
---
|
||||
# Hunting for T1098 Account Manipulation
|
||||
|
||||
## Overview
|
||||
|
||||
MITRE ATT&CK T1098 (Account Manipulation) covers adversary actions to maintain or expand access to compromised accounts, including adding credentials, modifying group memberships, SID history injection, and creating shadow admin accounts. This skill covers detecting these techniques through Windows Security Event Log analysis (Event IDs 4738, 4728, 4732, 4756, 4670, 5136), correlating group membership changes with privilege escalation indicators, and identifying anomalous account modification patterns.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Windows Security Event Logs (EVTX format) or SIEM access
|
||||
- Python 3.9+ with `python-evtx`, `lxml` libraries
|
||||
- Understanding of Active Directory group structure and SID architecture
|
||||
- Familiarity with MITRE ATT&CK T1098 sub-techniques
|
||||
|
||||
## Steps
|
||||
|
||||
### Step 1: Parse Account Modification Events
|
||||
Extract Event IDs 4738 (user account changed), 4728/4732/4756 (member added to security groups), and 5136 (directory service object modified).
|
||||
|
||||
### Step 2: Detect Privileged Group Changes
|
||||
Flag additions to Domain Admins, Enterprise Admins, Schema Admins, Administrators, and Backup Operators groups.
|
||||
|
||||
### Step 3: Identify Shadow Admin Indicators
|
||||
Detect accounts receiving AdminSDHolder protection, direct privilege assignment, or SID history injection.
|
||||
|
||||
### Step 4: Correlate with Attack Timeline
|
||||
Cross-reference account changes with authentication events to identify initial compromise and persistence establishment.
|
||||
|
||||
## Expected Output
|
||||
|
||||
JSON report with detected account manipulation events, privileged group changes, shadow admin indicators, and timeline correlation.
|
||||
@@ -0,0 +1,68 @@
|
||||
# API Reference: Hunting for T1098 Account Manipulation
|
||||
|
||||
## Key Windows Security Event IDs
|
||||
|
||||
| Event ID | Description | T1098 Relevance |
|
||||
|----------|-------------|-----------------|
|
||||
| 4738 | User account changed | Account property modification |
|
||||
| 4728 | Member added to global security group | Domain Admins, etc. |
|
||||
| 4732 | Member added to local security group | Administrators, etc. |
|
||||
| 4756 | Member added to universal security group | Enterprise Admins |
|
||||
| 4729 | Member removed from global security group | Evidence cleanup |
|
||||
| 4670 | Permissions on object changed | ACL manipulation |
|
||||
| 5136 | Directory service object modified | SID History, SPNs |
|
||||
| 4724 | Password reset attempted | Credential takeover |
|
||||
| 4781 | Account name changed | Account rename evasion |
|
||||
|
||||
## Privileged Groups to Monitor
|
||||
|
||||
| Group | Risk | Impact |
|
||||
|-------|------|--------|
|
||||
| Domain Admins | Critical | Full domain control |
|
||||
| Enterprise Admins | Critical | Forest-wide admin |
|
||||
| Schema Admins | Critical | AD schema modification |
|
||||
| Administrators | High | Local admin on DCs |
|
||||
| Backup Operators | High | Read any file, backup SAM |
|
||||
| DNS Admins | High | DLL injection on DCs |
|
||||
| Account Operators | Medium | Create/modify accounts |
|
||||
|
||||
## Sensitive AD Attributes
|
||||
|
||||
| Attribute | Attack Technique |
|
||||
|-----------|-----------------|
|
||||
| SIDHistory | T1134.005 - SID History Injection |
|
||||
| servicePrincipalName | T1558.003 - Kerberoasting setup |
|
||||
| msDS-AllowedToDelegateTo | Constrained delegation abuse |
|
||||
| msDS-AllowedToActOnBehalfOfOtherIdentity | RBCD attack |
|
||||
| AdminCount | AdminSDHolder persistence |
|
||||
| userAccountControl | Account flag manipulation |
|
||||
|
||||
## python-evtx Parsing
|
||||
|
||||
```python
|
||||
import Evtx.Evtx as evtx
|
||||
|
||||
with evtx.Evtx("Security.evtx") as log:
|
||||
for record in log.records():
|
||||
xml_str = record.xml()
|
||||
# Parse XML to extract EventID and Data fields
|
||||
```
|
||||
|
||||
Install: `pip install python-evtx lxml`
|
||||
|
||||
## MITRE T1098 Sub-Techniques
|
||||
|
||||
| ID | Name | Key Indicator |
|
||||
|----|------|---------------|
|
||||
| T1098.001 | Additional Cloud Credentials | New keys/certs added |
|
||||
| T1098.002 | Additional Email Delegate Access | Mailbox permission grants |
|
||||
| T1098.003 | Additional Cloud Roles | Role assignment changes |
|
||||
| T1098.004 | SSH Authorized Keys | authorized_keys modification |
|
||||
| T1098.005 | Device Registration | Rogue device enrollment |
|
||||
|
||||
## References
|
||||
|
||||
- MITRE T1098: https://attack.mitre.org/techniques/T1098/
|
||||
- CISA Eviction Guide: https://www.cisa.gov/eviction-strategies-tool/info-attack/T1098
|
||||
- Windows Event Mapping: https://www.socinvestigation.com/mapping-mitre-attck-with-window-event-log-ids/
|
||||
- python-evtx: https://github.com/williballenthin/python-evtx
|
||||
@@ -0,0 +1,223 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for hunting MITRE ATT&CK T1098 account manipulation.
|
||||
|
||||
Detects shadow admin creation, SID history injection, privileged
|
||||
group membership changes, and credential modifications by parsing
|
||||
Windows Security Event Logs for key event IDs.
|
||||
"""
|
||||
# For authorized threat hunting and blue team use only
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import xml.etree.ElementTree as ET
|
||||
from collections import Counter, defaultdict
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
try:
|
||||
import Evtx.Evtx as evtx
|
||||
except ImportError:
|
||||
evtx = None
|
||||
|
||||
NS = "{http://schemas.microsoft.com/win/2004/08/events/event}"
|
||||
|
||||
T1098_EVENT_IDS = {
|
||||
"4738": "User account changed",
|
||||
"4728": "Member added to global security group",
|
||||
"4732": "Member added to local security group",
|
||||
"4756": "Member added to universal security group",
|
||||
"4729": "Member removed from global security group",
|
||||
"4733": "Member removed from local security group",
|
||||
"4670": "Permissions on object changed",
|
||||
"5136": "Directory service object modified",
|
||||
"4724": "Password reset attempted",
|
||||
"4723": "Password change attempted",
|
||||
"4781": "Account name changed",
|
||||
}
|
||||
|
||||
PRIVILEGED_GROUPS = {
|
||||
"domain admins", "enterprise admins", "schema admins",
|
||||
"administrators", "backup operators", "server operators",
|
||||
"account operators", "print operators", "dns admins",
|
||||
"group policy creator owners", "remote desktop users",
|
||||
}
|
||||
|
||||
SENSITIVE_ATTRIBUTES = {
|
||||
"sidhistory", "serviceprincipalname", "msds-allowedtodelegateto",
|
||||
"msds-allowedtoactonbehalfofotheridentity", "admincount",
|
||||
"useraccountcontrol", "primarygroupid",
|
||||
}
|
||||
|
||||
|
||||
def _parse_event(xml_str):
|
||||
"""Extract event ID, timestamp, and data fields from event XML."""
|
||||
root = ET.fromstring(xml_str)
|
||||
sys_node = root.find(f"{NS}System")
|
||||
event_id = sys_node.find(f"{NS}EventID").text if sys_node is not None else None
|
||||
tc = sys_node.find(f"{NS}TimeCreated") if sys_node is not None else None
|
||||
timestamp = tc.get("SystemTime", "") if tc is not None else ""
|
||||
data = {}
|
||||
for d in root.iter(f"{NS}Data"):
|
||||
name = d.get("Name", "")
|
||||
data[name] = d.text or ""
|
||||
return event_id, timestamp, data
|
||||
|
||||
|
||||
class T1098HuntingAgent:
|
||||
"""Hunts for T1098 account manipulation in Windows Event Logs."""
|
||||
|
||||
def __init__(self, evtx_path, output_dir="./t1098_hunt"):
|
||||
self.evtx_path = evtx_path
|
||||
self.output_dir = Path(output_dir)
|
||||
self.output_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.events = []
|
||||
self.findings = []
|
||||
|
||||
def parse_events(self):
|
||||
"""Parse EVTX for T1098-relevant event IDs."""
|
||||
if evtx is None:
|
||||
raise RuntimeError("python-evtx required: pip install python-evtx")
|
||||
with evtx.Evtx(self.evtx_path) as log:
|
||||
for record in log.records():
|
||||
try:
|
||||
xml_str = record.xml()
|
||||
except Exception:
|
||||
continue
|
||||
event_id, ts, data = _parse_event(xml_str)
|
||||
if event_id in T1098_EVENT_IDS:
|
||||
self.events.append({
|
||||
"event_id": event_id,
|
||||
"description": T1098_EVENT_IDS[event_id],
|
||||
"timestamp": ts,
|
||||
"subject_user": data.get("SubjectUserName", ""),
|
||||
"subject_domain": data.get("SubjectDomainName", ""),
|
||||
"target_user": data.get("TargetUserName", data.get("MemberName", "")),
|
||||
"target_domain": data.get("TargetDomainName", ""),
|
||||
"group_name": data.get("TargetUserName", ""),
|
||||
"member_sid": data.get("MemberSid", ""),
|
||||
"attribute_name": data.get("AttributeLDAPDisplayName", ""),
|
||||
"attribute_value": data.get("AttributeValue", "")[:200],
|
||||
})
|
||||
|
||||
def detect_privileged_group_changes(self):
|
||||
"""Detect additions to privileged security groups."""
|
||||
group_add_ids = {"4728", "4732", "4756"}
|
||||
alerts = []
|
||||
for event in self.events:
|
||||
if event["event_id"] in group_add_ids:
|
||||
group = event["group_name"].lower()
|
||||
if any(pg in group for pg in PRIVILEGED_GROUPS):
|
||||
alerts.append(event)
|
||||
self.findings.append({
|
||||
"severity": "critical",
|
||||
"type": "Privileged Group Addition",
|
||||
"detail": f"{event['subject_user']} added {event['target_user']} "
|
||||
f"to '{event['group_name']}' at {event['timestamp']}",
|
||||
"mitre": "T1098.001",
|
||||
})
|
||||
return alerts
|
||||
|
||||
def detect_sid_history_injection(self):
|
||||
"""Detect SID History modifications via directory service changes."""
|
||||
alerts = []
|
||||
for event in self.events:
|
||||
if event["event_id"] == "5136":
|
||||
attr = event["attribute_name"].lower()
|
||||
if attr == "sidhistory":
|
||||
alerts.append(event)
|
||||
self.findings.append({
|
||||
"severity": "critical",
|
||||
"type": "SID History Injection",
|
||||
"detail": f"SID History modified on {event['target_user']} "
|
||||
f"by {event['subject_user']} at {event['timestamp']}",
|
||||
"mitre": "T1134.005",
|
||||
})
|
||||
return alerts
|
||||
|
||||
def detect_sensitive_attribute_changes(self):
|
||||
"""Detect changes to sensitive AD attributes."""
|
||||
alerts = []
|
||||
for event in self.events:
|
||||
if event["event_id"] == "5136":
|
||||
attr = event["attribute_name"].lower()
|
||||
if attr in SENSITIVE_ATTRIBUTES:
|
||||
alerts.append(event)
|
||||
self.findings.append({
|
||||
"severity": "high",
|
||||
"type": "Sensitive Attribute Modified",
|
||||
"detail": f"Attribute '{event['attribute_name']}' changed on "
|
||||
f"{event['target_user']} by {event['subject_user']}",
|
||||
"mitre": "T1098",
|
||||
})
|
||||
return alerts
|
||||
|
||||
def detect_shadow_admin(self):
|
||||
"""Detect potential shadow admin creation patterns."""
|
||||
alerts = []
|
||||
admin_adds = [e for e in self.events
|
||||
if e["event_id"] in ("4728", "4732", "4756") and
|
||||
any(pg in e["group_name"].lower() for pg in PRIVILEGED_GROUPS)]
|
||||
account_changes = [e for e in self.events if e["event_id"] == "4738"]
|
||||
|
||||
changed_accounts = {e["target_user"].lower() for e in account_changes}
|
||||
for add_event in admin_adds:
|
||||
target = add_event["target_user"].lower()
|
||||
if target in changed_accounts:
|
||||
alerts.append(add_event)
|
||||
self.findings.append({
|
||||
"severity": "critical",
|
||||
"type": "Shadow Admin Indicator",
|
||||
"detail": f"Account '{add_event['target_user']}' modified and then "
|
||||
f"added to '{add_event['group_name']}'",
|
||||
"mitre": "T1098",
|
||||
})
|
||||
return alerts
|
||||
|
||||
def generate_report(self):
|
||||
self.parse_events()
|
||||
priv_group = self.detect_privileged_group_changes()
|
||||
sid_history = self.detect_sid_history_injection()
|
||||
sensitive = self.detect_sensitive_attribute_changes()
|
||||
shadow = self.detect_shadow_admin()
|
||||
|
||||
event_summary = Counter(e["event_id"] for e in self.events)
|
||||
actor_summary = Counter(e["subject_user"] for e in self.events if e["subject_user"])
|
||||
|
||||
report = {
|
||||
"report_date": datetime.utcnow().isoformat(),
|
||||
"evtx_file": str(self.evtx_path),
|
||||
"mitre_technique": "T1098 - Account Manipulation",
|
||||
"total_t1098_events": len(self.events),
|
||||
"event_id_summary": dict(event_summary),
|
||||
"top_actors": actor_summary.most_common(10),
|
||||
"privileged_group_changes": len(priv_group),
|
||||
"sid_history_injections": len(sid_history),
|
||||
"sensitive_attr_changes": len(sensitive),
|
||||
"shadow_admin_indicators": len(shadow),
|
||||
"findings": self.findings,
|
||||
"total_findings": len(self.findings),
|
||||
}
|
||||
out = self.output_dir / "t1098_hunt_report.json"
|
||||
with open(out, "w") as f:
|
||||
json.dump(report, f, indent=2, default=str)
|
||||
print(json.dumps(report, indent=2, default=str))
|
||||
return report
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Hunt for MITRE T1098 account manipulation in Windows Event Logs"
|
||||
)
|
||||
parser.add_argument("evtx_file", help="Path to Security.evtx log file")
|
||||
parser.add_argument("--output-dir", default="./t1098_hunt",
|
||||
help="Output directory for hunt report")
|
||||
args = parser.parse_args()
|
||||
|
||||
os.makedirs(args.output_dir, exist_ok=True)
|
||||
agent = T1098HuntingAgent(args.evtx_file, output_dir=args.output_dir)
|
||||
agent.generate_report()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user