5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

sqlite3でPython変数を正しくバインドする方法

Last updated at Posted at 2022-06-17

記事の内容はあくまで個人の考えに基づくものであり、組織を代表するものではありません。

sqlite3を使って開発をする中で、よろしくない方法でPython変数をバインドしていた。
社内のコードレビューでご指摘いただき、事前に気づくことができた。
備忘も兼ねてまとめておく。

アンチパターン

もともと下記のような方法でPython変数をバインドしていた。

import sqlite3

name = "test user"
age = 20

con = sqlite3.connect('example.db')
cur = con.cursor()
cur.execute("create table user(id integer primary key autoincrement, name text, age integer);")
cur.execute("insert into user(name, age) values('{}', {});".format(name, age))
con.commit()
con.close()

上記方法でも、エラーなく動作はする。

しかし、下記の通り、Pythonの文字列操作でクエリを組み立てる方法は、SQLインジェクション攻撃に対して脆弱であると公式ドキュメントで説明されている。

SQL operations usually need to use values from Python variables. However, beware of using Python's string operations to assemble queries, as they are vulnerable to SQL injection attacks

SQLインジェクション(英: SQL injection)とは、アプリケーションのセキュリティ上の不備を意図的に利用し、アプリケーションが想定しないSQL文を実行させることにより、データベースシステムを不正に操作する攻撃方法のこと。また、その攻撃を可能とする脆弱性のことである。wikipediaより

正しい方法

公式ドキュメントに記載されている方法は2パターンある。

パターン1: qmark style

  • SQLの値を挿入する箇所に?を配置する
  • cursorのexecute()メソッドの第二引数に?の数と同じ要素数のタプルを渡す
  • ?の数とタプルの要素数が一致しない場合、ProgrammingErrorが発生する
cur.execute("insert into user(name, age) values(?, ?);", (name, age))

パターン2: named style

  • SQLの値を挿入する箇所に名前付きパラメータ(:任意の名前を組み合わせたもの)を指定する
  • cursorのexecute()メソッドの第二引数に名前付きパラメータ全てのキーを持つdictを渡す
  • 名前付きパラメータがdictのキーに含まれない場合ProgrammingErrorが発生し、余分なキーについては無視される
cur.execute("insert into user(name, age) values(:name, :age);", {"name": name, "age": age})
5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?