mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-29 07:30:59 +03:00
feat: add 5 cybersecurity skills - CloudTrail anomalies, SSL/TLS assessment, Wazuh detection, Prefetch analysis, WMI lateral movement
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: implementing-endpoint-detection-with-wazuh
|
||||
description: Deploy and configure Wazuh SIEM/XDR for endpoint detection including agent management, custom decoder and rule XML creation, alert querying via the Wazuh REST API, and automated response actions.
|
||||
domain: cybersecurity
|
||||
subdomain: security-operations
|
||||
tags: [siem, xdr, wazuh, endpoint-detection, custom-rules, incident-response]
|
||||
version: "1.0"
|
||||
author: mahipal
|
||||
license: MIT
|
||||
---
|
||||
# Implementing Endpoint Detection with Wazuh
|
||||
|
||||
## Overview
|
||||
|
||||
Wazuh is an open-source SIEM and XDR platform for endpoint monitoring, threat detection, and compliance. This skill covers managing agents via the Wazuh REST API, creating custom decoders and rules in XML for organization-specific detections, querying alerts, and testing rule logic using the logtest endpoint.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Wazuh Manager 4.x deployed with API enabled
|
||||
- Python 3.9+ with `requests` library
|
||||
- API credentials (username/password for JWT authentication)
|
||||
- Understanding of Wazuh decoder and rule XML syntax
|
||||
|
||||
## Steps
|
||||
|
||||
### Step 1: Authenticate to Wazuh API
|
||||
Obtain JWT token via POST to /security/user/authenticate.
|
||||
|
||||
### Step 2: List and Monitor Agents
|
||||
Query agent status, versions, and last keep-alive via /agents endpoint.
|
||||
|
||||
### Step 3: Query Security Alerts
|
||||
Search alerts by rule ID, severity, agent, or time range.
|
||||
|
||||
### Step 4: Test Custom Rules with Logtest
|
||||
Use the /logtest endpoint to validate decoder and rule logic against sample log lines.
|
||||
|
||||
## Expected Output
|
||||
|
||||
JSON report with agent inventory, alert statistics, rule coverage, and logtest validation results.
|
||||
@@ -0,0 +1,72 @@
|
||||
# API Reference: Implementing Endpoint Detection with Wazuh
|
||||
|
||||
## Wazuh REST API Endpoints
|
||||
|
||||
| Endpoint | Method | Purpose |
|
||||
|----------|--------|---------|
|
||||
| /security/user/authenticate | POST | Get JWT token (Basic Auth) |
|
||||
| /agents | GET | List agents with status |
|
||||
| /agents/summary/status | GET | Agent status summary |
|
||||
| /alerts | GET | Query security alerts |
|
||||
| /rules | GET | List detection rules |
|
||||
| /logtest | PUT | Test log against decoders/rules |
|
||||
| /manager/configuration | GET | Manager configuration |
|
||||
| /agents/{id}/restart | PUT | Restart specific agent |
|
||||
|
||||
## Authentication
|
||||
|
||||
```python
|
||||
import requests
|
||||
from requests.auth import HTTPBasicAuth
|
||||
|
||||
resp = requests.post(
|
||||
"https://wazuh:55000/security/user/authenticate",
|
||||
auth=HTTPBasicAuth("wazuh-wui", "password"),
|
||||
verify=False,
|
||||
)
|
||||
token = resp.json()["data"]["token"]
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
```
|
||||
|
||||
## Custom Rule XML Syntax
|
||||
|
||||
```xml
|
||||
<group name="custom_rules,">
|
||||
<rule id="100001" level="12">
|
||||
<if_sid>5716</if_sid>
|
||||
<srcip>!192.168.1.0/24</srcip>
|
||||
<description>SSH login from external IP</description>
|
||||
<mitre><id>T1078</id></mitre>
|
||||
</rule>
|
||||
</group>
|
||||
```
|
||||
|
||||
Location: `/var/ossec/etc/rules/local_rules.xml`
|
||||
|
||||
## Custom Decoder XML
|
||||
|
||||
```xml
|
||||
<decoder name="custom_app">
|
||||
<program_name>myapp</program_name>
|
||||
<regex>^(\S+) (\S+) (\S+)</regex>
|
||||
<order>srcip,user,action</order>
|
||||
</decoder>
|
||||
```
|
||||
|
||||
Location: `/var/ossec/etc/decoders/local_decoder.xml`
|
||||
|
||||
## Alert Query Parameters
|
||||
|
||||
| Parameter | Example | Description |
|
||||
|-----------|---------|-------------|
|
||||
| limit | 20 | Max results |
|
||||
| sort | -timestamp | Sort descending |
|
||||
| q | rule.level>=10 | Filter by level |
|
||||
| search | brute force | Text search |
|
||||
| select | rule.id,agent.name | Field selection |
|
||||
|
||||
## References
|
||||
|
||||
- Wazuh API Docs: https://documentation.wazuh.com/current/user-manual/api/
|
||||
- Wazuh Rules Syntax: https://documentation.wazuh.com/current/user-manual/ruleset/ruleset-xml-syntax/rules.html
|
||||
- Wazuh Custom Rules: https://documentation.wazuh.com/current/user-manual/ruleset/rules/custom.html
|
||||
@@ -0,0 +1,192 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for implementing endpoint detection with Wazuh.
|
||||
|
||||
Manages Wazuh agents, queries alerts, tests custom decoder/rule
|
||||
logic via logtest, and audits endpoint coverage using the
|
||||
Wazuh REST API.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
try:
|
||||
import requests
|
||||
from requests.auth import HTTPBasicAuth
|
||||
except ImportError:
|
||||
requests = None
|
||||
|
||||
|
||||
class WazuhDetectionAgent:
|
||||
"""Manages Wazuh endpoint detection via its REST API."""
|
||||
|
||||
def __init__(self, wazuh_url, username, password,
|
||||
output_dir="./wazuh_detection"):
|
||||
self.base_url = wazuh_url.rstrip("/")
|
||||
self.output_dir = Path(output_dir)
|
||||
self.output_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.findings = []
|
||||
self.token = self._authenticate(username, password)
|
||||
|
||||
def _authenticate(self, username, password):
|
||||
"""Authenticate and obtain JWT token."""
|
||||
if not requests:
|
||||
return None
|
||||
try:
|
||||
resp = requests.post(
|
||||
f"{self.base_url}/security/user/authenticate",
|
||||
auth=HTTPBasicAuth(username, password),
|
||||
verify=False, timeout=10,
|
||||
)
|
||||
if resp.status_code == 200:
|
||||
return resp.json().get("data", {}).get("token")
|
||||
except requests.RequestException:
|
||||
pass
|
||||
return None
|
||||
|
||||
def _api(self, method, path, params=None, data=None):
|
||||
if not requests or not self.token:
|
||||
return None
|
||||
try:
|
||||
resp = requests.request(
|
||||
method, f"{self.base_url}{path}",
|
||||
headers={"Authorization": f"Bearer {self.token}"},
|
||||
params=params, json=data, verify=False, timeout=15,
|
||||
)
|
||||
return resp.json() if resp.status_code == 200 else None
|
||||
except requests.RequestException:
|
||||
return None
|
||||
|
||||
def list_agents(self):
|
||||
"""List all registered Wazuh agents with status."""
|
||||
data = self._api("GET", "/agents", params={"limit": 500, "select": "id,name,status,os.name,os.version,version,lastKeepAlive,ip"})
|
||||
if not data:
|
||||
return []
|
||||
agents = data.get("data", {}).get("affected_items", [])
|
||||
disconnected = [a for a in agents if a.get("status") == "disconnected"]
|
||||
if disconnected:
|
||||
self.findings.append({
|
||||
"severity": "medium", "type": "Disconnected Agents",
|
||||
"detail": f"{len(disconnected)} agents disconnected",
|
||||
})
|
||||
return agents
|
||||
|
||||
def get_agent_summary(self):
|
||||
"""Get agent status summary counts."""
|
||||
data = self._api("GET", "/agents/summary/status")
|
||||
if data:
|
||||
return data.get("data", {})
|
||||
return {}
|
||||
|
||||
def query_alerts(self, limit=20, level_min=10):
|
||||
"""Query recent high-severity alerts."""
|
||||
data = self._api("GET", "/alerts", params={
|
||||
"limit": limit, "sort": "-timestamp",
|
||||
"q": f"rule.level>={level_min}",
|
||||
})
|
||||
if not data:
|
||||
return []
|
||||
alerts = data.get("data", {}).get("affected_items", [])
|
||||
return [{
|
||||
"id": a.get("id"),
|
||||
"timestamp": a.get("timestamp"),
|
||||
"rule_id": a.get("rule", {}).get("id"),
|
||||
"rule_description": a.get("rule", {}).get("description"),
|
||||
"rule_level": a.get("rule", {}).get("level"),
|
||||
"agent_name": a.get("agent", {}).get("name"),
|
||||
"agent_id": a.get("agent", {}).get("id"),
|
||||
} for a in alerts]
|
||||
|
||||
def get_rules_summary(self):
|
||||
"""Get summary of active detection rules."""
|
||||
data = self._api("GET", "/rules", params={"limit": 500, "select": "id,description,level,groups"})
|
||||
if not data:
|
||||
return {"total": 0}
|
||||
rules = data.get("data", {}).get("affected_items", [])
|
||||
total = data.get("data", {}).get("total_affected_items", len(rules))
|
||||
levels = {}
|
||||
for r in rules:
|
||||
lvl = str(r.get("level", 0))
|
||||
levels[lvl] = levels.get(lvl, 0) + 1
|
||||
return {"total_rules": total, "by_level": levels}
|
||||
|
||||
def test_logtest(self, log_line, log_format="syslog"):
|
||||
"""Test a log line against Wazuh decoders and rules."""
|
||||
data = self._api("PUT", "/logtest", data={
|
||||
"log_format": log_format,
|
||||
"location": "test",
|
||||
"event": log_line,
|
||||
})
|
||||
if not data:
|
||||
return {"error": "Logtest failed"}
|
||||
result = data.get("data", {})
|
||||
return {
|
||||
"decoder": result.get("decoder", {}).get("name"),
|
||||
"rule_id": result.get("rule", {}).get("id"),
|
||||
"rule_description": result.get("rule", {}).get("description"),
|
||||
"rule_level": result.get("rule", {}).get("level"),
|
||||
"output": result.get("output"),
|
||||
}
|
||||
|
||||
def check_vulnerability_detection(self):
|
||||
"""Check if vulnerability detection module is enabled."""
|
||||
data = self._api("GET", "/manager/configuration",
|
||||
params={"section": "vulnerability-detector"})
|
||||
if data:
|
||||
config = data.get("data", {}).get("affected_items", [])
|
||||
if config:
|
||||
enabled = config[0].get("vulnerability-detector", {}).get("enabled", "no")
|
||||
if enabled != "yes":
|
||||
self.findings.append({
|
||||
"severity": "medium", "type": "Vuln Detection Disabled",
|
||||
"detail": "Vulnerability detection module is not enabled",
|
||||
})
|
||||
return {"enabled": enabled == "yes"}
|
||||
return {"enabled": False}
|
||||
|
||||
def generate_report(self):
|
||||
agents = self.list_agents()
|
||||
summary = self.get_agent_summary()
|
||||
alerts = self.query_alerts()
|
||||
rules = self.get_rules_summary()
|
||||
vuln_det = self.check_vulnerability_detection()
|
||||
|
||||
report = {
|
||||
"report_date": datetime.utcnow().isoformat(),
|
||||
"wazuh_url": self.base_url,
|
||||
"agent_summary": summary,
|
||||
"agents": agents[:50],
|
||||
"total_agents": len(agents),
|
||||
"recent_critical_alerts": alerts,
|
||||
"rules_summary": rules,
|
||||
"vulnerability_detection": vuln_det,
|
||||
"findings": self.findings,
|
||||
"total_findings": len(self.findings),
|
||||
}
|
||||
out = self.output_dir / "wazuh_detection_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="Manage Wazuh endpoint detection and query alerts"
|
||||
)
|
||||
parser.add_argument("wazuh_url", help="Wazuh API URL (e.g. https://wazuh:55000)")
|
||||
parser.add_argument("--username", default="wazuh-wui", help="API username")
|
||||
parser.add_argument("--password", required=True, help="API password")
|
||||
parser.add_argument("--output-dir", default="./wazuh_detection")
|
||||
args = parser.parse_args()
|
||||
|
||||
os.makedirs(args.output_dir, exist_ok=True)
|
||||
agent = WazuhDetectionAgent(args.wazuh_url, args.username, args.password,
|
||||
output_dir=args.output_dir)
|
||||
agent.generate_report()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user