web-dev-qa-db-ja.com

Python MySQLに接続してクエリを実行するためのベストプラクティスおよび最も安全な方法

Mysqlでクエリを実行する最も安全な方法は何ですか、MySQLとSQLインジェクションに伴う危険性を認識しています。

ただし、他のユーザー(Webクライアント)が操作できる変数へのインジェクションを防ぐためにクエリを実行する方法がわかりません。以前は独自のエスケープ関数を作成していましたが、明らかに「未完了」です。

Mysqlインジェクションを危険にさらすことなく、pythonを使用してMySQLデータベースでクエリを実行し、安全に挿入するために、何を使用し、どのように使用する必要がありますか?

54
Lucas Kauffman

インジェクションを回避するには、各変数の代わりに%sexecuteを使用し、リストまたはTupleを介してexecuteの2番目のパラメーターとして値を渡します。 ドキュメントの例 は次のとおりです。

c=db.cursor()
max_price=5
c.execute("""SELECT spam, eggs, sausage FROM breakfast
          WHERE price < %s""", (max_price,))

これはcommaを使用しており、(これはエスケープされていない、直接の文字列置換)。 これをしないでください

c.execute("""SELECT spam, eggs, sausage FROM breakfast
          WHERE price < %s""" % (max_price,))

また、パラメーターが文字列の場合、位置ホルダー('%s')を引用符で囲む必要はありません。

78
Bruno

ブルーノの答えの拡張として、MySQLクライアントライブラリは、名前付きパラメーターを指定するためのいくつかの異なる形式のいずれかをサポートする場合があります。 PEP 249(DB-API) から、次のようなクエリを作成できます。

「qmark」

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = ?", (lumberjack,))

「数値」

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = :1", (lumberjack,))

「名前付き」

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = :jack", {'jack': lumberjack})

'フォーマット'

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = %s", (lumberjack,))

「pyformat」

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = %(jack)s", {'jack': lumberjack})

paramstyleモジュールレベル変数を見ると、クライアントライブラリがサポートしているものを確認できます。

>>> clientlibrary.paramstyle
'pyformat'

上記のオプションはいずれも、安全でない可能性のあるデータの処理に関して適切に実行する必要があります。ブルーノが指摘したように、パラメーターを自分で挿入しようとしないでください。一般的に使用されるクライアントライブラリは、単なる人間よりもデータの処理がはるかに優れています。

71
Kirk Strauser