- 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
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
主なオプション例
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件のコメント
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 以外のほぼすべてのマシンですぐ動くので、採用されるために必ずしも強力である必要はないという点
そうやって Go と自分の拙いプログラムをずっとからかっていて、意図せずその日は Ruby もかなり学ぶことになった
すべてのコードファイルを連結してからリポジトリ全体で行単位にテストすることもできるだろうが、おそらく遅すぎると思う
xz や zstd のほうが良い選択かもしれないし、最高の圧縮率がより良いエントロピー推定だという観点で Hutter Prize [1] の受賞作を見てもよい
[1] http://prize.hutter1.net/
もちろん展開時にも、その辞書を別入力として渡す必要があるはず
この問題は、すべてのデータベースパスワードを
abcdにすることで超越した"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"を高エントロピーな行として検出したパスワード: postgres
"correct horse battery staple"は、ただの普通に見える単語列なので低エントロピーになりそうこうした用途でのエントロピーの使い方を扱った良い記事があるのか気になる。人々が実際にどう使っているのか、効果があるのかはずっと気になっていたが、自分で掘り下げたことはない
まず、テキストの「エントロピー」をどう定義するかも曖昧だ。ここでは
-Sum(x log(x))、つまりx = countOccurences(char) / len(text)程度の単純なものだが、これが実際どれほど機能するのかにはいろいろ疑問が湧く文字列はどれくらい長い必要があるのか。自然言語にはほぼ一定のエントロピーがあるのか。もっと良いアプローチはあるのか。
たとえば
"vorpal"は"hJ6&:a"より「明らかに」エントロピーが低いはずだと思う。後者は自然言語よりずっと大きな文字集合を使っているように見えるし、仮にそうでなくても文字の順序が重要で、前者は Carroll が作った単語にもかかわらず実在の単語のように聞こえるところが、皆が使っているこの「エントロピー」はそうしたことをまったく知らない。両者はまったく同じ「エントロピー」を持つはずだ
もう一つの GitHub パスワード検索器程度には十分うまく機能するかもしれないが、もっと良いものがあるのか気になる。テキストのランダム性をより意味のある形で測る尺度はあるのだろうか
こうしたプロジェクトは何十もあり、皆が「エントロピー」を当然のように使っているが、この主題についてのきちんとした研究は見たことがない
あるものは、あるエンコーディングでは複雑に見えても、正しいエンコーディングでは低エントロピーになり得る
信号のエントロピーを正確に判断するには、正しい基底を知っているか、文脈から推論する必要がある
元記事のツールをより強くするなら、ソースコードや自然言語のような典型的なテキスト範囲について事前計算した辞書をいくつか用意し、各辞書で文字列をエンコードして圧縮可能性を比較する方式がよい
秘密値のようにエントロピーの高い文字列は、利用可能なすべての辞書に対して圧縮されにくいはず
私たちがランダムでないデータとランダムなデータを区別できる理由は、あり得るすべての状態のうち人間にとって有用だと考えられる状態は小さな部分集合にすぎず、その部分集合がどのようなものかをある程度知っているので、特定の文字列がどの過程で生成されたのかを推定できるからだ
もちろん 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 -- 有料だが、場合によっては既存ライセンスに含まれることもある
こうしたソリューションは、エントロピーに基づく単純なアプローチよりもシークレット値の検出にははるかに優れていると思う
エントロピーのほうがより汎用的なのは確かだが、これらのツールはすでに定着しており、本当に多くのデータセットを通して検証されている
数年前、高エントロピー文字列とは何かを質問し[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 の利点の一つは、開発者がそのまま動作する 単一バイナリを配布できることではなかったのか?
Docker イメージも作る予定
正直ここまで人気が出るとは思っていなかったので、リポジトリはまだ 100% 準備できている状態ではない
Llama 3 のような 言語モデルなら、トークンごとの意外性をモデル化して、最も意外な領域、つまりエントロピーが最も高い領域を検出できそう
例の一つのように、アルファベット全体はある観点ではエントロピーが高いかもしれないが、コードに慣れた言語モデルなら、コードベースに Base62 アルファベットが定数としてあることをまったく意外とは見なさないはず