JavaのSQLインジェクションとは?文字列連結でSQLを書く危険性

最終更新日

Schoo Java入門 中級 第2回 データベース処理とオブジェクト設計

本記事は、Schooの「Java入門 中級【2026年版】」第2回「データベース処理とオブジェクト設計の基礎」を学ぶ前後に、SQLインジェクションの基本を整理したい方向けの記事です。

SQLインジェクションは、利用者が入力した文字が、検索キーワードではなくSQLの一部として解釈されてしまう問題です。JDBCを使うときは、文字列連結でSQLを組み立てる危険性を理解しておく必要があります。

Schoo コースページ:Java入門 中級【2026年版】

SQLインジェクションは入力によってSQLの意味が変わる問題

たとえば、曲名で検索するプログラムを考えます。利用者が入力した文字を keyword に入れ、その値をSQLに直接つなげると、次のようなコードになります。

String sql = "SELECT id, title, artist FROM songs WHERE title = '" + keyword + "'";

普通に曲名を入力するだけなら、問題が見えにくいかもしれません。しかし、入力欄にSQLとして意味を持つ文字が入ると、プログラムが作るSQLの意味が変わってしまいます。

図解:入力文字がSQLの条件を変えてしまう
Javaで文字列連結してSQLを作る
“SELECT … WHERE title = ‘” + keyword + “‘”
利用者が次の文字を入力する
‘ OR ‘1’=’1
SQLとして読むと、条件の意味が変わる
WHERE title = ” OR ‘1’=’1′
後半の '1'='1' は常に成り立つため、意図しない行まで対象になる可能性があります。
SQLインジェクションは、入力文字が「ただの検索キーワード」ではなく、SQLの一部として解釈されてしまう問題です。

なぜ全件表示のようなことが起きるのか

攻撃用の文字列を覚える必要はありません。大切なのは、文字列連結でSQLを作ると、入力された引用符や条件式までSQLの一部として読まれてしまう、という点です。

OR は「または」を表します。条件の中に「常に成り立つ条件」が混ざると、本来は1件だけを探すつもりでも、意図しない行まで検索対象になる可能性があります。

つまり、SQLインジェクションは「変な文字を入れるとエラーになる」というだけの話ではありません。入力値によって、検索・更新・削除の対象が変わってしまう可能性がある問題です。

PreparedStatementでは入力値をSQLの命令として扱わない

SQLインジェクションを避ける基本は、SQL文と入力値を分けることです。JDBCでは PreparedStatement を使います。

String sql = "SELECT id, title, artist FROM songs WHERE title = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, keyword);
ResultSet rs = pstmt.executeQuery();
図解:文字列連結とPreparedStatementの違い
文字列連結
title = ‘” + keyword + “‘
入力値がSQL文の中に直接入るため、記号もSQLの一部として読まれます。
PreparedStatement
title = ?
pstmt.setString(1, keyword);
入力値はSQLの命令ではなく、検索に使う値として渡されます。
PreparedStatementは、SQLの形と入力値を分けることで、入力値にSQLの意味を持たせないようにします。

? は、あとから値を入れる場所です。pstmt.setString(1, keyword) と書くことで、1番目の ?keyword の値を渡します。

この書き方では、入力値をSQL文そのものとしてつなぎません。そのため、入力欄に引用符や OR のような文字が含まれていても、それはSQLの命令ではなく、検索に使う文字列として扱われます。

初学者がまず避けたい書き方

JDBCで利用者の入力を扱うとき、次のようにSQLと入力値を + でつなぐ書き方は避けます。

String sql = "SELECT id, title, artist FROM songs WHERE title = '" + keyword + "'";

代わりに、SQLの中で値が入る場所を ? にして、setString などで値を渡します。

String sql = "SELECT id, title, artist FROM songs WHERE title = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, keyword);

確認問題

次のコードには、利用者の入力をSQLに直接つなげている箇所があります。

String keyword = scanner.nextLine();
String sql = "SELECT id, title, artist FROM songs WHERE title = '" + keyword + "'";
  1. この書き方が危険な理由を説明してください。
  2. PreparedStatement を使う形に書き換えてください。

確認問題の回答例を見る

まとめ

  • SQLインジェクションは、入力値がSQLの意味を変えてしまう問題
  • 文字列連結でSQLを作ると、入力された記号や条件式までSQLとして読まれる可能性がある
  • JDBCでは PreparedStatement を使い、SQLの形と値を分けて扱う
  • 利用者の入力をSQLに直接つなげないことが基本

関連する記事

シェアする