targets/canary | 生成日: 2026-06-06
canary は単一ファイル(約85行)の C コマンドラインツールです。
argv[1] で指定されたファイルを 4KB のバッファに読み込み、先頭バイトに基づいて3つの「パーサ」関数にディスパッチします
('A' → parse_alpha、'B' → parse_bravo、'C' → parse_charlie)。
gcc:14 Docker イメージ内で gcc -O1 -fsanitize=address によりビルドされ、vuln-pipeline の高速スモークテスト用ターゲットとして提供されています。
上流リポジトリ・CVE 履歴・本番環境へのデプロイは存在しません。バグは意図的に埋め込まれており、ソースコードのコメントおよび README.md に記載されています。
| 資産 | 説明 | 機密性 |
|---|---|---|
| ホストプロセスの完全性 | entry プロセスのメモリおよび命令ポインタの制御。組み込み用途では呼び出し元における RCE を意味する。 |
critical(重大) |
| サービス可用性 | 任意の入力に対して entry が正常終了できる能力。 |
low(低) |
| エントリポイント | 説明 | 信頼境界 | 到達可能な資産 |
|---|---|---|---|
ファイル入力(argv[1]) |
main(entry.c:64–83)が呼び出し元の指定パスから最大 4096 バイトを読み込み、buf[0] で各パーサにディスパッチする。 |
信頼されないファイル → プロセスメモリ | ホストプロセスの完全性、サービス可用性 |
| ビルドパイプライン(Dockerfile) | FROM gcc:14 は可変タグを Docker Hub から取得し、apt-get install はピン留めされていないパッケージを取得する。 |
信頼されないレジストリ → ビルド成果物 | ホストプロセスの完全性 |
各 STRIDE カテゴリとエントリポイントの組み合わせに対するリスク評価です。
| STRIDEカテゴリ | ファイル入力 ( argv[1]) |
parse_alpha (dispatch: A) |
parse_bravo (dispatch: B) |
parse_charlie (dispatch: C) |
ビルドパイプライン (Dockerfile) |
|---|---|---|---|---|---|
| S なりすまし Spoofing |
— 認証なし・設計上の仕様 |
— | — | — | △ 不正イメージのなりすまし |
| T 改ざん Tampering |
● T1 入力バイト全体が攻撃ベクタ |
● T1 length フィールドでメモリ改ざん |
● T1 スタックフレーム上書き |
● T1 解放済みヒープへの書き込み |
● T3 ビルド成果物の汚染 |
| R 否認 Repudiation |
— 監査ログなし・単一ユーザー |
— | — | — | — |
| I 情報漏洩 Information Disclosure |
— 機密データ非保有 |
— | — | △ 非ASAN環境でprintf出力 |
— |
| D サービス拒否 Denial of Service |
● T2 任意クラッシュ |
● T2 ヒープ破壊でクラッシュ |
● T2 スタック破壊でクラッシュ |
● T2 UAF でクラッシュ |
— |
| E 権限昇格 Elevation of Privilege |
● T1 RCE へ発展 |
● T1 ヒープ破壊 → RCE |
● T1 スタック破壊 → RCE |
● T1 UAF → RCE |
● T3 権限昇格の踏み台 |
※「—」はスコープ外または設計上の前提により除外。「△」は低リスク / 条件付き。「●」は該当あり(脅威 ID 参照)。
| ID | 脅威 | アクター | 対象面 | 資産 | 影響度 | 可能性 | ステータス | 現行対策 | 根拠 |
|---|---|---|---|---|---|---|---|---|---|
| T1 | alpha / bravo / charlie パーサにおける信頼されないファイル解析を経由したメモリ破壊による RCE | local_user | ファイル入力(argv[1]) |
ホストプロセスの完全性 | critical | almost_certain | unmitigated | なし | entry.c:25 ヒープバッファオーバーフロー(parse_alpha)、entry.c:38 スタックバッファオーバーフロー(parse_bravo)、entry.c:58 ヒープ解放後使用(parse_charlie) |
| T2 | 不正入力によるクラッシュまたは無制限コピーを経由したサービス拒否(DoS) | local_user | ファイル入力(argv[1]) |
サービス可用性 | low | almost_certain | risk_accepted | ASAN がクリーンにアボート。本ターゲットはクラッシュテスト用途。 | T1 と同じ埋め込みバグ |
| T3 | ピン留めされていない gcc:14 ベースイメージを経由したサプライチェーン侵害 |
supply_chain | ビルドパイプライン(Dockerfile) | ホストプロセスの完全性 | critical | rare | partially_mitigated | メジャーバージョンタグによるピン留め。実行時は --network none。 |
(なし) |
| 脅威 | 除外理由 |
|---|---|
| なりすまし(Spoofing) | ID や認証の概念がスコープ外。入力はファイルであり設計上の仕様。 |
| 否認(Repudiation) | 複数ユーザーによる操作なし、監査ログなし、状態なし。 |
| 情報漏洩(Information Disclosure) | 機密データの読み書きを行わない。 |
| 保存済み入力の改ざん(Tampering of input at rest) | 入力ファイルは定義上攻撃者が供給するものであり、改ざんは攻撃モデルそのものであって独立した脅威ではない。 |
actor を決定する。)low より高くなるかを判断するために必要。)targets/canary(独立した git リポジトリではない)--vulns 未指定、git 履歴なし)| 対策 | 対象脅威 ID | クラス全体を閉じるか | 工数 |
|---|---|---|---|
memcpy の前に入力由来の長さをコピー先バッファに対して境界チェックする |
T1, T2 | partial(部分的) | S(小) |
すべてのパーサをサンドボックス化したサブプロセス(seccomp + --network none + メモリ上限)で実行する |
T1, T2 | yes(完全) | M(中) |
Dockerfile のベースイメージをダイジェスト(gcc:14@sha256:...)と apt パッケージバージョンでピン留めする |
T3 | partial(部分的) | S(小) |
| ID | 深刻度 | カテゴリ | ファイル:行 | タイトル |
|---|---|---|---|---|
| F-001 | HIGH | heap-buffer-overflow |
entry.c:27 |
parse_alpha における入力制御長によるヒープバッファオーバーフロー |
| F-002 | HIGH | stack-buffer-overflow |
entry.c:40 |
parse_bravo における無制限 memcpy によるスタックバッファオーバーフロー |
| F-003 | HIGH | use-after-free |
entry.c:61 |
parse_charlie におけるセンチネル値による早期解放後の解放済みメモリ使用 |
heap-buffer-overflow
entry.c:23 にて buf[0](攻撃者制御バイト、範囲 0–255)がバリデーションなしで claimed に読み込まれます。
entry.c:24 で malloc(8) により固定 8 バイトのヒープバッファが確保されます。
entry.c:27 の memcpy(out, buf+1, claimed) は境界チェックなしで claimed バイトをコピーします。
ペイロードバイトが 9 以上の場合、隣接するヒープメモリへのオーバーフローが発生します。
'A'(ディスパッチ)、2 バイト目に >= 0x09(例: 0xff)を持つファイルを供給します。
ASAN ビルドでは heap-buffer-overflow クラッシュ。非 ASAN ビルドでは RCE に利用可能なヒープ破壊プリミティブとなります。
if (claimed > 8) { free(out); return; } — アロケーションサイズに対してキャップします。
stack-buffer-overflow
entry.c:37 にて char name[16] がスタック上に宣言されます。
entry.c:40 の memcpy(name, buf, len) は len <= sizeof(name) のチェックなしにコピーします。
len は fread の戻り値から最大 4095 バイトになります。ペイロード長が 15 バイトを超えるとスタックフレームが破壊されます。
'B'、続いて 17 バイト以上の制御データを持つファイルを供給します。
非 ASAN バイナリではリターンアドレスの制御と RCE が可能。ASAN では即座に検出・強制終了されます。
if (len >= sizeof(name)) return; — コピー前に長さを確認します。
use-after-free
entry.c:58–60 にて r->id == 0xff の場合 free(r) が呼び出されますが return 文がなく実行が継続されます。
entry.c:61 の r->value = buf[1] が解放済みポインタ経由で書き込みます(UAF 書き込み)。
entry.c:62 の printf が解放済みポインタ経由で読み込みます(UAF 読み込み)。
'C'、2 バイト目に 0xff、3 バイト目に任意の値を持つファイルを供給します。
ASAN ビルドでは heap-use-after-free アボート。非 ASAN では tcache ポイズニング等のヒープ悪用が可能です。
free(r); return; — free の直後に return を追加してフォールスルーを除去します。