質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

エスケープ処理

エスケープ処理とは、一連の文字や一文字に対して、一定の規則に従って別の意味を適用する処理過程です。

Q&A

3回答

740閲覧

【Java】Shift_JIS環境でのSQLエスケープライブラリ

terepoteto

総合スコア6

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

エスケープ処理

エスケープ処理とは、一連の文字や一文字に対して、一定の規則に従って別の意味を適用する処理過程です。

0グッド

3クリップ

投稿2018/03/15 19:14

編集2018/03/19 16:58

ヘディングのテキスト### 前提・実現したいこと

Java8(Spring4.3)で作られたWebアプリでブラインドSQLインジェクション対策をしようと考えています。

発生している問題・エラーメッセージ

JavaにはShift_JIS環境でも安全にSQLをエスケープできるライブラリは無いのでしょうか。
PHPでいうpg_escape_stringのようなものを探しています。

該当のソースコード

Java

1Int cnt = 0; 2StringBuffer buff = new StringBuffer(); 3 4buff.append("select columnA, columnB, columnC, ・(中略)・ from FooTable"); 5 6If(CanGetParamA){ 7  If(cnt = 0){ 8    buff.append("Where ColumnA = '"); 9    buff.append(paramA); 10    buff.append("'"); 11  }else{ 12    buff.append("and ColumnA = '"); 13    buff.append(paramA); 14    buff.append("'"); 15  } 16} 17 18If(CanGetParamB){ 19  If(cnt = 0){ 20    buff.append("Where ColumnB = '"); 21    buff.append(ParamB); 22    buff.append("'"); 23  }else{ 24    buff.append("and ColumnB = '"); 25    buff.append(ParamB); 26    buff.append("'"); 27  } 28} 29 30If(CanGetParamC){ 31  If(cnt = 0){ 32    buff.append("Where ColumnC = '"); 33    buff.append(ParamC); 34    buff.append("'"); 35  }else{ 36    buff.append("and ColumnC = '"); 37    buff.append(ParamC); 38    buff.append("'"); 39  } 40} 41 42(以下同じ条件式が続き中略) 43 44If(CanGetParamH){ 45    buff.append("order by '"); 46    buff.append(ParamH); 47    buff.append("'"); 48  } 49} 50 51buff.append(";"); 52String sql = buff.toString(); 53ResultSet rs = stmt.executeQuery(sql); //コネクション作成及びステートメント作成は略

試したこと

・ライブラリ調査(途上)
・以下の置換を行う自作メソッド作成(5c問題に対応できず断念)
' ⇒ ''
\ ⇒ 
; ⇒ ;
% ⇒ %
_ ⇒ _

補足情報(FW/ツールのバージョンなど)

RDBMSはOracle12cです。
尚、古い携帯にも対応させる為、文字コードはShift_JISから変更できず
内部でUTF-8、出力時にShift_JISといった変換もできません。

当初プレイスホルダの使用(StatementクラスからPreparedStatementクラスへの変更、
setStringやsetIntメソッドの使用)を提案しましたが、
改修コスト及びテストコストより却下され、サニタイズのみで対応する事となりました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/03/21 00:17

拒否されたことを全部洗いざらい書いてください。
guest

回答3

0

客先との機密保持契約により公開できません。

その場合、再現コードを作成してください。

特に記述がないので hibernate の前提で

HQL ( FROM User WHERE id = :name )

エスケープはORMが対応するため発生しません。

HQL ( FROM User WHERE id = [input var] ) // String append

エスケープはコーダーが対応するため発生する可能性があります。

SQL ( SELECT u.* FROM User u WHERE u.id = :name )

エスケープはORMが対応するため発生しません。

SQL ( SELECT u.* FROM User u WHERE u.id = ? )

エスケープはORMが対応するため発生しません。

SQL ( SELECT u.* FROM User u WHERE u.id = [input var] ) // String append

エスケープはコーダーが対応するため発生する可能性があります。

のように HQL/SQL ともに バインド変数を利用すれば発生しません。
もし特定のワードで発生する場合はそのバージョンの不具合ですのでバージョンアップをしましょう。

投稿2018/03/15 21:56

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

terepoteto

2018/03/19 16:55

hibernateをはじめとしたO/Rマッパーは一切使っていません。 また改修コスト及びテストコスト的にO/Rマッパー導入は難しいと思われます。 (PreparedStatementすら拒否されるレベルなので)
mpyw

2018/03/19 18:48 編集

本当に会社やめましょうっていうレベルのひどい案件ですね…ここまで理不尽なコードとそれに全く見合わない見当はずれな要求初めて見ました ・ORMを使わずに ・クライアント側サーバ側ともに正しい文字コードをセットして ・RDBMSネイティブの本物のプリペアドステートメントを使う これが最も現実的な解だと思いませんか?それを拒否するというのはなんかもう絶望にしか値しない…
mpyw

2018/03/19 18:55 編集

Web業界の人間でSIerのことはあまり知らないのですが,「下手に自分でエスケープ関数書くほうがセキュリティ面とか保守コスト面でのリスクになっちゃうよ」という主張さえすることは許されないんでしょうか。エスケープ関数を自分で書けばそれの念入りなテストが必要になるので,テストコストを理由にプリペアドステートメントの導入を渋るのは破綻してると思うんですが。
退会済みユーザー

