フック

network フック:URL の SSRF リスクを判定する

コマンドラインから直接、1 つまたは複数のリクエスト先の SSRF リスクを判定できます。

network フックは、サーバー側のリクエスト先が SSRF(内部サービス、クラウドのメタデータ、プライベートなホストに向けられうるリクエスト)に対して安全かどうかを判定します。network 専門知識 を支える決定論的なエンジンで、自分で実行することもできます。

実行方法​

各リクエスト先を --url で渡します。フックはリクエスト先ごとに 1 語を出力します。その意味は下の表のとおりです。

npx lagune read network --url 'http://example.com/'
# => safe

npx lagune read network --url 'http://0x7f000001/'
# => private-target

ホストはネットワークと同じ方法で解釈するため、内部アドレスをエンコードした形式もすり抜けられません:16 進数、8 進数、ドットなしの 10 進数、省略形、IPv6、IPv4 射影アドレスは、どれも private-target と判定されます。また、ずさんな検証処理と実際にリクエストを送る処理とで読み取るホストが食い違う場合、判定は parser-divergent になります。

判定の読み方​

判定意味
safeリクエスト先が公開ホストに接続し、ずさんな検証処理でも同じホストとして読み取られる。
private-targetホストがプライベート、ループバック、リンクローカル、未指定、またはクラウドメタデータのアドレスに解決される。
parser-divergentずさんなテキスト検証処理が、リクエストを送る処理の実際の接続先とは異なるホストを読み取る。
invalid url文字列を URL として解析できず、リクエストする対象がない。

許可を意味するのは safe だけです。private-target、parser-divergent、invalid url はいずれもブロックとして扱ってください。

CLI オプション​

オプション値説明
--urlURL またはホスト1 つのリクエスト先をチェックする。繰り返し指定すると複数をチェックし、1 行に 1 つずつ判定を出力する。

--url は少なくとも 1 つ必要です。リクエスト先を位置引数として単独で渡すことはないため、フラグと取り違えられることはありません。

フラグの値として渡す理由

各リクエスト先はフラグの値として渡され、コマンドに埋め込まれることはありません。引用符やバッククォートを含む値も無害なままで、シェルへのインジェクションは起こりません。シェルが先に展開してしまわないよう、必ずシングルクォートで囲んでください。

対象外の範囲

このフックは純粋関数で、DNS の名前解決を一切行わないため、実行時に生じる 2 つの抜け穴は対象外です:DNS リバインディング(チェック時には公開アドレスに、リクエスト時には内部アドレスに解決される名前)と、リダイレクトチェーン(最初のホップはチェックを通過し、その後で内部へリダイレクトされるもの)です。これらは、名前解決を 1 回だけ行って検証済みのアドレスに接続し、リダイレクトを拒否することで塞いでください。予約済みのループバック名(localhost と .localhost 系)は名前解決をせずに内部として扱いますが、それ以外の DNS 名はすべて safe と判定されます。内部に解決されると断定するには名前解決が必要になるためです。こうした名前は許可リストで守るもので、このチェッカーが検証するのもその許可リストです。

ヒント

これは、リクエスト先のフィルターが有効であることを証明するために network 専門知識 が実行するチェックと同じものです。

よくある質問

network フックを実行します。リクエスト先を判定し、safe、private-target、parser-divergent、invalid url のいずれかを返します。許可を意味するのは safe だけです。

パーサーによって解釈が異なる URL のことで、SSRF 対策を回避する典型的な手口です。network フックはこれを許可せず、指摘します。