SV.PATH
パスおよびファイル名の挿入
このエラーは、システムの操作やファイルの読み取り/作成を行うメソッドにおいて、ファイル名やパス名に未検証データまたは汚染データが直接使用されている状況を検出します。攻撃者がファイル区切り文字と相対パス名を使用して、アクセスを許可されていないファイルを読み取る可能性があります。
リリース 2023.2 の時点で、このチェッカーは Jakarta EE をサポートしています。
リリース 2026.3 以降、このチェッカーは LLM 応答テキストも信頼できないソースとして扱います。
脆弱性とリスク
一般に、アプリケーション内でのホストシステム上のファイルのアクセスや作成は、セキュリティ上の懸念事項となります。実行に使用されるファイルまたはパス文字列の一部に未チェックのユーザー入力が使用される場合には、セキュリティ脆弱性があります。攻撃者がファイルやパスを操作して、ホストシステム上でデータの作成やアクセスを行う可能性があります。代表的な攻撃は、ファイル名を操作して、ホストシステムから /etc/passwd ファイルにアクセスするものです。一般に、パス挿入はホストサーバー上のファイルシステムのセキュリティに危険をもたらす可能性があります。
Klocwork セキュリティ脆弱性 (SV) チェッカーは、潜在的に危険なデータを生成する呼び出しを特定します。このような呼び出しは安全でないソースと考えられます。ユーザーは攻撃者になる可能性があり、ヒューマンエラーを取り込む可能性があるため、安全でないソースはユーザーが指定した任意のデータである可能性があります。
軽減と防止
ユーザー入力からのパス挿入攻撃は、アプリケーションの外部からのあらゆる入力 (ユーザー入力、ファイル入力、システムパラメーターなど) を検証することで防止できます。検証には、長さと内容を含める必要があります。通常、英数字文字 (A ~ Z、a ~ z、0 ~ 9) のみが必要とされます。受け取ったその他の文字はすべてエスケープする必要があります。この検証は、各パラメーターを HTTP 要求から読み取った場合などに、データのソースごとに実行する必要があります。
脆弱コード例 1
import javax.servlet.http.*;
public void processUserProfile(ServletRequest req) throws IOException {
// Source of data from HTTP request in servlet
String userName = req.getParameter("userName");
String profile = profileDir + File.separator + userName;
BufferedReader reader = new BufferedReader(new FileReader(profile));
try {
//...
} finally {
reader.close();
}
}
Klocwork は、6 行目で SV.PATH の欠陥を報告し、次を示します。'userName' には HTTP 要求パラメーターからのデータが含まれているため、汚染される可能性があります (5 行目)。この値は定数文字列と連結され、6 行目で 'profile' に保存されます。7 行目で、'profile' はローカルファイルシステム内のファイルにアクセスするために使用されます。ファイルおよびパス名は、重要な情報を開示するように操作されたり、アプリケーション動作の変更に使用される可能性があります。
脆弱コード例 2
import jakarta.servlet.http.*;
public void processUserProfile(ServletRequest req) throws IOException {
// Source of data from HTTP request in servlet
String userName = req.getParameter("userName");
String profile = profileDir + File.separator + userName;
BufferedReader reader = new BufferedReader(new FileReader(profile));
try {
//...
} finally {
reader.close();
}
}
Klocwork は、6 行目で SV.PATH の欠陥を報告し、次を示します。'userName' には HTTP 要求パラメーターからのデータが含まれているため、汚染される可能性があります (5 行目)。この値は定数文字列と連結され、6 行目で 'profile' に保存されます。7 行目で、'profile' はローカルファイルシステム内のファイルにアクセスするために使用されます。ファイルおよびパス名は、重要な情報を開示するように操作されたり、アプリケーション動作の変更に使用される可能性があります。
脆弱コード例 3
import dev.langchain4j.model.chat.ChatModel;
import java.io.FileInputStream;
import java.io.IOException;
public class Example {
public FileInputStream run(ChatModel model) throws IOException {
String path = model.chat("Which file holds the config?"); // untrusted LLM output
return new FileInputStream(path); // opens a model-supplied path
}
}
LLM 出力がファイルパスとして直接使用されているため、Klocwork は 7 行目で SV.PATH の欠陥を報告しています。
修正コード例 3
import dev.langchain4j.model.chat.ChatModel;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
public class Example {
public FileInputStream run(ChatModel model) throws IOException {
String name = model.chat("Which file holds the config?");
Path base = Path.of("/srv/config").toRealPath();
Path resolved = base.resolve(name).normalize();
if (!resolved.startsWith(base)) { // reject traversal outside the base directory
throw new SecurityException("path outside allowed directory");
}
return new FileInputStream(resolved.toFile());
}
}
この修正例では、モデルの提供するパスが許可されたベースディレクトリを基準に解決され、そのディレクトリから外れた場合は拒否されるため、Klocwork は SV.PATH の欠陥を報告しなくなります。
外部参考資料
セキュリティトレーニング
Secure Code Warrior が提供しているアプリケーションセキュリティトレーニング教材。
拡張機能
このチェッカーは、Klocwork knowledge base (ナレッジベース) を利用して拡張できます。詳細については、Java 解析のチューニングを参照してください。