16
20

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 5 years have passed since last update.

MySQL-python でパラメータの自動エスケープ

Last updated at Posted at 2016-12-23

まとめ

Python の MySQL-python (MySQLdb) モジュールを使ってクエリを構築するときは Cursor.execute(self, query, args=None) の説明にある placeholder を活用しよう。

query -- string, query to execute on server
args -- optional sequence or mapping, parameters to use with query.

Note: If args is a sequence, then %s must be used as the
parameter placeholder in the query. If a mapping is used,
%(key)s must be used as the placeholder.

テスト用のテーブル

テスト用に以下のようなテーブルを作っておく。

mysql> select * from testdb.person;
+------+--------+
| id   | name   |
+------+--------+
|    1 | foo    |
|    2 | bar    |
+------+--------+

悪い例

bad.py
import MySQLdb


def select(name):
    connection = MySQLdb.connect(db='testdb', user='testuser')
    cursor = connection.cursor()
    cursor.execute("select * from person where name='%s'" % name)
    print("[query]")
    print(cursor._last_executed)
    print("[result]")
    result = cursor.fetchall()
    for rec in result:
        print(rec)

select("foo") とすると、いい感じに動いているように見える。

[query]
select * from person where name='foo'
[result]
(1L, 'foo')

しかし、 select("foo' or name=name-- ") のようにすると

[query]
select * from person where name='foo' or name=name-- '
[result]
(1L, 'foo')
(2L, 'bar')

と SQL injection ができてしまう。

良い例

good.py
import MySQLdb


def select(name):
    connection = MySQLdb.connect(db='testdb', user='testuser')
    cursor = connection.cursor()
    cursor.execute("select * from person where name=%s", name)
    print("[query]")
    print(cursor._last_executed)
    print("[result]")
    result = cursor.fetchall()
    for rec in result:
        print(rec)

変えたのは cursor.execute() の引数の部分のみ。

select("foo") とすると、先程の例と同じように動作する。

[query]
select * from person where name='foo'
[result]
(1L, 'foo')

select("foo' or name=name-- ") としてもちゃんとエスケープしてくれる。

[query]
select * from person where name='foo\' or name=name-- '
[result]

参考文献

16
20
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
16
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?