シークレットスキャナーのバグを、カナリアは見つけられなかった
配送
販売するキットをZIP圧縮する前に、ゲートが当社のシークレットの実値をスキャンします。スキャンは必ず、各種類のカナリアを1つずつ仕掛けて始まり、すべてを検出できない限り実行を拒否します。カナリアは常に検出されていました。それでもバグはありました。
ゲートがシークレットを読む仕組み
ゲートはキーのような形のものだけを探すのではありません。シークレットが保存されているファイル(envファイル、JSON設定、キーファイル)を読み、名前がシークレットであることを示す値をすべて取得し、出荷予定のコンテンツを、そのままの形式とBase64エンコードの両方で検索します。
バグの内容
次のような行の場合:
DB_PASSWORD='Tr0ub4dor-and-3' # 5月にローテーション済み
リーダーは、値が引用符で始まり引用符で終わる場合に限り、周囲の引用符を除去していました。値の後にコメントが続くと行は文字で終わるため、引用符が残ってしまいます。次にコメントが切り取られ、ゲートは引用符付きの'Tr0ub4dor-and-3'を検索し続けます。引用符なしでパスワードを含むキットは、通過してしまっていたはずです。
カナリアが気づかなかった理由
カナリアはネット(検出網)を検証します。スキャナーがすでに知っている値を仕掛け、検出されるかを確認します。当社のカナリア値はスキャナーに直接渡されていたため、設定行を読むコードを通過していませんでした。すべてのネットは検証されましたが、その手前のパーサーは検証されていませんでした。
発見の経緯
ゲートを独立した製品化しようとして、実際に人が書く形式(export、引用符、末尾のコメント)の設定ファイルを渡すテストを作成しました。コメント付きの引用符付き行でテストは失敗しました。修正では、引用符付きの値を閉じ引用符まで読み、その後に続くものを無視します。
影響はあったのか?
変更前に確認しました。ビルドマシンでは、ゲートは与えられた59個のファイルから133個のシークレット値を読み取り、別のマシンでは499個を読み取りますが、その形状を持つものは1つもありませんでした。過去の判定結果は変わりません。リリース済みのすべてのキットは、現在スキャンされるのと同じ値でスキャンされていました。いずれにせよ、3台すべてのマシンでゲートを修正しました。
まとめ
スキャナーが検索対象を抽出できるなら、仕込んだ値での検索だけでなく、現実的な入力での抽出もテストすること。カナリアは網が機能することは証明しても、目的の魚が網にかかることまでは証明しない。Secret Gateのテストでは両方をカバーしており、リリース前にビルドゲートと同じ133の値を読み取れることを確認した。