mcpField
P
performing-linux-log-forensics-investigation

performing-linux-log-forensics-investigation

github.com/mukul975セキュリティ35.2k70 回インストール8 週間前に更新
リポジトリ

performing-linux-log-forensics-investigation について

調査担当者やインシデント対応担当者向けの Linux ログフォレンジック用スキルです。認証、システム、監査、journal のログを扱い、コマンドライン分析と Python パーサーの例を示します。

主な機能

  1. 01認証ログと SSH ログの分析
  2. 02systemd journal の出力と絞り込み
  3. 03Linux Audit イベントの検索
  4. 04Cron とパッケージ操作の確認
  5. 05Python フォレンジックパーサーの例

活用シーン

  1. 01Linux のユーザーセッション再構成
  2. 02不正アクセスの疑いの調査
  3. 03ホストログからのイベント時系列作成

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill performing-linux-log-forensics-investigation

インストール後、Claude Code で/performing-linux-log-forensics-investigationを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

LICENSE
assets/
template.md
references/
api-reference.md
standards.md
workflows.md
scripts/
agent.py
process.py

詳細

Linux ログフォレンジック調査の実施

概要

Linux システムには、フォレンジック調査における主要な証拠源となるログが大量に記録されています。Windows イベントログとは異なり、Linux のログは通常、/var/log/ に保存されたプレーンテキストファイルと、systemd-journald が管理するバイナリージャーナルファイルです。主なフォレンジックログには、auth.log(認証イベント、sudo の使用、SSH セッション)、syslog(システム全体のメッセージ)、kern.log(カーネルイベント)、アプリケーション固有のログがあります。Linux Audit フレームワーク(auditd)は、Windows セキュリティイベントログに匹敵する詳細なセキュリティイベントのログ記録を提供します。これらのログをフォレンジック分析することで、調査担当者はユーザーセッションを再構成し、不正アクセスを特定し、権限昇格を検出し、ラテラルムーブメントを追跡し、包括的なイベントのタイムラインを作成できます。

使用する場面

  • Linux ログフォレンジック調査の実施を伴うセキュリティ評価を行う場合
  • 関連するセキュリティイベントへのインシデント対応手順に従う場合
  • 定期的なセキュリティテストや監査活動を行う場合
  • 実践的なテストを通じてセキュリティ制御を検証する場合

前提条件

  • デジタルフォレンジックの概念とツールに関する知識があること
  • 安全に実行できるテスト環境またはラボ環境にアクセスできること
  • 必要な依存関係をインストールした Python 3.8 以降
  • テスト活動に対する適切な許可があること

主なログファイルと保存場所

ログファイルパス内容
auth.log / secure/var/log/auth.log(Debian)または /var/log/secure(RHEL)認証、sudo、SSH、PAM
syslog / messages/var/log/syslog(Debian)または /var/log/messages(RHEL)一般的なシステムメッセージ
kern.log/var/log/kern.logカーネルメッセージ、USB イベント、ドライバーの読み込み
lastlog/var/log/lastlogユーザーごとの最終ログイン(バイナリー)
wtmp/var/log/wtmpログイン/ログアウトの記録(バイナリー、last で読み取り)
btmp/var/log/btmpログイン失敗の試行(バイナリー、lastb で読み取り)
faillog/var/log/faillogログイン失敗のカウンター(バイナリー)
cron.log/var/log/cron または /var/log/syslogスケジュールされたタスクの実行
audit.log/var/log/audit/audit.logLinux Audit フレームワークのイベント
journal/var/log/journal/ または /run/log/journal/systemd のバイナリージャーナル
dpkg.log/var/log/dpkg.logパッケージのインストール/削除(Debian)
yum.log/var/log/yum.logパッケージのインストール/削除(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
Systemd ジャーナルの分析
# 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
Linux Audit フレームワークの分析
# 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
Cron ジョブの調査
# 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

Python フォレンジックログパーサー

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()

参考資料

コメント