2011-06-28 81 views
32

使用SQLAlchemy時緩解SQL注入攻擊的最佳做法是什麼?SQLAlchemy + SQL注入

+24

使用SQLAlchemy *是最佳實踐。 :-) –

回答

31

如果您有任何「特殊」字符(如分號或撇號 )的數據,他們將 自動被 SQLEngine對象引用你的,所以你不必 擔心引用。這也意味着 ,除非你刻意繞過 SQLAlchemy的引用機制, SQL注入攻擊基本上是 不可能的。

[每http://www.rmunn.com/sqlalchemy-tutorial/tutorial.html]

+16

答案表示引用來自「the」文檔,當它沒有時:它似乎來自[教程](http://www.rmunn.com/sqlalchemy-tutorial/tutorial.html )不與SQLAlchemy關聯。其次,引用是在正確處理轉義的SQLAlchemy API的一部分的上下文中,使用處理轉義的示例。但是,仍然可以使用'execute()'或其他不會被SQLAlchemy轉義的文字數據。是的,在大多數情況下,SQLAlchemy會自動轉義,但如果您使用的是文字或原始SQL,您仍然可以在腳下自我拍攝。 –

51

tldr:避免生SQL儘可能。

接受的答案是懶惰和不正確的。過濾器方法接受原始SQL,如果以這種方式使用,則完全容易受到SQL注入攻擊。舉例來說,如果你是從URL接受值和原始的SQL的過濾器結合起來,你是開放的攻擊:

session.query(MyClass).filter("foo={}".format(getArgs['val']))

使用上面的代碼和下面的網址,你會將SQL注入到過濾器語句中。上面的代碼將返回數據庫中的所有行。

http://domain.com/?val=2%20or%201%20=%201

+4

「,除非你故意繞過SQLAlchemy的引用機制...「是的,輸入原始的sql是故意繞過那個引用機制,所以不,上面的回答是沒有錯誤的 – Johnston

+12

我不同意你可以傳遞原始sql到過濾器方法是sqlalchemy的一部分,而不是一些結束破解...所以在這裏值得注意的是要注意的事情 – Mike

+2

如果我必須接受用戶輸入的過濾器,確保用戶沒有輸入原始SQL來刪除表或任何其他意外行爲的正確方法是什麼? –

3

爲了增加@Tendrid answer。我使用安靜的天真方法做了一些調查。 filter方法有*criterion作爲它的參數,其他幾個ORM查詢方法也有類似的說法。

filter方法的情況下*criterion參數結束傳遞到_literal_as_text,在字符串的情況下 - 將其標記爲安全的SQL(請糾正我,如果我錯了)。因此它使它不安全。

這裏是*criterion說法ORM Query class法調查的結果:可能的方法missuses

filter - uses _literal_as_text (NOT SAFE) 
having - uses _literal_as_text (NOT SAFE) 

distinct - uses _literal_as_label_reference (NOT SAFE) 
group_by - uses _literal_as_label_reference (NOT SAFE) 
order_by - uses _literal_as_label_reference (NOT SAFE) 

join  - uses model attributes to resolve relation (SAFE) 

例子(保持它的簡單,字符串格式化跳過):

db.session.query(User.login).group_by('login').having('count(id) > 4; select name from roles').all() 
db.session.query(User.login).distinct('name) name from roles /*').order_by('*/').all() 
db.session.query(User.login).order_by('users_login; select name from roles').all() 
db.session.query(User.login).group_by('login union select name from roles').all() 

注意如果傳遞字符串文字,這些方法只是不安全的。