mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-08-28 04:09:40 +03:00
Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills
Complete skill folder anatomy across all cybersecurity skills: - scripts/agent.py: 80-150 line Python agents using real libraries (impacket, boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.) - references/api-reference.md: real API documentation with method signatures - LICENSE: MIT license for all skill folders
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Anthropic Agent Skills Contributors
|
||||
|
||||
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,53 @@
|
||||
# API Reference: Log Analysis for Forensic Investigation
|
||||
|
||||
## python-evtx Library
|
||||
|
||||
```python
|
||||
import Evtx.Evtx as evtx
|
||||
with evtx.Evtx("Security.evtx") as log:
|
||||
for record in log.records():
|
||||
print(record.xml())
|
||||
```
|
||||
|
||||
## Key Windows Security Event IDs
|
||||
|
||||
| Event ID | Description | Forensic Value |
|
||||
|----------|-------------|----------------|
|
||||
| 4624 | Successful logon | Track authentication patterns |
|
||||
| 4625 | Failed logon | Brute force detection |
|
||||
| 4648 | Explicit credentials | Lateral movement indicator |
|
||||
| 4688 | Process creation | Command execution timeline |
|
||||
| 4697 | Service installed | Persistence mechanism |
|
||||
| 4698 | Scheduled task created | Persistence mechanism |
|
||||
| 1102 | Audit log cleared | Anti-forensics detection |
|
||||
|
||||
## Syslog Parsing
|
||||
|
||||
| Log File | Content | Key Events |
|
||||
|----------|---------|------------|
|
||||
| `/var/log/auth.log` | SSH, sudo, su | Failed/successful SSH, privilege escalation |
|
||||
| `/var/log/syslog` | General system | Service events, kernel messages |
|
||||
| `/var/log/audit/audit.log` | auditd | File access, command execution |
|
||||
|
||||
## Python Libraries
|
||||
|
||||
| Library | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| `python-evtx` | >=0.7 | Windows EVTX event log parsing |
|
||||
| `csv` | stdlib | Log data export and normalization |
|
||||
| `re` | stdlib | Syslog and access log parsing |
|
||||
|
||||
## CLI Tools
|
||||
|
||||
| Tool | Command | Description |
|
||||
|------|---------|-------------|
|
||||
| evtxexport | `evtxexport Security.evtx` | Export EVTX to text |
|
||||
| Chainsaw | `chainsaw hunt <evtx_dir> -s sigma/` | Sigma-based EVTX analysis |
|
||||
| Hayabusa | `hayabusa csv-timeline -d <evtx_dir>` | Fast EVTX timeline generator |
|
||||
|
||||
## References
|
||||
|
||||
- python-evtx: https://github.com/williballenthin/python-evtx
|
||||
- Chainsaw: https://github.com/WithSecureLabs/chainsaw
|
||||
- Hayabusa: https://github.com/Yamato-Security/hayabusa
|
||||
- Sigma rules: https://github.com/SigmaHQ/sigma
|
||||
@@ -0,0 +1,220 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for performing log analysis for forensic investigation.
|
||||
|
||||
Parses Windows EVTX, Linux syslog, and web access logs to build
|
||||
correlated forensic timelines for incident investigations.
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import csv
|
||||
import re
|
||||
from datetime import datetime
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class ForensicLogAnalyzer:
|
||||
"""Analyzes and correlates logs for forensic investigations."""
|
||||
|
||||
def __init__(self, case_id, output_dir):
|
||||
self.case_id = case_id
|
||||
self.output_dir = Path(output_dir)
|
||||
self.output_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.events = []
|
||||
|
||||
def parse_evtx(self, evtx_path):
|
||||
"""Parse Windows EVTX event log files."""
|
||||
try:
|
||||
import Evtx.Evtx as evtx
|
||||
import xml.etree.ElementTree as ET
|
||||
except ImportError:
|
||||
print("Install python-evtx: pip install python-evtx")
|
||||
return []
|
||||
|
||||
records = []
|
||||
target_ids = {"4624", "4625", "4648", "4672", "4688", "4697", "4698", "1102"}
|
||||
|
||||
with evtx.Evtx(evtx_path) as log:
|
||||
for record in log.records():
|
||||
try:
|
||||
root = ET.fromstring(record.xml())
|
||||
ns = {"ns": "http://schemas.microsoft.com/win/2004/08/events/event"}
|
||||
event_id = root.find(".//ns:EventID", ns).text
|
||||
if event_id not in target_ids:
|
||||
continue
|
||||
time_elem = root.find(".//ns:TimeCreated", ns)
|
||||
timestamp = time_elem.get("SystemTime") if time_elem is not None else ""
|
||||
data_fields = {}
|
||||
for data in root.findall(".//ns:Data", ns):
|
||||
name = data.get("Name", "")
|
||||
data_fields[name] = data.text or ""
|
||||
|
||||
event = {
|
||||
"timestamp": timestamp,
|
||||
"source": "Windows-Security",
|
||||
"event_id": event_id,
|
||||
"computer": data_fields.get("Computer", ""),
|
||||
"user": data_fields.get("TargetUserName", ""),
|
||||
"details": data_fields,
|
||||
}
|
||||
records.append(event)
|
||||
self.events.append(event)
|
||||
except Exception:
|
||||
continue
|
||||
return records
|
||||
|
||||
def parse_syslog(self, log_path):
|
||||
"""Parse Linux syslog/auth.log files."""
|
||||
records = []
|
||||
syslog_re = re.compile(
|
||||
r"^(\w{3}\s+\d+\s+\d{2}:\d{2}:\d{2})\s+(\S+)\s+(\S+?)(?:\[\d+\])?:\s+(.*)"
|
||||
)
|
||||
with open(log_path, "r", errors="ignore") as f:
|
||||
for line in f:
|
||||
match = syslog_re.match(line.strip())
|
||||
if match:
|
||||
event = {
|
||||
"timestamp": match.group(1),
|
||||
"source": "Linux-Syslog",
|
||||
"host": match.group(2),
|
||||
"service": match.group(3),
|
||||
"message": match.group(4),
|
||||
}
|
||||
records.append(event)
|
||||
self.events.append(event)
|
||||
return records
|
||||
|
||||
def parse_web_access_log(self, log_path):
|
||||
"""Parse Apache/Nginx combined access log format."""
|
||||
records = []
|
||||
access_re = re.compile(
|
||||
r'^(\S+)\s+\S+\s+\S+\s+\[([^\]]+)\]\s+"([^"]+)"\s+(\d{3})\s+(\d+)'
|
||||
)
|
||||
with open(log_path, "r", errors="ignore") as f:
|
||||
for line in f:
|
||||
match = access_re.match(line.strip())
|
||||
if match:
|
||||
event = {
|
||||
"timestamp": match.group(2),
|
||||
"source": "Web-Access",
|
||||
"client_ip": match.group(1),
|
||||
"request": match.group(3),
|
||||
"status": match.group(4),
|
||||
"size": match.group(5),
|
||||
}
|
||||
records.append(event)
|
||||
self.events.append(event)
|
||||
return records
|
||||
|
||||
def detect_attack_patterns(self, web_events):
|
||||
"""Detect common web attack patterns in access logs."""
|
||||
patterns = {
|
||||
"sql_injection": re.compile(r"(union.*select|or\s+1\s*=\s*1|drop\s+table)", re.I),
|
||||
"xss": re.compile(r"(<script|javascript:|onerror=|onload=)", re.I),
|
||||
"path_traversal": re.compile(r"(\.\./|\.\.\\|/etc/passwd|/etc/shadow)", re.I),
|
||||
"command_injection": re.compile(r"(;\s*(ls|cat|wget|curl|nc)\b|`|\$\()", re.I),
|
||||
}
|
||||
findings = defaultdict(list)
|
||||
for event in web_events:
|
||||
request = event.get("request", "")
|
||||
for attack_type, pattern in patterns.items():
|
||||
if pattern.search(request):
|
||||
findings[attack_type].append({
|
||||
"timestamp": event["timestamp"],
|
||||
"client_ip": event.get("client_ip", ""),
|
||||
"request": request[:200],
|
||||
"status": event.get("status", ""),
|
||||
})
|
||||
return dict(findings)
|
||||
|
||||
def detect_brute_force(self):
|
||||
"""Detect brute force patterns in authentication events."""
|
||||
failed_by_source = defaultdict(lambda: {"count": 0, "users": set()})
|
||||
for event in self.events:
|
||||
if event.get("event_id") == "4625":
|
||||
src = event.get("details", {}).get("IpAddress", "unknown")
|
||||
user = event.get("user", "unknown")
|
||||
failed_by_source[src]["count"] += 1
|
||||
failed_by_source[src]["users"].add(user)
|
||||
|
||||
return [
|
||||
{"source_ip": src, "failed_attempts": data["count"],
|
||||
"targeted_users": sorted(data["users"])}
|
||||
for src, data in failed_by_source.items()
|
||||
if data["count"] > 5
|
||||
]
|
||||
|
||||
def detect_log_clearing(self):
|
||||
"""Detect audit log clearing events (anti-forensics)."""
|
||||
return [
|
||||
event for event in self.events
|
||||
if event.get("event_id") == "1102"
|
||||
]
|
||||
|
||||
def build_correlated_timeline(self):
|
||||
"""Build a unified correlated timeline from all log sources."""
|
||||
sorted_events = sorted(self.events, key=lambda e: e.get("timestamp", ""))
|
||||
return sorted_events
|
||||
|
||||
def generate_forensic_report(self):
|
||||
"""Generate a comprehensive forensic log analysis report."""
|
||||
timeline = self.build_correlated_timeline()
|
||||
brute_force = self.detect_brute_force()
|
||||
log_clearing = self.detect_log_clearing()
|
||||
|
||||
web_events = [e for e in self.events if e.get("source") == "Web-Access"]
|
||||
attack_patterns = self.detect_attack_patterns(web_events)
|
||||
|
||||
source_counts = defaultdict(int)
|
||||
for event in self.events:
|
||||
source_counts[event.get("source", "unknown")] += 1
|
||||
|
||||
report = {
|
||||
"case_id": self.case_id,
|
||||
"report_date": datetime.utcnow().isoformat(),
|
||||
"total_events": len(self.events),
|
||||
"source_breakdown": dict(source_counts),
|
||||
"brute_force_detections": brute_force,
|
||||
"log_clearing_events": log_clearing,
|
||||
"web_attack_patterns": {k: len(v) for k, v in attack_patterns.items()},
|
||||
"timeline_entries": len(timeline),
|
||||
}
|
||||
|
||||
report_path = self.output_dir / f"{self.case_id}_log_analysis.json"
|
||||
with open(report_path, "w") as f:
|
||||
json.dump(report, f, indent=2, default=list)
|
||||
|
||||
timeline_path = self.output_dir / f"{self.case_id}_timeline.csv"
|
||||
if timeline:
|
||||
with open(timeline_path, "w", newline="") as f:
|
||||
writer = csv.DictWriter(f, fieldnames=list(timeline[0].keys()))
|
||||
writer.writeheader()
|
||||
for event in timeline[:10000]:
|
||||
writer.writerow({k: str(v)[:200] for k, v in event.items()})
|
||||
|
||||
print(json.dumps(report, indent=2, default=list))
|
||||
return report
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 3:
|
||||
print("Usage: agent.py <case_id> <output_dir> [evtx_file] [syslog_file] [access_log]")
|
||||
sys.exit(1)
|
||||
|
||||
case_id = sys.argv[1]
|
||||
output_dir = sys.argv[2]
|
||||
analyzer = ForensicLogAnalyzer(case_id, output_dir)
|
||||
|
||||
if len(sys.argv) > 3:
|
||||
analyzer.parse_evtx(sys.argv[3])
|
||||
if len(sys.argv) > 4:
|
||||
analyzer.parse_syslog(sys.argv[4])
|
||||
if len(sys.argv) > 5:
|
||||
analyzer.parse_web_access_log(sys.argv[5])
|
||||
|
||||
analyzer.generate_forensic_report()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user