プレースホルダと ORDER BY 句
Web アプリケーションの商品検索処理は,次の Java コードで SQL 文を組み立てて実行している。ここで,keyword と sort は HTTP リクエストのパラメタから取得した文字列である。このコードに関する記述として,適切なものはどれか。
String sql = "SELECT name, price FROM items WHERE name LIKE ? ORDER BY " + sort;
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, "%" + keyword + "%");
ResultSet rs = ps.executeQuery();- アPreparedStatement を用いているので,keyword と sort のどちらにどのような値が与えられても,SQL 文の構文は変わらない。
- イsort の値は文字列連結によって SQL 文の一部になるので,SQL インジェクションが可能である。並べ替えの列は,アプリケーションが定めた列名の中から選ぶ方式にする。
- ウkeyword の値に「'」が含まれると,setString で割り当てた値の途中で文字列リテラルが終わるので,SQL インジェクションが可能になる。
- エORDER BY 句も「ORDER BY ?」とし,setString で sort の値を割り当てれば,指定された列で並べ替えられ,安全になる。
正解と解説を見る
正解 イ
この問題の基礎知識
- SQL インジェクションは,入力値が SQL 文の一部として解釈され,SQL 文の構文が改変されてしまう脆弱性である。
- プレースホルダを用いると,SQL 文の構文を確定させた後に値を割り当てるので,割り当てた値はデータとして扱われ構文を変えない。保護されるのは ? に割り当てた値だけであり,文字列連結で組み込んだ部分は保護されない。
- プレースホルダが表せるのはデータの値であり,表名や列名,ASC や DESC などの構文要素は割り当てられない。これらを利用者の指定で変える場合は,アプリケーションが定めた候補から選ばせる。
アPreparedStatement を用いているので,keyword と sort のどちらにどのような値が与えられても,SQL 文の構文は変わらない。
プレースホルダで保護されるのは,? に割り当てた値だけである。sort は prepareStatement の前に文字列連結で SQL 文に組み込まれるので,その値によって SQL 文の構文が変わり得る。
イsort の値は文字列連結によって SQL 文の一部になるので,SQL インジェクションが可能である。並べ替えの列は,アプリケーションが定めた列名の中から選ぶ方式にする。正解
SQL 文の構文は連結後の文字列で確定するので,sort に SQL の断片を与えると構文を改変できる。列名はプレースホルダで扱えないので,利用者の選択をアプリケーションが定めた列名に対応付け,それ以外は拒否する。
ウkeyword の値に「'」が含まれると,setString で割り当てた値の途中で文字列リテラルが終わるので,SQL インジェクションが可能になる。
setString で割り当てた値は,SQL 文の構文が確定した後にデータとして扱われる。「'」を含んでいても文字列リテラルの終端として解釈されることはなく,構文は変わらない。
エORDER BY 句も「ORDER BY ?」とし,setString で sort の値を割り当てれば,指定された列で並べ替えられ,安全になる。
プレースホルダが表すのはデータの値であり,表名や列名,ASC や DESC などのキーワードは割り当てられない。sort の値は列名ではなく文字列の値として扱われるので,指定した列での並べ替えにはならない。
検証用の出典出典照合済み
OWASP SQL Injection Prevention Cheat Sheet / IPA 安全なウェブサイトの作り方照合の根拠(3 件)
- イ(正解)・ア(誤り)・ウ(誤り): バインドした値(keyword)はデータとして扱われるが,prepare の前に連結した sort は保護されない
Prepared statements treat bound values as data rather than SQL syntax . Concatenating untrusted values into the query before preparing it defeats this protection.
OWASP SQL Injection Prevention Cheat Sheet · Primary Defenses(新しいタブで開きます) - エ(誤り): プレースホルダは列名や ASC / DESC を表せない
Parameter markers represent data values, not table names, column names, or SQL keywords such as ASC and DESC ;
OWASP SQL Injection Prevention Cheat Sheet · Allow-List Input Validation(新しいタブで開きます) - イ(正解): 利用者の選択をアプリケーションが定めた値に対応付け,それ以外は拒否する
When users need to select among them, map their selection to a small set of application-owned tokens allowed for that query and reject unknown choices.
OWASP SQL Injection Prevention Cheat Sheet · Allow-List Input Validation(新しいタブで開きます)
コードの 1 行目で sort が prepareStatement の前に文字列連結されているので,sort の値で SQL 文の構文が変わり得る。keyword は setString でバインドされている。