1

このプロジェクトでは、次のようなテーブル RESULTS を含むデータベース ファイルがあります。

conn.execute('''CREATE TABLE RESULTS(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age TEXT NOT NULL,
gender TEXT NOT NULL);''')

これは、ユーザーがデータベース内のデータにアクセスできるように、フロント エンドのプロトタイプを作成するために使用しているファイルです。

#setting up the user input variables
srcIn = input("what field do you want to search: id, name, age, or gender? ")
srcQuery = input("what result do you want to find from the "+ srcIn + " search? ")
if(srcIn == "age") or (srcIn == "id"):
    #by default input returns a string but it needs to be an int for age and id parameters
    srcQuery = int(srcQuery)
    print("converted to int")
srcOut = input("what field do you want to return: id, name, age, or gender? ")

print("making cursor")
cursor = conn.execute("SELECT %s FROM RESULTS WHERE %s = %s" % (srcOut, srcIn, srcQuery))
for row in cursor:
    print(srcOut + ": " + row[0])

conn.close()
print("closed database " + db)

これを実行して年齢または ID、数字の 45、および名前を渡すと、名前、性別、およびその他の統計情報がデータベースから完全に返されます。ただし、性別、女性または男性を渡し、名前または年齢または ID を返すと、次のようなエラーがポップアップ表示されます。

cursor = conn.execute("SELECT %s FROM RESULTS WHERE %s = %s" % (srcOut, srcIn, srcQuery))
sqlite3.OperationalError: no such column: male

この特定の例では:

srcOut = name
srcIn = gender
srcQuery = male

%s を ? に置き換えてみました。引数 (SELECT ステートメントに渡すパラメーターでは機能しないことはわかっています) であるため、困惑しています。

特定のインスタンスでは整数を srcQuery フィールドに渡し、他のインスタンスでは文字列を渡しているという事実と関係があると思います。

ヘルプや提案をいただければ幸いです。

4

1 に答える 1

2

いいえ、@Suever が提案した方法で行うべきではありません

次の値を指定すると、どのようなクエリが実行されるか想像してみてください。

srcOut = "name"
srcIn = "gender"
srcQuery = "' or 1 = 1 -- "

あなたのコードは実際に実行されます:

SELECT 
    name 
FROM 
    RESULTS 
WHERE  
    gender = '' or 1 = 1 -- '

これは、テーブル内のすべての行に一致します。

または、言い換えると、検証とエスケープがなく、特定の入力を準備することによって、すべての結果をテーブルに取得していますが、これはもちろん、現実の世界では起こりたくないことです. これは、SQL インジェクション攻撃と呼ばれます。

文字列の書式設定ではなく、クエリをパラメーター化する必要があります。ただし、クエリのパラメーター化は、テーブル名と列名では機能しません 。これらはクエリに挿入する前に検証する必要があります。 と の可能な値の量scrInsrcOut非常に限られているためです。予期しない値が表示された場合は、単にエラーをスローします。 、例:

columns = {'id', 'name', 'age', 'gender'} 
srcIn = input("what field do you want to search: id, name, age, or gender? ")
if srcIn not in columns:
    raise ValueError("Invalid srcIn value")

-これについては、パラメータ化srcQueryする必要があります:

query = "SELECT {column_out} FROM RESULTS WHERE {column_in} = ?".format(column_out=srcOut, column_in=scrIn)
cursor = conn.execute(query, (srcQuery, ))

はるかに安全であるだけでなく、これにより、python からデータベースへの型変換と引用符について考える問題も解消されます。データベース ドライバーはそれを自動的に処理します。

于 2016-12-10T04:15:03.793 に答える