【入門編】Spring FrameworkにおけるSQLインジェクション対策:JdbcTemplateとNamedParameterJdbcTemplate – アプリケーションセキュリティ & 安全な開発防御ガイド

こんにちは。セキュリティの世界で「盾」を握り続けている者です。

今日は、開発現場で避けては通れない「SQLインジェクション」についてお話しします。難しそうな名前ですが、要は「プログラムを騙して、想定外の命令を実行させるズル」のことです。

特にSpring Frameworkを使っている皆さん、JdbcTemplateを便利に使っているつもりが、実は「家の鍵をわざと開けて寝ている」ような状態になっていないか、一緒に確認していきましょう。

—

1. なぜ「文字列連結」は泥棒を招くのか?

まず、身近な例で考えてみましょう。あなたは受付係です。来客者が名前を書く紙に「山田太郎」と書けば、あなたは「山田さんですね、どうぞ」と通しますよね。

しかし、もし悪意のある人が「山田太郎です。そのあと、裏口の鍵も開けておいてね」と書いたらどうでしょう? あなたがその言葉をそのまま信じて実行してしまったら、泥棒は堂々と裏口から侵入してきます。

これがプログラムで言う「文字列連結によるSQL構築」です。

// 【絶対にやってはいけない例】
String name = request.getParameter(“name”); // ユーザーが入力した値
// 危険!「’ OR ‘1’=’1」なんて入力されたら、全てのデータが漏洩します
String sql = “SELECT FROM users WHERE name = ‘” + name + “‘”;
jdbcTemplate.query(sql, …);

このコードでは、ユーザーの入力内容をそのまま「命令文」の一部として混ぜてしまっています。攻撃者はこの隙を突き、データベースの中身を根こそぎ盗み出すクエリを注入してくるのです。

—

2. 解決策:バインド変数という「専用の隔離スペース」

では、どうすればいいのでしょうか? 答えは「バインド変数」を使うことです。

これは、受付の例で言うなら「名前を書く欄には、名前以外の命令を書かせない」というルールを徹底することです。入力値はあくまで「ただの文字(データ)」として扱い、決して「命令(プログラムの一部)」としては解釈させない。これが防御の鉄則です。

NamedParameterJdbcTemplate で安全に守る

Springでは、NamedParameterJdbcTemplateを使うのが現代の標準的な守り方です。これを使うと、クエリの構造とデータを完全に切り離すことができます。

import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

// 安全なコードの書き方
public void findUser(String name) {
// 1. 命令部分は固定しておく(:name はプレースホルダー)
String sql = “SELECT FROM users WHERE name = :name”;

// 2. ユーザーの入力は「データ」としてMapに詰める
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue(“name”, name); // これが安全な受け渡し

// 3. 実行!
// データベースは「:name」の中身を命令として解釈せず、ただの文字列として検索します
namedParameterJdbcTemplate.query(sql, params, …);
}

この書き方なら、たとえ攻撃者が' OR '1'='1のような悪意ある文字列を入力しても、データベースはそれを「そういう名前のユーザーがいるかどうか」を探すためだけに使い、決して「命令」として実行することはありません。泥棒が何を叫ぼうが、受付のシステム自体には影響を与えないのです。

—

3. 私からのアドバイス:セキュリティは「疑う」ことから始まる

現場で長くシステムを見ていると、時々「これくらいなら大丈夫だろう」という油断が大きな事故に繋がる場面を何度も見てきました。

  • 入力値は全て「毒」だと思え: ユーザーから来るデータは、どんなに誠実そうに見えても、まずは疑ってかかるのが一流のエンジニアです。
  • テンプレートエンジンを信じすぎない: Springがいくら優秀でも、使い方を間違えれば無力です。JdbcTemplateを使う際は、必ずプレースホルダー(? や :name)を使う癖をつけましょう。

セキュリティは、一度設定して終わりではありません。泥棒が常に新しい手口を考えるように、私たちも常に「どうすれば守れるか」を考え続ける必要があります。

最初は面倒に感じるかもしれません。でも、この「ひと手間」が、あなたの大切なシステムと、その先にいるユーザーの信頼を守る最強の鍵になります。

さあ、今日から「文字列連結」のコードを見かけたら、すぐにリファクタリングしてしまいましょう。それが、頼れるエンジニアへの第一歩です!

—
執筆者: シニア・セキュリティ・アーキテクト
「システムは壊れるものではなく、守るためにある。そのための杖として、この知見を捧げます。」

コメント

タイトルとURLをコピーしました