2

私は、私の個人的なプロジェクトの mysql データベースと関連するアカウントの作成を自動化するのに役立つ小さな python スクリプトを書いています。このスクリプトの一部は、データベース名を文字列として受け取り、データベースを作成する関数です。

def createDB(dbConn, dbName):
    import MySQLdb
    c = dbConn.cursor()
    query = """CREATE DATABASE %s;""";
    c.execute(query, (dbName,))

次のように、 MySQL の CREATE DATABASEが引用符で囲まれていないデータベースの名前を要求するため、これは機能しません。

  CREATE DATAbASE test_db

しかし、ユーザーが提供したデータベース名をクエリに安全に挿入しようとする私のコードは次を作成します:

  CREATE DATABASE 'test_db'

そして、「テストに近い MySQL 構文に問題があります」というメッセージが表示されます。

これは個人的な使用のためのものですが、ユーザーが提供した文字列をあらゆる種類のクエリに直接挿入したくありません。それは私の宗教に反しています。ユーザーが指定したデータベース名を python (または任意の言語) の mySQL クエリに挿入して、ユーザー入力test_db; DROP some_other_db;が拒否または正しくエスケープされることを確認する安全な方法はありますか?

4

2 に答える 2

5

データベース名(または列名やテーブル名)はデータ値ではないため、プレースホルダーの適切な使用法ではありません。これをしたいのは通常悪い兆候です。を発行できるのはDBAだけcreate databaseです。これを行うには、かなりの特権が必要になるためです。ほとんどのアプリケーションでは、DBAがデータベースの作成を発行し、作成されたデータベースをdbapi.Connectionの引数で使用されるパラメーターとして使用する必要があります。

これが必要であると確信し、入力のソースを信頼し、入力に無効な文字がないかチェックした場合は、Pythonで次のように置換するだけです。

def createDB(dbConn, dbName):
    c = dbConn.cursor()
    query = """CREATE DATABASE %s;""" % dbName
    c.execute(query)
于 2011-07-11T21:27:11.317 に答える
2

掘り下げた結果、phpmyadmin はバッククォートを使用してデータベース、テーブル、および列の名前を引用していることがわかりました。彼らは単に行います:

$sql_query = 'CREATE DATABASE ' . PMA_backquote($new_db);  

上記のエラーケースでは、次のようなものが得られます

CREATE DATABASE `test_db; DROP some_other_db`;

もちろん、入力文字列内のすべてのバックティックはエスケープする必要があります。これは、phpmyadmin のコードによると、単一のバックティックをすべて二重のバックティックに置き換えることによって行われます。これが正しいことを確認する場所が見つかりません。

バッククォートは標準SQLではないことにもオンラインで気付きました。

于 2011-07-12T14:19:03.320 に答える