説明
未検証の入力で接続先のカタログを選ぶと、アプリケーションが意図しないデータ領域を操作する可能性があります。java.sql.Connection.setCatalog()の対応状況と動作はドライバーによって異なります。カタログの変更自体でデータベースアカウントの権限が上がるわけではありませんが、そのアカウントが扱える別のデータを誤って読み書きするおそれがあります。
想定される影響
- 意図しないデータ操作: 別のデータベースのデータを取得・変更する可能性があります。
- サービスの中断: 存在しないデータベースを選ぶと、処理に失敗するおそれがあります。
- アクセス境界の破綻: アカウントが複数のカタログにアクセスできる場合、ユーザーやテナント間のデータ分離が崩れる可能性があります。
対処方法
- データベース設定には、アプリケーションが管理する値を使ってください。
- サーバー管理の許可リストから選び、現在のユーザーがそのカタログへアクセスできることも確認してください。
- 動的な選択が不要なら接続設定を固定してください。必要な場合は要求ごとの権限と接続プールの状態初期化を確認し、次の要求に設定を残さないでください。
例
Java 9以降とjavax.servlet APIを使う抜粋です。例の許可リストは、すべての呼び出し元が両カタログを利用できる前提です。ユーザーごとに権限が異なる場合は、別途認可を確認してください。
変更前
java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.servlet.http.HttpServletRequest;
public class UnsafeDatabaseConfig {
public void setDatabase(HttpServletRequest request, Connection connection) throws SQLException {
String catalog = request.getParameter("db"); // 入力を直接使用
connection.setCatalog(catalog);
}
}
変更後
java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
public class SafeDatabaseConfig {
private static final Set<String> ALLOWED_CATALOGS = Set.of("main_db", "backup_db");
public void setDatabase(HttpServletRequest request, Connection connection) throws SQLException {
String catalog = request.getParameter("db");
if (catalog == null || !ALLOWED_CATALOGS.contains(catalog)) {
throw new SecurityException("Invalid database selection");
}
connection.setCatalog(catalog);
}
}
説明:
- 変更前: 入力をそのまま
setCatalog()へ渡し、ドライバーとアカウントが許す範囲で意図しないカタログを選択できる状態です。 - 変更後:
ALLOWED_CATALOGSを定義し、nullではなく、その集合に含まれる値にだけsetCatalog()を実行します。