SQL注入
SQL攻擊(SQL injection),簡(jiǎn)稱注入攻擊,是發(fā)生于應(yīng)用程序之?dāng)?shù)據(jù)庫(kù)層的安全漏洞。簡(jiǎn)而言之,是在輸入的字符串之中注入SQL指令,在設(shè)計(jì)不良的程序當(dāng)中忽略了檢查,那么這些注入進(jìn)去的指令就會(huì)被數(shù)據(jù)庫(kù)服務(wù)器誤認(rèn)為是正常的SQL指令而運(yùn)行,因此遭到破壞或是入侵。
----維基百科
簡(jiǎn)而言之,sql注入是指在http通信中, 將sql語(yǔ)句偽裝成參數(shù)傳入服務(wù)器,服務(wù)器如果沒有防范則會(huì)執(zhí)行惡意sql語(yǔ)句,從而導(dǎo)致數(shù)據(jù)泄露等危險(xiǎn).那么如何防止sql注入呢?
ORM
象關(guān)系映射(英語(yǔ):Object Relational Mapping,簡(jiǎn)稱ORM),是一種程序設(shè)計(jì)技術(shù),用于實(shí)現(xiàn)面向?qū)ο缶幊陶Z(yǔ)言里不同類型系統(tǒng)的數(shù)據(jù)之間的轉(zhuǎn)換。從效果上說(shuō),它其實(shí)是創(chuàng)建了一個(gè)可在編程語(yǔ)言里使用的“虛擬對(duì)象數(shù)據(jù)庫(kù)”.
借助OO思想,數(shù)據(jù)庫(kù)中的表被映射為Python的類,類的對(duì)象代表數(shù)據(jù)表中的一行記錄,所有的DB操作都通過(guò)對(duì)象方法調(diào)用來(lái)實(shí)現(xiàn),這些調(diào)用在底層被自動(dòng)轉(zhuǎn)換成SQL語(yǔ)句,在轉(zhuǎn)換過(guò)程中,通常會(huì)采用parameter bind的方式保證生成的parameterized SQL不存在被注入的風(fēng)險(xiǎn).
常用的orm肯定是sqlalchemy.
MySQLdb
mysqldb是常用的操作mysql的庫(kù), 導(dǎo)致sql注入的寫法:
temp = "select name from userinfo where name='%s' and password='%s'" % (username, pwd)
effect_row = cursor.execute(temp)
這種方法直接將參數(shù)進(jìn)行拼接
正確的寫法是:
effect_row = cursor.execute("select name from userinfo where name='%s' and password='%s'",(username, pwd,))
通過(guò)參數(shù)的形式傳入sql語(yǔ)句, 會(huì)將 ' 單引號(hào)進(jìn)行轉(zhuǎn)義
SQLAlchemy
前文說(shuō)到,當(dāng)使用sqlalchemy時(shí),正常使用如:
session.query(User).filter(id == user_id)
是不會(huì)有問題的,因?yàn)閛rm會(huì)將sql語(yǔ)句進(jìn)行轉(zhuǎn)義,但是如果使用其execute()
直接執(zhí)行sql語(yǔ)句則還是有一定的風(fēng)險(xiǎn)的,如:
session.execute('select * from user where id = %s' % user_id).fetchall()
正確的寫法:
from sqlalchemy import text
sql = 'select * from user where id = :id'
session.execute(text(sql), {'id':1}).fetchall()
通過(guò)text函數(shù)將數(shù)值通過(guò)參數(shù)的形式傳入.
結(jié)尾結(jié)論: 無(wú)論何時(shí)盡量使用參數(shù)綁定的形式來(lái)構(gòu)建SQL語(yǔ)句