状況
商品名の部分一致検索(Python の sqlite3)のレビュー。word は検索欄の入力で、SQL インジェクションになると指摘したところ、直し方の案が 4 つ出た。
直し方として正しいものは?
def search_items(conn, word): sql = f"SELECT * FROM items WHERE name LIKE '%{word}%'" return conn.execute(sql).fetchall()正答
- conn.execute("SELECT * FROM items WHERE name LIKE '%?%'", (word,))
- conn.execute("SELECT * FROM items WHERE name LIKE '%" + word + "%'")
- conn.execute("SELECT * FROM items WHERE name LIKE ?", (f"%{word}%",))
- conn.execute("SELECT * FROM items WHERE name LIKE '%' + ? + '%'", (word,))
解説
LIKE の部分一致でも、入力は ? で値として渡し、% は値の側に付ける。'%?%' のように引用符の中に書いた ? はただの文字でプレースホルダにならず、sqlite3 は「バインドする数が合わない」とエラーにする。+ で連結すると入力が SQL 文の一部になり、' を含む入力で条件を書き換えられる。SQLite の + は数値の足し算なので、'%' + ? + '%' は 0 になり、名前が 0 の行しか見つからない(文字列の連結は ||)。'%' || ? || '%' と書くのも正しい直し方。入力に含まれる % や _ はワイルドカードとして働くので、必要なら ESCAPE で扱う。
参考: cheatsheetseries.owasp.org
この問題を含む セキュリティ のテストを制限時間つきで解く
セキュリティクイズへ