退会済みユーザー

2018/03/19 23:21 編集

mpyw とあるエスケープ関数 をつくれば保守コストはかからんよ すべてのアスキー以外を \u0000 形式に変換するエスケープ処理なら改修コストは1回分 ーーー なにをいってるんだろう、テスト工数は同じですよ(SQL数はかわらない) 改修コストは 1.2 倍 (まともに組むなら 1.5倍)ぐらいになるかもしれませんが、(対象の文字列を洗い出す作業をコストに含めると同じになるが)
退会済みユーザー

退会済みユーザー

2018/03/19 23:13

ふと気づいた、utfが表示できない古いガラケーに対応するということは個人情報があってもhttp通信か(現在 HTTPS通信はほとんどの3G端末では利用できない)
mpyw

2018/03/20 03:46 編集

>> すべてのアスキー以外を \u0000 形式に変換するエスケープ処理なら改修コストは1回分 UNISTR https://docs.oracle.com/cd/E60665_01/db112/SQLRF/functions224.htm Oracle疎くて知らなかったのですが,こういうのがあるんですね。それなら納得です,失礼しました。(処理が煩雑になりそうなので「アスキー以外」という区別は要らないとは思いますが
mpyw

2018/03/20 03:48

>> ふと気づいた、utfが表示できない古いガラケーに対応するということは個人情報があってもhttp通信か(現在 HTTPS通信はほとんどの3G端末では利用できない) 御尤もです。多くのWebアプリケーションがガラケーサポート打ち切っているこのご時世に,危険なガラケーをサポートすることにどれだけの価値があるんでしょうかねえ…
mpyw

2018/03/20 04:17

(補足)MySQLでもCONVERT関数がありますね。RDBMS依存にはなりますが,一応幅広く使える方針にはなりそうです。
guest

0

JavaのUnicode文字列の変換用メソッド("あ" <-> "\u3042") - Qiita

を参考に

java

1public static String toUniStr(String original) 2{ 3 StringBuilder sb = new StringBuilder(); 4 sb.append("UNISTR('"); 5 for (int i = 0; i < original.length(); i++) { 6 sb.append(String.format("\%04X", Character.codePointAt(original, i))); 7 } 8 sb.append("')"); 9 return sb.toString(); 10}

とかですかね。

投稿2018/03/20 04:01

編集2018/03/20 17:43
mpyw

総合スコア5223

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/03/20 04:07

それそれ
mpyw

2018/03/20 04:12

本当にその場しのぎでしかないので極力使いたくないですけどね…w
mpyw

2018/03/20 17:44 編集

こちら "u" が不要であったため訂正しました。
guest

0

脳筋レベルの書き換えですが

diff

1If (CanGetParamA) { 2 If (cnt = 0){ 3- buff.append("Where ColumnA = '"); 4- buff.append(paramA); 5- buff.append("'"); 6+ buff.append("Where ColumnA = "); 7+ buff.append(StringUtil.toUniStr(paramA)); 8 } else { 9- buff.append("and ColumnA = '"); 10- buff.append(paramA); 11- buff.append("'"); 12+ buff.append("and ColumnA = "); 13+ buff.append(StringUtil.toUniStr(paramA)); 14 } 15}

一応こんな感じでとりあえずは凌げそう。

投稿2018/03/20 04:11

mpyw

総合スコア5223

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mpyw

2018/03/20 04:11

失礼しました,回答編集しようとしたら追加してしまった…
退会済みユーザー

退会済みユーザー

2018/03/20 04:46

つかw if / else ともに buff.append(StringUtil.toUniStr(paramA)); つかってるからまとめれるよw
mpyw

2018/03/20 10:18

※ 脳筋レベルの書き換え
mpyw

2018/03/20 10:21 編集

いやもうそんなこと言い出したらこれ全部書き換えたいですよwwJava5以降でStringBufferとか見えてる時点でお察し
terepoteto

2018/03/20 16:03

すみませんが文字コード変換は文字化け防止の為禁止されていて「UNISTR」は使えません。 そもそもDBもShift_JISなので。 またDAOのSQL文を書き換えるのは改修&テストコスト的に拒否されています。 同様の理由で代替引用メカニズム「q」を使ったDAOのSQL文の書き換えもNGを出されました。
mpyw

2018/03/20 18:06 編集

>> すみませんが文字コード変換は文字化け防止の為禁止されていて「UNISTR」は使えません。そもそもDBもShift_JISなので。 (Unicodeという解釈では)文字コード変換ではありません。Unicodeコードポイント表記は文字コードに依存しない表記法です。UTF-*は文字コードですがUnicodeは単なる文字集合です。文脈次第でUTF-32と等価である文字コードと言えなくもないですが,それでも全ての文字コードのスーパーセットであるため,文字化けは絶対にしません。 (UTF-8でも,UNISTRの場当たり的手法は使えませんが,アプリケーション全体で改修する場合は文字化けの心配は一切要りません) UNISTR https://docs.oracle.com/cd/E60665_01/db112/SQLRF/functions224.htm マニュアルを見てもらえると分かると思いますが,DBがどんなキャラクタセットであろうと使えます。
退会済みユーザー

退会済みユーザー

2018/03/21 00:21

制限事項のオンパレードだな・・・・デスマがんば・・・
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問