external/anthropic-cybersecurity-skills/skills/performing-linux-log-forensics-investigation/SKILL.md
Perform forensic investigation of Linux system logs including syslog, auth.log, systemd journal, kern.log, and application logs to reconstruct user activity, detect unauthorized access, and establish event timelines on compromised Linux systems.
npx skillsauth add seikaikyo/dash-skills performing-linux-log-forensics-investigationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Linux systems maintain extensive logs that serve as primary evidence sources in forensic investigations. Unlike Windows Event Logs, Linux logs are typically plain-text files stored in /var/log/ and binary journal files managed by systemd-journald. Key forensic logs include auth.log (authentication events, sudo usage, SSH sessions), syslog (system-wide messages), kern.log (kernel events), and application-specific logs. The Linux Audit framework (auditd) provides detailed security event logging comparable to Windows Security Event Logs. Forensic analysis of these logs enables investigators to reconstruct user sessions, identify unauthorized access, detect privilege escalation, trace lateral movement, and establish comprehensive event timelines.
| Log File | Path | Contents |
|----------|------|----------|
| auth.log / secure | /var/log/auth.log (Debian) or /var/log/secure (RHEL) | Authentication, sudo, SSH, PAM |
| syslog / messages | /var/log/syslog (Debian) or /var/log/messages (RHEL) | General system messages |
| kern.log | /var/log/kern.log | Kernel messages, USB events, driver loads |
| lastlog | /var/log/lastlog | Last login per user (binary) |
| wtmp | /var/log/wtmp | Login/logout records (binary, read with last) |
| btmp | /var/log/btmp | Failed login attempts (binary, read with lastb) |
| faillog | /var/log/faillog | Failed login counter (binary) |
| cron.log | /var/log/cron or /var/log/syslog | Scheduled task execution |
| audit.log | /var/log/audit/audit.log | Linux Audit Framework events |
| journal | /var/log/journal/ or /run/log/journal/ | systemd binary journal |
| dpkg.log | /var/log/dpkg.log | Package installation/removal (Debian) |
| yum.log | /var/log/yum.log | Package installation/removal (RHEL) |
# Find all successful SSH logins
grep "Accepted" /var/log/auth.log
# Find failed SSH login attempts
grep "Failed password" /var/log/auth.log
# Extract unique source IPs from failed logins
grep "Failed password" /var/log/auth.log | grep -oP '\d+\.\d+\.\d+\.\d+' | sort -u
# Find sudo command execution
grep "sudo:" /var/log/auth.log | grep "COMMAND"
# Detect brute force patterns (>10 failures from same IP)
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20
# Find account creation events
grep "useradd\|adduser" /var/log/auth.log
# Detect SSH key authentication
grep "Accepted publickey" /var/log/auth.log
# Export journal in JSON format for forensic processing
journalctl --output=json --no-pager > journal_export.json
# Filter by time range
journalctl --since "2025-02-01" --until "2025-02-15" --output=json > timerange.json
# Filter by unit/service
journalctl -u sshd --output=json > sshd_journal.json
# Show kernel messages (USB events, module loads)
journalctl -k --output=json > kernel_journal.json
# Filter by priority (0=emerg to 7=debug)
journalctl -p err --output=json > errors.json
# Boot-specific logs
journalctl -b 0 --output=json > current_boot.json
journalctl --list-boots # List all recorded boot sessions
# Search audit log for specific event types
ausearch -m USER_AUTH --start today
# Search for file access events
ausearch -f /etc/shadow
# Search for process execution
ausearch -m EXECVE --start "02/01/2025" --end "02/28/2025"
# Generate report of login events
aureport --login --start "02/01/2025"
# Generate summary of failed authentications
aureport --auth --failed
# Search for specific user activity
ausearch -ua 1001 # By UID
ausearch -ua username # By username
# Check system-wide crontab
cat /etc/crontab
# Check user crontabs
ls -la /var/spool/cron/crontabs/
# Review cron execution logs
grep "CRON" /var/log/syslog
# Check for at/batch jobs
ls -la /var/spool/at/
atq
import re
import json
import sys
import os
from datetime import datetime
from collections import defaultdict
class LinuxLogForensicAnalyzer:
"""Analyze Linux system logs for forensic investigation."""
def __init__(self, log_dir: str, output_dir: str):
self.log_dir = log_dir
self.output_dir = output_dir
os.makedirs(output_dir, exist_ok=True)
def parse_auth_log(self, auth_log_path: str) -> dict:
"""Parse auth.log for authentication events."""
events = {
"successful_logins": [],
"failed_logins": [],
"sudo_commands": [],
"account_changes": [],
"ssh_sessions": []
}
ssh_accepted = re.compile(
r'(\w+\s+\d+\s+[\d:]+)\s+(\S+)\s+sshd\[\d+\]:\s+Accepted\s+(\S+)\s+for\s+(\S+)\s+from\s+([\d.]+)'
)
ssh_failed = re.compile(
r'(\w+\s+\d+\s+[\d:]+)\s+(\S+)\s+sshd\[\d+\]:\s+Failed\s+password\s+for\s+(\S*)\s+from\s+([\d.]+)'
)
sudo_cmd = re.compile(
r'(\w+\s+\d+\s+[\d:]+)\s+(\S+)\s+sudo:\s+(\S+)\s+:.*COMMAND=(.*)'
)
useradd = re.compile(
r'(\w+\s+\d+\s+[\d:]+)\s+(\S+)\s+useradd\[\d+\]:\s+new user: name=(\S+)'
)
with open(auth_log_path, "r", errors="replace") as f:
for line in f:
m = ssh_accepted.search(line)
if m:
events["successful_logins"].append({
"timestamp": m.group(1), "host": m.group(2),
"method": m.group(3), "user": m.group(4), "source_ip": m.group(5)
})
continue
m = ssh_failed.search(line)
if m:
events["failed_logins"].append({
"timestamp": m.group(1), "host": m.group(2),
"user": m.group(3), "source_ip": m.group(4)
})
continue
m = sudo_cmd.search(line)
if m:
events["sudo_commands"].append({
"timestamp": m.group(1), "host": m.group(2),
"user": m.group(3), "command": m.group(4).strip()
})
continue
m = useradd.search(line)
if m:
events["account_changes"].append({
"timestamp": m.group(1), "host": m.group(2),
"new_user": m.group(3)
})
return events
def detect_brute_force(self, auth_events: dict, threshold: int = 10) -> list:
"""Detect brute force attempts from auth log data."""
ip_failures = defaultdict(int)
for event in auth_events.get("failed_logins", []):
ip_failures[event["source_ip"]] += 1
brute_force = []
for ip, count in ip_failures.items():
if count >= threshold:
brute_force.append({"source_ip": ip, "failed_attempts": count})
return sorted(brute_force, key=lambda x: x["failed_attempts"], reverse=True)
def generate_report(self, auth_log_path: str) -> str:
"""Generate comprehensive forensic analysis report."""
auth_events = self.parse_auth_log(auth_log_path)
brute_force = self.detect_brute_force(auth_events)
report = {
"analysis_timestamp": datetime.now().isoformat(),
"log_source": auth_log_path,
"summary": {
"successful_logins": len(auth_events["successful_logins"]),
"failed_logins": len(auth_events["failed_logins"]),
"sudo_commands": len(auth_events["sudo_commands"]),
"account_changes": len(auth_events["account_changes"]),
"brute_force_sources": len(brute_force)
},
"brute_force_detected": brute_force,
"auth_events": auth_events
}
report_path = os.path.join(self.output_dir, "linux_log_forensics.json")
with open(report_path, "w") as f:
json.dump(report, f, indent=2)
print(f"[*] Successful logins: {report['summary']['successful_logins']}")
print(f"[*] Failed logins: {report['summary']['failed_logins']}")
print(f"[*] Sudo commands: {report['summary']['sudo_commands']}")
print(f"[*] Brute force sources: {report['summary']['brute_force_sources']}")
return report_path
def main():
if len(sys.argv) < 3:
print("Usage: python process.py <auth_log_path> <output_dir>")
sys.exit(1)
analyzer = LinuxLogForensicAnalyzer(os.path.dirname(sys.argv[1]), sys.argv[2])
analyzer.generate_report(sys.argv[1])
if __name__ == "__main__":
main()
development
拋棄式 HTML mockup 比稿:產出 2 到 3 個設計立場不同的變體(密度 / 版式 / 強調軸,不是換色),各附取捨說明,最後給有立場的對比結論。適用:「畫個草圖」「比較 A 版 B 版」「先看方向再做」「給我看幾種做法」。要 production 元件或設計已定案時不適用。
tools
需求不明時的意圖萃取訪談:一次一題、每題附上自己的猜測、聽出「真正想要 vs 覺得應該要」,直到能預測使用者反應(約 95% 信心)才動工。適用:需求缺少對象 / 動機 / 成功標準 / 約束,或使用者點名「訪談我」「先確認一下」「我們確定嗎」。明確自足的指示、純資訊查詢、機械性操作不適用。
development
對非平凡決策啟動新鮮 context 對抗審查(找碴不背書),在修正還便宜的時候抓出錯誤方向。適用:高風險改動(production、資安敏感邏輯、不可逆操作)、不熟的程式碼、要宣稱「這樣是安全的 / 可行的」之前。機械性操作與一行修改不適用。
testing
Reference for writing and editing agent skills well — the vocabulary and principles that make a skill predictable. Consult when authoring, reviewing, or pruning a SKILL.md.