python Web安全之防止SQL注入

伴隨着Web2.0、社交網絡、微博等一系列新型互聯網產品的興起,基於Web環境的互聯網應用越來越廣泛,Web攻擊的手段也越來越多樣,Web安全史上的一個重要里程碑是大約1999年發現的SQL注入攻擊,之後的XSS,CSRF等攻擊手段愈發強大,Web攻擊的思路也從服務端轉向了客戶端,轉向了瀏覽器和用戶。

在安全領域,一般用帽子的顏色來比喻黑客的善與惡,白帽子是指那些工作在反黑客領域的技術專家,這個羣體是”善”的的象徵;而黑帽子則是指那些利用黑客技術造成破壞甚至謀取私利造成犯罪的羣體,他們是”惡”的代表。

“白帽子”和”黑帽子”是兩個完全對立的羣體。對於黑帽子而言,他們只要找到系統的一個切入點就可以達到入侵破壞的目的,而白帽子必須將自己系統所有可能被突破的地方都設防,以保證系統的安全運行。

這看起來好像是不公平的,但是安全世界裏的規則就是這樣,可能我們的網站1000處都佈防的很好,考慮的很周到,但是只要有一個地方疏忽了,攻擊者就會利用這個點進行突破,讓我們另外的1000處努力白費。

 

常見攻擊方式

一般說來,在Web安全領域,常見的攻擊方式大概有以下幾種:
1、SQL注入攻擊
2、跨站腳本攻擊 - XSS
3、跨站僞造請求攻擊 - CSRF
4、文件上傳漏洞攻擊
5、分佈式拒絕服務攻擊 - DDOS

SQL注入實例之參數化


from pymysql import *

def main():

    find_name = input("請輸入物品名稱:")

    # 創建Connection連接
    conn = connect(host='localhost',port=3306,user='root',password='mysql',database='jing_dong',charset='utf8')
    # 獲得Cursor對象
    cs1 = conn.cursor()


    # # 非安全的方式
    # # 輸入 " or 1=1 or "   (雙引號也要輸入)
    # sql = 'select * from goods where name="%s"' % find_name
    # print("""sql===>%s<====""" % sql)
    # # 執行select語句,並返回受影響的行數:查詢所有數據
    # count = cs1.execute(sql)

    # 安全的方式
    # 構造參數列表
    params = [find_name]
    # 執行select語句,並返回受影響的行數:查詢所有數據
    count = cs1.execute('select * from goods where name=%s', params)
    # 注意:
    # 如果要是有多個參數,需要進行參數化
    # 那麼params = [數值1, 數值2....],此時sql語句中有多個%s即可 

    # 打印受影響的行數
    print(count)
    # 獲取查詢的結果
    # result = cs1.fetchone()
    result = cs1.fetchall()
    # 打印查詢的結果
    print(result)
    # 關閉Cursor對象
    cs1.close()
    # 關閉Connection對象
    conn.close()

if __name__ == '__main__':
    main()

這種用法就是常見的拼接字符串導致sql注入漏洞的產生。看到這個突然想到上個禮拜drupal水滴的那個漏洞,其並不是預編譯語句被繞過了。而是在構造帶入的預編譯語句的時候拼接了用戶輸入字符串,還未帶入查詢的預編譯語句已經被注入了,之後帶入正確的參數,最後被注入了

正確用法:
execute() 函數本身有接受sql語句參數位的,可以通過python自身的函數處理sql注入問題。

使用如此參數帶入方式,python會自動過濾params中的特殊字符,制止SQL注入的產生。

execute()函數本身就有接受SQL語句變量的參數位,只要正確的使用(直白一點就是:使用”逗號”,而不是”百分號”)就可以對傳入的值進行correctly轉義,從而避免SQL注入的發生。

如何確定SQL注入漏洞

通過以上的實例,我們仍然還會有疑問:黑客並不知道我們程序代碼的邏輯和SQL語句的寫法,他是如何確定一個網站是否存在SQL注入漏洞呢?一般說來有以下2種途徑:

1、錯誤提示

如果目標Web網站開啓了錯誤顯示,攻擊者就可以通過反覆調整發送的參數、查看頁面打印的錯誤信息,推測出Web網站使用的數據庫和開發語言等重要信息。

2、盲注

除非運維人員疏忽,否則大部分的Web運營網站應該都關閉了錯誤提示信息,此時攻擊者一般會採用盲注的技巧來進行反覆的嘗試判斷。 仍然以上面的數據表user爲例,我們之前的查看會員詳情頁面的url地址爲userinfo.php?username=plhwin,此時黑客分別訪問userinfo.php?username=plhwin' AND 1=1-- hackuserinfo.php?username=plhwin' AND 1=2-- hack,如果前者訪問能返回正常的信息而後者不能,就基本可以判斷此網站存在SQL注入漏洞,因爲後者的1=2這個表達式永遠不成立,所以即使username傳入了正確的參數也無法通過,由此可以推斷這個頁面存在SQL注入漏洞,並且可以通過username參數進行注入。

