要約
ほとんどのSASTルールには推論モデルは必要ありませんが、JavaScriptのパストラバーサルのようなエッジケースでは、2倍の誤検知を検出します。
推論モデルは単なる誇大広告なのでしょうか?
「推論モデル」が注目を集めています。大手AIラボは主導権争いを繰り広げ、スケーリング法則、よりスマートな事前学習、およびRLHF(人間のフィードバックからの強化学習)によるファインチューニングを通じて、モデルのサイズとパフォーマンスの限界を押し広げています。また、思考連鎖プロンプティングを重ねることで、推論中にモデルが「思考を声に出す」ようにしています。これにより、論理タスクにおいて非AIシステムを凌駕し、その過程でリーダーボードのトップに立っています。
それは印象的です。しかし、それらは実際に実用的でしょうか?それは状況によります。
AutoTriage* の場合、SAST**ルールの複雑さに大きく依存します。
*簡単なまとめ - AutoTriageは、AikidoがSASTの誤検知をフィルタリングするために使用する機能です。
**SASTの検出結果は、ハードコードされたパターン検出器によって報告される、ソースコード内で発見された潜在的な脆弱性です。
ほとんどのSASTルールに対して過度に高価です。
AutoTriageは2つのステップで機能します。まず、エクスプロイトの可能性を排除しようと試みます。それが可能であれば、誤検知を除外できます。これには、ユーザー制御変数が脆弱性に到達可能であるかについて、厳密な判断が必要です。モデルは基本的に、変数が実際にユーザーによって制御されているか、そしてサニタイズ、バリデーション、型変換が適切に行われているかを確認します。また、何らかの緩和策がある場合、それが実際に効果的であるかを判断します。
第2ステップは、第1ステップでエクスプロイトの可能性を排除できない場合にのみ実行されます。この場合、優先順位付けに焦点を当てます。優先順位は、問題が発生する可能性と、問題が発生した場合の深刻度によって定義されます。この第2ステップは、第1ステップほど厳密ではありませんが、完全なコンテキストが不足している場合のユーザー制御変数など、主観的な評価にも依存します。
ほとんどのルールにおいて、これを合理的な数の「経験則」で要約できるため、推論モデルは過剰です。推論モデルは同様の精度を持つ傾向がありますが、コストが大幅に高くなります。
小規模な推論モデルが機能する理由
一部のルールは驚くほど複雑であり、非推論モデルではそれらを把握することが困難です。話す言葉一つ一つに全く同じ思考空間を使用すると想像してみてください。まず誰かが「1+1は何ですか?」と尋ね、次に同じ人が「26248 + 346237は何ですか?」と尋ねます。通常のモデルがさまざまな複雑さのレベルに苦労する一方で、推論モデルは、複雑な入力に対してより多くの「言葉」を使用し、より大きな問題をより小さく、より管理しやすいサブ問題に分解することで、それらを処理できます。
残念ながら、推論モデルはより多くのトークンを消費するため、一般的にコストも高くなります。しかし、推論モデルとして構造化されたモデルは、非推論モデルよりもモデルの小型化による影響を受けにくいです。より大きなモデルに向かう理由は2つあります。(1) より多くの知識を蓄積する能力があるためです(ただし、脆弱性のトリアージにおいては、多くの知識は必ずしも必要ではありません)。(2) より大きなモデルは、「言葉」あたりの精度がわずかに高い傾向があります。しかし、推論モデルはその推論構造のおかげで、間違いから回復することができます。そのため、より多くのトークンを消費するにもかかわらず、トークン使用量の増加を相殺するために、トークンあたりのコストが低い小規模モデルで運用することは、実際には実現可能です。
JavaScriptにおけるパストラバーサル
パストラバーサルは、トリアージが驚くほど複雑であるため、推論モデルが真価を発揮できるルールです。これは、エンドユーザーが意図されたディレクトリ外のファイルを読み書きできる脆弱性です。例えば、Google Driveがファイルシステム上で各ユーザー専用のフォルダを個別に持っていると想像してみてください。
Google Drive/userId1/
Google Drive/userId2/…次回、ご自身のファイルのいずれかをダウンロードしたい場合、ブラウザクライアントからGoogle DriveにGETリクエストを送信します。例えば、ファイル名として myDogEatingShoes.jpg。そのファイルが存在する場合、ダウンロードはすぐに開始されます。しかし、次のファイル名を試したらどうなるでしょうか。 ../userId2/mypasswords.txt。もしGoogle Driveがパストラバーサルからバックエンドを保護していなかった場合、別のユーザーの「mypasswords.txt」ファイルをダウンロードできる可能性があります。そのファイルが存在すればですが。
さまざまなパストラバーサル攻撃
パストラバーサルSASTの検出結果をトリアージするためには、何が脆弱であるか、あるいはそうでないかのさまざまなケースを理解する必要があります。まずは簡単なケースから始め、徐々に複雑さを増していきましょう。
パターン1: ‘../’
ここでの見過ごせない問題は「../」パターンです。「../」を含むファイルパスから読み書きした場合、意図したディレクトリから抜け出し、意図しない場所に読み書きする可能性があります。したがって、ファイルパスに「../」のチェックがなく、ファイルがクライアント側で指定されている場合、実際の脆弱性が存在します。最悪の場合、ハッカーがシステム上の認証情報を含むファイルを読み取ることができました。
パターン2: ‘..\’
「../」をチェックしたとします。しかし、コードがWindowsシステムで実行されている場合、再び問題が発生します。「..\」パターンでもパストラバーサルは依然として可能だからです。ここまでは順調です。チェックすべき2つの経験則はまだ管理可能ですよね?
パターン3: ‘..’
スラッシュの欠落がない、きれいで整ったパスを得るために、多くの人が次のような関数を使用します。 path.resolve() または path.join()。ここからが本番です。次のような状況を想像してみてください。
if (userControlledSubPath.includes(‘../’) || userControlledSubPath.includes(‘..\\’)|| filename.includes(‘../’) || filename.includes(‘..\\’))
{
throw new Error(‘Path traversal attempt detected);
}
const filepath = path.join(HARDCODED_BASE_PATH, userControlledSubPath, filename);
return fs.readFileSync(filepath);これはまだ脆弱性があることが判明しました。攻撃者が使用した場合、 userControlledSubPath === '..', その機能は path.join 依然として1つ上のディレクトリに移動するものとして解釈します。
しかし、の最後の引数は path.join() その攻撃に対して耐性があります。攻撃者が最後の引数に「..」を指定した場合、その path.join() 関数はファイルパスではなくディレクトリを返し、その結果、無効な読み書き操作が発生します。
パターン4: 「/*」
新しい例では、再びこのようなテストがありました。
if (filename.includes(‘..’))
{
throw new Error(‘Path traversal attempt detected);
}
const filepath = path.resolve(HARDCODED_BASE_PATH, filename);
return fs.readFileSync(filepath);これは安全に見えますよね?チェックは「..」、「../」、および「..\」のケースをカバーしており、洗練されています!しかし、これがまだ脆弱である驚くべき方法があります。ドラムロール…トrrrrrrrr…の引数が path.resolve() スラッシュで始まる場合、以前のすべての引数を無視します。そのため、攻撃者が filename = /etc/passwd のような操作を行うと、その path.resolve() はハードコードされたベースパスを無視し、に解決されます。 /etc/passwd恐ろしいですよね?末尾のスラッシュもチェックすべきでした。なお、を使用していれば path.join() 安全になっていたでしょう。
複雑さを理解する
チャールズ・チャップリンはかつて「シンプルであることは、単純なことではない」と言いました。これはここにも当てはまります。シンプルで効果的な修正策は存在しますが、まず考えられる攻撃ベクトルの範囲を理解する必要があります。パストラバーサルに対する最もシンプルで堅牢な修正策は、まずパスを解決し、それが意図されたベースパスでまだ始まっているかを確認することです。そのチェックを回避する方法はありません。
しかし、AutoTriageチームには、修正策を選択できるという贅沢はありません。不必要に顧客を誤検知で圧倒しないよう、代替ソリューションを安全としてマークできる必要があります。これまでにパストラバーサルの4つの異なる攻撃ベクトルを見てきましたが、それらにはすべて特定のチェックが伴います。これらの各攻撃ベクトルについて、LLMは、成功する攻撃を行うためのすべての要件を満たして発生する可能性があるか、または攻撃の可能性を排除できるかをチェックする必要があります。
ほとんどのルールで推論モデルがデフォルトではないにもかかわらず、JavaScriptのパストラバーサルにおいて、非推論モデルと比較して2倍の誤検知を安全にフィルタリングできます。これはノイズ削減にとって画期的なことです。

