
外部から観測可能なデータのみを使用して、組織が契約しているSaaSサービスを特定します。シャドーITの発見のために構築されています。
▄▄▓▓▓▓▓▓▓▓▓▄▄
▄▓▓▒▒▒▒▒▒▒▒▒▒▒▓▓▄ Yowie · 誰も教えてくれなかったSaaSを追跡する
▓▓▒▒░░░░░░░░░░░▒▒▓▓
▓▒░░ ● ● ░▒▓ ドメイン acme.com.au
▓▒░░ ▼ ░▒▓ 候補 acme, acmecorp
▓▓▒░░ ╰───╯ ░▒▓▓
▀▓▓▒▒░░░░░░░░░▒▒▓▓▀
▀▀▓▓▓▓▓▓▓▓▓▓▓▀▀
組織が契約しているSaaSサービスを、外部から観測可能なデータのみを使って発見します。シャドーITの発見のために作られました。見つける価値のあるサービスとは、誰も教えてくれなかったサービスのことです。
オーストラリアの未確認生物にちなんで名付けられました。誰もが「そんなものは存在しない」と言い張る何かを、あなたは追いかけているのですから。

412ベンダーをカバーする574のシグネチャが9つの検出器にまたがって存在し、さらに104件が確認待ちとして保留されています。検出結果は格付けされ、そのすべてが、それを生み出したレコードまたはレスポンスを伴っています。
go build -o yowie ./cmd/yowie
Go 1.22以降が必要です。シグネチャパックはバイナリに埋め込まれているため、デプロイに必要なのはこの単一ファイルだけです。
yowie [flags] <domain> [candidate ...]
ドメインは組織のルートドメインです。候補は、ベンダーのテナント名に使われている可能性のある短い文字列です。商号、略称、買収によって引き継がれた旧ブランドなどが該当します。思いつく限り指定してください。それぞれがテナントを見つける追加のチャンスになります。指定しない場合は、ドメインの最初のラベルが使われます。
yowie acme.com.au acme acmecorp acmegroup
yowie -format html -o report.html acme.com.au acme
yowie -format json acme.com.au | jq '.findings[] | select(.confidence=="high")'
yowie -only dns,spf,dmarc -compact acme.com.au
yowie -signatures ./signatures -validate
| 検出器 | シグナル |
|---|---|
dns | TXT検証トークン、CNAME、MX、NSレコード |
vanity | 組織名を冠したベンダーホスト型テナント(acme.zendesk.com) |
http | DNS上の痕跡がないサービス向けのアプリケーション層フィンガープリント |
spf | SPF includeグラフ全体。ネストされたincludeとredirectを追跡 |
dmarc | DMARC集約/forensicレポートの送信先 |
bimi | BIMIロゴとVerified Mark Certificateのホスティング |
mta-sts | MTA-STSポリシーの内容 |
tenant | MicrosoftテナントID、フェデレーションIDプロバイダー、および兄弟ドメイン |
ct | Certificate Transparencyログから得たサブドメインを解決し、帰属を判定 |
-onlyまたは-skipで選択します。例えば-skip ct,httpとすると、高速なDNSのみのパスになります。
最後の2つは特筆に値します。シグネチャリストでは見つけられないものを発見するからです。
**tenant**は、Microsoftの認証不要エンドポイントに、そのドメインが誰に属するかを問い合わせます。Autodiscoverのフェデレーション情報は、同じテナントに紐づくすべてのドメインを返し、これによって事業部門、買収先、放棄されたブランドが日常的に浮かび上がります。それぞれが、スキャンする価値のある別のドメインなのです。
**ct**は発見のモデルを反転させます。他のすべてのチェックは固定リストに対して「この組織はベンダーXを使っているか?」と問うため、誰かがすでにシグネチャを書いたベンダーしか見つけられません。CTは「この組織は実際に自分のサブドメインを何に向けているのか?」と問います。ある製品にサインアップし、support.acme.comを設定したチームには証明書が発行され、その証明書は公開され、永続的です。どのシグネチャにも一致しないターゲットはリードとして報告されます。これが、探すべきだと知らなかったものを見つける方法です。
検出結果は格付けされ、その格付けこそが要点です。
acme.blogspot.comはあなたのacmeではないかもしれない。2つの独立した検出器が同じベンダーで一致すると、Probableの検出結果はConfirmedに昇格します。すべての検出結果は、それを引き起こした正確なレコードまたはレスポンスを伴うため、ツールを再実行することなくレポートを正当化できます。
この昇格には1つ例外があり、それは「このテナントは存在する」と「このテナントはあなたのものだ」の違いです。精度に関する注意の名前空間の注記を参照してください。
-no-unknownは、シグナルのみが必要な場合に、帰属不明のリードを除外します。
-format cli(デフォルト)、json、jsonl、csv、html。-oでファイルに書き出します。HTMLレポートは自己完結型で、外部アセットを必要としないため、メール添付や共有ドライブへの配置にも耐えます。
進捗はstderrに、結果はstdoutに出力されるため、yowie -format json acme.com > out.jsonでもライブの進捗行が表示されます。
シグネチャはsignatures/*.yamlにあります。バイナリはそれらを埋め込みますが、-signatures <dir>またはYOWIE_SIGNATURES=<dir>を使うとディスクから読み込みます。これにより、再ビルドせずに反復作業ができます。
version: 1
pack: dns-txt
description: "Domain-ownership verification tokens published as TXT records."
defaults:
confidence: high
signatures:
- id: txt-1password
vendor: "1Password"
category: "Identity & Secrets"
type: txt
query: "{domain}"
match:
contains: "1password-site-verification"
{domain}はルートドメインに、{candidate}は各候補文字列に展開されます。{candidate}を参照するシグネチャは、候補ごとに1回評価されます。
| タイプ | マッチ対象 | 備考 |
|---|---|---|
txt, cname, mx, ns | queryのレコードに対するmatch.contains | 大文字小文字を区別しない |
vanity_a, vanity_cname | ベースライン比較。matchブロックなし | queryに{candidate}を含む必要がある |
http | match.present、match.absent、またはmatch.statusのみ | 下記のステータス処理を参照 |
spf_include | 解決済みSPF includeグラフに対するmatch.contains | |
dmarc_rua | DMARCレポート送信先に対するmatch.contains | |
cname_target | queryはホスティングサフィックスのみ | ctで発見されたホストに適用。*は1ラベルにマッチ |
disabled: trueは、その背後にある調査を失うことなくシグネチャを保留します。notes:はアナリストのガイダンスをレポートまで引き継ぎます。
編集後はyowie -validateを実行してください。検証は厳格で、未知のキーはサイレントな無視ではなくエラーになります。また、パックはgo testでもチェックされるため、タイポが今後のすべてのスキャンで気づかぬうちにカバレッジを損なうことはありません。
| パック | 内容 |
|---|---|
dns-txt, dns-cname, dns-mx | 検証トークンと委任ホスト名。有効。 |
email-spf, email-dmarc | 送信元とDMARCプロセッサ。有効。 |
vanity-tenants, http-endpoints | テナントホスト名とアプリのフィンガープリント。有効。 |
cname-targets | CTで発見されたサブドメイン向けのホスティングサフィックス。有効。 |
ai-services | AIおよびLLMプラットフォーム。保留。 |
file-transfer | マネージドファイル転送 — MOVEit、GoAnywhere、Egnyte。保留。 |
finance-procurement | 財務、経費、給与、調達。保留。 |
security-grc | セキュリティツールとコンプライアンス自動化。保留。 |
graveyard | 未検証のエントリ、および運営元を特定できなかったプラットフォーム。保留。 |
5つのパックは完全に無効化された状態で出荷されます。構造的には完全で検証も通りますが、マッチ条件が実際のテナントに対して確認されたことがないため、スキャン中には評価されません。
これは意図的なものです。containsの値が間違っているシグネチャは、決して発火せず、決してエラーも出しません。ただ、カバーされていないベンダーがカバーされているように見えるだけです。それらを無効のまま出荷することで、数字を水増しすることなく、調査をリポジトリに残せます。
これまでに5つが昇格しました。残りを信頼する前に知っておく価値のある記録として、2つは書かれた通りに正しく、1つはドメインが間違っており、2つはドメインは正しいがチャネルが間違っていました。つまり、エントリが予測した顧客ごとのホスト名ではなく、SPF includeとしてベンダーが現れたのです。残りの保留エントリは、潜在的なカバレッジではなく調査ノートとして扱ってください。
-validateはバックログをパックごとにグループ化して出力します。
$ ./yowie -validate
574 signatures across 13 packs, covering 412 vendors
...
104 signature(s) parked behind `disabled: true`, awaiting confirmation against a live tenant:
ai-services.yaml (24)
txt-fireflies-ai Fireflies.ai
...
昇格させるには:
dig +short TXT known-customer.com | grep -i <vendor> # token signatures
dig +short A acme.egnyte.com # vanity signatures
dig +short A $(openssl rand -hex 6).egnyte.com # ...and its baseline
バニティテナントは、ランダムなラベルとは異なる応答を返さなければなりません。disabled: trueを削除し、正直なconfidenceを設定する。notes:を、確認した内容を述べるように書き直す。./yowie -signatures ./signatures -validateメカニズムが機能しないことが判明した場合は、無効のままにし、否定的な結果をnotes:に記録してください。それは機能するシグネチャと同じくらい価値があります。次の人が午後を費やして再発見するのを防ぐからです。security-grcにはすでにそのようないくつかが含まれており、CrowdStrike、Wiz、Tenableにバニティシグネチャが存在しない理由を説明しています。彼らはすべての顧客を共有コンソールに配置するため、顧客ごとに検出できるものが何もないのです。
このツールは自らのバックログを生成します。帰属不明の送信元とホストは、まさにシグネチャを書く価値のあるベンダーであり、多くのスキャンを通じて頻度順に自らをランク付けします。
for d in $(cat domains.txt); do ./yowie -format json -quiet "$d"; done \
| jq -r '.findings[] | select(.category|startswith("Unidentified")) | .vendor' \
| sort | uniq -c | sort -rn | head -40
無関係な組織をまたいで繰り返し現れるものは本物です。これはまた、確認済みのライブサンプルを無償で生み出します。SPFとDMARCの証拠には実際の送信元ホスト名が含まれており、これはまさに保留エントリが必要としているものです。
多くのベンダーはテナントゾーンをワイルドカード化しているため、「解決する」ことは何も証明しません。各テンプレートはまず、存在しないテナントに対してベンダーがどう応答するかを知るために、2つのランダムなラベルでプローブされます。候補がカウントされるのは、その応答がそのベースラインと異なる場合だけです。2つのベースラインが互いに一致しない場合(ジオDNS、ラウンドロビン)、比較は無意味であり、シグネチャは推測されることなく警告とともにスキップされます。
NXDOMAINのベースラインはConfirmedの検出結果を生みます。異なる応答を返すワイルドカードのベースラインは、そのシグネチャ自身のconfidenceと、なぜそれが弱いのかを説明する注記を生みます。
| フラグ | 目的 |
|---|---|
-only / -skip | 検出器を選択 |
-compact | 検出結果ごとに1行 |
-max-evidence | ターミナルで検出結果ごとに表示する証拠行数。デフォルト6(0で全件) |
-no-unknown | 帰属不明の送信元とホストを除外 |
-warnings | 致命的でない問題を表示。警告のあるスキャンは部分的なスキャン |
-ct-limit | CTログから解決するホスト名の上限(デフォルト400) |
-ct-timeout | CTアグリゲータは遅い(デフォルト60秒) |
-nameservers | パブリックリゾルバを上書き |
-timeout | スキャン全体の予算(デフォルト5分) |
-dns-concurrency / -http-concurrency | スループットを調整 |
-dns-timeout / -http-timeout | クエリごと、リクエストごとの予算 |
-quiet | 進捗行を抑制 |
-insecure | 証明書が壊れているベンダー向けにTLS検証をスキップ |
-no-banner / -no-color / -no-evidence | ターミナル出力を簡素化 |