如何防禦SQL注入

對於服務器配置層面的防範,應該保證生產環境的Webserver是關閉錯誤信息的,比如PHP在生產環境的配置文件php.ini中的display_errors應該設置爲Off,這樣就關閉了錯誤提示,下面我們更多的從編碼的角度來看看如何防範SQL注入。

上面用兩個實例分析了SQL注入攻擊的技巧,可以看到,但凡有SQL注入漏洞的程序,都是因爲程序要接受來自客戶端用戶輸入的變量或URL傳遞的參數,並且這個變量或參數是組成SQL語句的一部分,對於用戶輸入的內容或傳遞的參數,我們應該要時刻保持警惕,這是安全領域裏的「外部數據不可信任」的原則,縱觀Web安全領域的各種攻擊方式,大多數都是因爲開發者違反了這個原則而導致的,所以自然能想到的,就是從變量的檢測、過濾、驗證下手,確保變量是開發者所預想的。

1、檢查變量數據類型和格式

如果你的SQL語句是類似where id={$id}這種形式,數據庫裏所有的id都是數字,那麼就應該在SQL被執行前,檢查確保變量id是int類型;如果是接受郵箱,那就應該檢查並嚴格確保變量一定是郵箱的格式,其他的類型比如日期、時間等也是一個道理。總結起來:只要是有固定格式的變量,在SQL語句執行前,應該嚴格按照固定格式去檢查,確保變量是我們預想的格式,這樣很大程度上可以避免SQL注入攻擊。

比如,我們前面接受username參數例子中,我們的產品設計應該是在用戶註冊的一開始,就有一個用戶名的規則,比如5-20個字符,只能由大小寫字母、數字以及一些安全的符號組成,不包含特殊字符。此時我們應該有一個check_username的函數來進行統一的檢查。不過,仍然有很多例外情況並不能應用到這一準則,比如文章發佈系統,評論系統等必須要允許用戶提交任意字符串的場景,這就需要採用過濾等其他方案了。

2、過濾特殊符號

對於無法確定固定格式的變量,一定要進行特殊符號過濾或轉義處理。以PHP爲例,通常是採用addslashes函數,它會在指定的預定義字符前添加反斜槓轉義,這些預定義的字符是:單引號 (') 雙引號 (") 反斜槓 (\) NULL

相信大家都還對2011年爆出的CSDN拖庫事件記憶猶新,這件事情導致CSDN處在風口浪尖被大家痛罵的原因就在於他們竟然明文存儲用戶的密碼,這引發了科技界對用戶信息安全尤其是密碼安全的強烈關注,我們在防範SQL注入的發生的同時,也應該未雨綢繆,說不定下一個被拖庫的就是你,誰知道呢。

在Web開發中,傳統的加解密大致可以分爲三種:

1、對稱加密:即加密方和解密方都使用相同的加密算法和密鑰,這種方案的密鑰的保存非常關鍵,因爲算法是公開的,而密鑰是保密的,一旦密匙泄露,黑客仍然可以輕易解密。常見的對稱加密算法有:AESDES等。

2、非對稱加密:即使用不同的密鑰來進行加解密,密鑰被分爲公鑰和私鑰,用私鑰加密的數據必須使用公鑰來解密,同樣用公鑰加密的數據必須用對應的私鑰來解密,常見的非對稱加密算法有:RSA等。

3、不可逆加密:利用哈希算法使數據加密之後無法解密回原數據,這樣的哈希算法常用的有:md5SHA-1等。

在我們上面登錄系統的示例代碼中,$md5password = md5($password);從這句代碼可以看到採用了md5的不可逆加密算法來存儲密碼,這也是多年來業界常用的密碼加密算法,但是這仍然不安全。爲什麼呢?

這是因爲md5加密有一個特點:同樣的字符串經過md5哈希計算之後生成的加密字符串也是相同的,由於業界採用這種加密的方式由來已久,黑客們也準備了自己強大的md5彩虹表來逆向匹配加密前的字符串,這種用於逆向反推MD5加密的彩虹表在互聯網上隨處可見,在Google裏使用md5 解密作爲關鍵詞搜索,一下就能找到md5在線破解網站,把我們插入用戶數據時候的MD5加密字符串e10adc3949ba59abbe56e057f20f883e填入進去,瞬間就能得到加密前的密碼:123456。當然也並不是每一個都能成功,但可以肯定的是,這個彩虹表會越來越完善。

所以,我們有迫切的需求採用更好的方法對密碼數據進行不可逆加密,通常的做法是爲每個用戶確定不同的密碼加鹽(salt)後,再混合用戶的真實密碼進行md5加密

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章