2 ポイント 投稿者 GN⁺ 2024-06-06 | 1件のコメント | WhatsAppで共有
  • Entropyは、大規模なコードベースから高エントロピーの行をスキャンし、シークレットと思われる文字列を見つけるCLIツール
  • 高エントロピーの行はシークレットである可能性が高い対象として扱われ、コードベース内に露出したシークレットを見つける用途に焦点を当てている
  • インストールと実行は、Goソースからのインストールgo run、Homebrew、Dockerの方法で提供される
  • 実行オプションとして -top-ext-ignore-ext を使い、結果の件数、対象に含める拡張子、除外する拡張子を指定できる
  • Dockerで実行する場合は、現在のディレクトリを /data にマウントし、コマンドの末尾に /data を付ける必要がある。そうすることでローカルファイルシステムをスキャンする

Entropyが行うこと

  • Entropyはコードベースをスキャンし、高エントロピーの行を見つけるCLIツール
  • 高エントロピーの行はシークレットであることが多く、コードベース内のシークレット漏えいを見つけるのに役立つ

インストールと実行方法

  • Goでインストール

    • 推奨されるインストール方法は、Goを使ったソースからのインストール
    • インストール後は entropy コマンドで実行する
go install github.com/EwenQuim/entropy@latest
entropy
  • 1行で実行する方法も提供されている
go run github.com/EwenQuim/entropy@latest
  • Homebrewでインストール

    • Homebrewのインストールコマンドは次のとおり
brew install ewenquim/repo/entropy
entropy
  • Dockerで実行

    • Dockerでの実行は、現在のディレクトリをコンテナの /data にマウントする方式
docker run --rm -v $(pwd):/data ewenquim/entropy /data

主なオプション例

  • -h: 利用可能なオプションを確認する
entropy -h
  • -top: 出力する上位結果の件数を指定する
  • -ext: スキャン対象の拡張子を指定する
entropy -top 20 -ext go,py,js
  • -ignore-ext: 除外する拡張子を指定する
  • ファイルとフォルダをまとめて引数として渡せる
entropy -top 5 -ignore-ext min.js,pdf,png,jpg,jpeg,zip,mp4,gif my-folder my-file1 my-file2

Docker使用時の注意点

  • Dockerの -v オプションは、現在のディレクトリをコンテナ内にマウントするために使う
  • /data は、ツールがファイルを探すデフォルトのディレクトリ
  • コマンドの末尾に /data を追加しないと、ローカルファイルシステムではなくコンテナ内部を検索する
docker run --rm -v $(pwd):/data ewenquim/entropy -top 20 -ext go,py,js /data
docker run --rm -v $(pwd):/data ewenquim/entropy -top 5 /data/my-folder /data/my-file

