初めまして。ゼネット新人の佐藤です。
現在私はJava、JDBC、PostgreSQLを使ったWEBアプリケーション研修をしています。
その際にSQLインジェクションの脆弱性がある危険なコードを書いてしまったことがあります。
そのため、今回は知らず知らずのうちに危険なコーディングをしないように、JavaでできるSQLインジェクションの対策方法について解説していこうと思います。
PreparedStatementの使用
JavaでできるSQLインジェクション対策の一つに、PreparedStatementのプレースホルダを使用したエスケープ処理が挙げられます。
プレースホルダとは?
後から実際に扱う値を入れる前に、一時的に場所を確保するために入れられる仮の値のこと。
エスケープ処理とは?
特別な意味を持つ文字列を、無害な別の文字列に変換すること。
PreparedStatementを使用した対策例
例えば、ユーザーがWEBページの入力フォームにデータを入力し、その入力データもとにSQLを実行するコードがあるとします。
この入力フォームに悪意のあるユーザーが不正なSQL文を入力した場合でも、以下の例のようにPreparedStatementを用いて対策したコードであれば、入力されたSQL文が無害化され、SQLインジェクションの対策が可能です。
入力フォームに入力された悪意のあるSQL文の例
101; DROP TABLE テーブル名;
PreparedStatementを使用したJavaコードの例
//実行されるSQL文、プレースホルダ「?」を設定
String sql = "SELECT * FROM テーブル名 WHERE id = ?"
//入力された文字列
String str = "101; DROP TABLE テーブル名;";
//JDBCドライバの読み込み
Class.forName("org.postgresql.Driver");
//データベースへアクセスし接続情報を取得する
Connection connection = DriverManager.getConnection(DBのURL, ユーザID, パスワード);
//実行したいSQLからPreparedStatement型のSQL文を取得する
PreparedStatement pstatement = connection.prepareStatement(sql );
//「?」の部分に、String型の値にエスケープ処理した入力データを設定
pstatement.setString(1, str);
//SQL文の実行
pstatement.executeQuery();
上記のコードでは実行するSQL文にプレースホルダ「?」を設定しています。
PreparedStatementインターフェースのメソッドsetString()を使用し、入力データをエスケープ処理してからプレースホルダと置き換えることで、不正な入力データを無害化し、SQLインジェクションの対策が可能となります。
上記の対策を行った場合には、実行されるSQL文は以下のようになり、入力データが文字列として扱われ、SQL文として実行されることはなくなります。
SELECT * FROM テーブル名 WHERE id = '101; DROP TABLE テーブル名;'
仮にエスケープ処理を行わず、入力データを直接設定した場合には以下のようにSQL文が実行され、テーブルが削除される危険性があります。
SELECT * FROM テーブル名 WHERE id = 101;
DROP TABLE テーブル名;
まとめ
SQLインジェクションの仕組みと対策法を知らないと、意図せず脆弱性のあるコードを書いてしまう可能性があります。
ユーザーの入力値をもとにSQL文を実行するコードを書く際はSQLインジェクションの対策を忘れないようにしましょう。
最後までお読みいただきありがとうございました。少しでも参考になれば幸いです。