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