1件のコメント

 
GN⁺ 2024-06-06
Hacker News の意見
  • 興味深い。自分なら、高エントロピーなものは圧縮しにくいという原理で、こんなふうにやったと思う
    perl -lne 'next unless $_; $z = qx(echo "$_" | gzip | wc -c); printf "%5.2f %s\n", $z/length($_), $_'
    ただしこの方式は、ファイル全体ではなく各行を辞書のように使うため、非常に短い行は圧縮されにくく、少し問題が出る
    return map { $_ > 1 ? 1 : ($_ < 0 ? 0 : $_) } @vs; のような行には反応したが、有効なコードではあるものの、実際かなりエントロピーが高そうに見える
    逆に、自然言語の英語コメントを付け加えると、高エントロピーな行を検出できないようにだますこともできた
    移動中なので詳しくは見られないが、この Perl コマンドとこのツールを比較してみると面白そうだ。Perl コマンドの利点は、Windows 以外のほぼすべてのマシンですぐ動くので、採用されるために必ずしも強力である必要はないという点

    • ずいぶん前に Advent of Code の問題を解きながら Go を学んでいたのだが、問題を解くたびにハウスメイトがコードを見せろとせがみ、その後 Go で 10〜50 行だった解答をRuby のワンライナーに書き直していた
      そうやって Go と自分の拙いプログラムをずっとからかっていて、意図せずその日は Ruby もかなり学ぶことになった
    • テスト対象の行を除いたファイルの全行でファイルサイズを測り、その行を追加してから再度測れば、サイズ差がより公平な指標になりそう
      すべてのコードファイルを連結してからリポジトリ全体で行単位にテストすることもできるだろうが、おそらく遅すぎると思う
    • gzip より良い圧縮器を使うだろうが、このトリックは何度か使ったことがある
      xzzstd のほうが良い選択かもしれないし、最高の圧縮率がより良いエントロピー推定だという観点で Hutter Prize [1] の受賞作を見てもよい
      [1] http://prize.hutter1.net/
    • zip のようなコマンドラインツールの中に、1 つ以上のファイルで辞書を事前定義しておき、その辞書で小さなファイルを圧縮できるものがあるのか気になる
      もちろん展開時にも、その辞書を別入力として渡す必要があるはず
    • Yelp の secret scanner を pre-commit フックとして使っているが、pre-commit のインストール機構でかなり簡単に設定できる
  • この問題は、すべてのデータベースパスワードを abcd にすることで超越した

    • うちのコードベースでは、このツールが "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"高エントロピーな行として検出した
    • ユーザー名: postgres
      パスワード: postgres
    • https://xkcd.com/936/ を思い出す。"correct horse battery staple" は、ただの普通に見える単語列なので低エントロピーになりそう
  • こうした用途でのエントロピーの使い方を扱った良い記事があるのか気になる。人々が実際にどう使っているのか、効果があるのかはずっと気になっていたが、自分で掘り下げたことはない
    まず、テキストの「エントロピー」をどう定義するかも曖昧だ。ここでは -Sum(x log(x))、つまり x = countOccurences(char) / len(text) 程度の単純なものだが、これが実際どれほど機能するのかにはいろいろ疑問が湧く
    文字列はどれくらい長い必要があるのか。自然言語にはほぼ一定のエントロピーがあるのか。もっと良いアプローチはあるのか。
    たとえば "vorpal""hJ6&:a" より「明らかに」エントロピーが低いはずだと思う。後者は自然言語よりずっと大きな文字集合を使っているように見えるし、仮にそうでなくても文字の順序が重要で、前者は Carroll が作った単語にもかかわらず実在の単語のように聞こえる
    ところが、皆が使っているこの「エントロピー」はそうしたことをまったく知らない。両者はまったく同じ「エントロピー」を持つはずだ
    もう一つの GitHub パスワード検索器程度には十分うまく機能するかもしれないが、もっと良いものがあるのか気になる。テキストのランダム性をより意味のある形で測る尺度はあるのだろうか
    こうしたプロジェクトは何十もあり、皆が「エントロピー」を当然のように使っているが、この主題についてのきちんとした研究は見たことがない

    • エントロピーは信号の複雑さや無秩序さを測る尺度だ。興味深いのは、その無秩序さが適切な基底や辞書に相対的だという点
      あるものは、あるエンコーディングでは複雑に見えても、正しいエンコーディングでは低エントロピーになり得る
      信号のエントロピーを正確に判断するには、正しい基底を知っているか、文脈から推論する必要がある
      元記事のツールをより強くするなら、ソースコードや自然言語のような典型的なテキスト範囲について事前計算した辞書をいくつか用意し、各辞書で文字列をエンコードして圧縮可能性を比較する方式がよい
      秘密値のようにエントロピーの高い文字列は、利用可能なすべての辞書に対して圧縮されにくいはず
    • 特定の文字列のエントロピーは、厳密な数学的概念ではない。定義上、すでに知られている文字列は 1 つの値しか持てないため、「エントロピー」は0 ビットになる
      私たちがランダムでないデータとランダムなデータを区別できる理由は、あり得るすべての状態のうち人間にとって有用だと考えられる状態は小さな部分集合にすぎず、その部分集合がどのようなものかをある程度知っているので、特定の文字列がどの過程で生成されたのかを推定できるからだ
      もちろん https://en.wikipedia.org/wiki/Diehard_tests のような統計的検定は、低エントロピーのデータと高エントロピーのデータを区別するには十分良いが、最近の疑似乱数生成器はこうした検定をすべて通過するのに問題がない。実際の「エントロピー」はシード値とアルゴリズムの複雑さ程度でしかないにもかかわらず
    • 任意の文字列のコルモゴロフ複雑性は計算不可能
  • あわせて見ておきたいツール:
    trufflehog: https://github.com/trufflesecurity/trufflehog
    detect-secrets: https://github.com/Yelp/detect-secrets
    semgrep secrets: https://semgrep.dev/products/semgrep-secrets -- 有料だが、場合によっては既存ライセンスに含まれることもある

    • 興味深い文字列やシークレット値を探すには PyWhat も見ておく価値がある: https://github.com/bee-san/pyWhat
    • noseyparker も悪くない: https://github.com/praetorian-inc/noseyparker
      こうしたソリューションは、エントロピーに基づく単純なアプローチよりもシークレット値の検出にははるかに優れていると思う
      エントロピーのほうがより汎用的なのは確かだが、これらのツールはすでに定着しており、本当に多くのデータセットを通して検証されている
  • 数年前、高エントロピー文字列とは何かを質問し[0]、関連する良い記事[1]をリンクしてくれた DrJones のおかげで助かった
    [0] https://news.ycombinator.com/item?id=13304641
    [1] https://www.splunk.com/en_us/blog/security/random-words-on-e...

  • 長年使ってきた ent プログラムを思い出す
    https://fourmilab.ch/random/

  • プロジェクトの git 履歴全体まで調べてくれると便利そう。シークレット値がコミットされて後から削除されていても、履歴にはまだ残っている可能性がある

  • このツールを実行するのに、なぜ Go をインストールしなければならないのか分からない。Go の利点の一つは、開発者がそのまま動作する 単一バイナリを配布できることではなかったのか?

    • セキュリティツールなので、最初からバイナリを信頼するのは目的に反する。ソースがあれば、少なくとも実際に何をしているのか確認する選択肢はある
    • Homebrew に載せたかったが PR が却下されたので、自分で brew tap を作るか、受け入れてもらえるよう説得する必要がありそう
      Docker イメージも作る予定
      正直ここまで人気が出るとは思っていなかったので、リポジトリはまだ 100% 準備できている状態ではない
    • Docker コンテナは現在利用可能で、ホームページにドキュメント化されている
  • Llama 3 のような 言語モデルなら、トークンごとの意外性をモデル化して、最も意外な領域、つまりエントロピーが最も高い領域を検出できそう
    例の一つのように、アルファベット全体はある観点ではエントロピーが高いかもしれないが、コードに慣れた言語モデルなら、コードベースに Base62 アルファベットが定数としてあることをまったく意外とは見なさないはず