本文介紹了為什么PyMySQL不容易受到SQL注入攻擊?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我不熟悉PyMySQL,剛剛嘗試執行查詢:
c.execute('''INSERT INTO mysql_test1 (
data,
duration,
audio,
comments
) VALUES (
?,
?,
?,
?
);
''', [
comments_var,
duration_var,
audio_var,
comments_var
]
);
但是,它引發了以下錯誤:
TypeError: not all arguments converted during string formatting
我注意到我的變量一定有問題,并閱讀了如何在PyMySQL中正確處理它們,期望使用參數替換方法,但令我驚訝的是,我什么也找不到。相反,我發現的每個線程都使用字符串操作(例如here、here、here和here(有一條注釋聲稱字符串操作將是PyMySQL的標準操作)。
這對我來說很有趣,因為我以前只處理過SQLite,其中DBAPI文檔explicitly warns使用帶有變量的字符串操作:
SQL操作通常需要使用來自Python變量的值。但是,請注意不要使用Python的字符串操作來組合查詢,因為它們容易受到SQL注入攻擊。
文檔通過以下代碼片段舉例說明了這一點:
Never do this -- insecure!
symbol = 'RHAT'
cur.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)
Instead, use the DB-API’s parameter substitution.
當我閱讀PyMySQL docs時,我找不到任何關于這種危險的提法。它只是證實了我之前的發現:
如果args是列表或元組,則%s可以用作查詢中的占位符。如果args是詞典,則%(Name)s可以用作查詢中的占位符。
為什么在sqlite3
中使用字符串操作容易受到SQL注入攻擊,而在pymysql
中卻沒有受到質疑?
推薦答案
很遺憾,pymysql的設計者選擇使用%s
作為參數占位符。它讓許多開發人員感到困惑,因為它與字符串格式化函數中使用的%s
相同。但它在pymysql中做的不是同樣的事情。
它不僅僅是進行簡單的字符串替換。Pymysql將對值應用轉義,然后再將它們插入到SQL查詢中。這可防止特殊字符更改SQL查詢的語法。
事實上,pymysql也會給您帶來麻煩。以下是不安全的:
cur.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)
因為它在將變量symbol
作為參數傳遞給execute()
之前將其插入到字符串中。然后,唯一的參數是帶有格式化變量的已完成的SQL字符串。
鑒于這是安全的:
cur.execute("SELECT * FROM stocks WHERE symbol = %s", (symbol,))
因為它傳遞由symbol
變量組成的列表作為第二個參數。execute()
函數中的代碼將轉義應用于列表中的每個元素,并將結果值插入到SQL查詢字符串中。注意%s
不是用單引號分隔的。execute()
的代碼負責這一點。
這篇關于為什么PyMySQL不容易受到SQL注入攻擊?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,