Django之SQL注入


## 所謂SQL注入,就是通過把SQL命令插入到表單中或頁面請求的查詢字符串中,最終達到欺騙服務器執行惡意的SQL命令。
    具體來說,它是利用現有應用程序,將(惡意的)SQL命令注入到后台數據庫引擎執行的能力,
    它可以通過在Web表單中輸入(惡意)SQL語句得到一個存在安全漏洞的網站上的數據庫,而不是按照設計者意圖去執行SQL語句。 
    比如先前的很多影視網站泄露VIP會員密碼大多就是通過WEB表單遞交查詢字符暴出的。
## 場景:
    比如現在數據庫中有一個front_user表,表結構如下:
        class User(models.Model):
            telephone = models.CharField(max_length=11)
            username = models.CharField(max_length=100)
            password = models.CharField(max_length=100)
    然后我們使用原生sql語句實現以下需求:
    1.實現一個根據用戶id獲取用戶詳情的視圖。示例代碼如下:
         def index(request):
             user_id = request.GET.get('user_id')
             cursor = connection.cursor()
             cursor.execute("select id,username from front_user where id=%s" % user_id)
             rows = cursor.fetchall()
             for row in rows:
                 print(row)
             return HttpResponse('success')
    這樣表面上看起來沒有問題。但是如果用戶傳的user_id是等於1 or 1=1,那么以上拼接后的sql語句為:
        select id,username from front_user where id=1 or 1=1
    以上sql語句的條件是id=1 or 1=1,只要id=1或者是1=1兩個有一個成立,那么整個條件就成立。毫無疑問1=1是肯定成立的。
    因此執行完以上sql語句后,會將front_user表中所有的數據都提取出來。
    
    2.實現一個根據用戶的username提取用戶的視圖。示例代碼如下:
         def index(request):
             username = request.GET.get('username')
             cursor = connection.cursor()
             cursor.execute("select id,username from front_user where username='%s'" % username)
             rows = cursor.fetchall()
             for row in rows:
                 print(row)
             return HttpResponse('success')
    這樣表面上看起來也沒有問題。但是如果用戶傳的username是zhiliao' or '1=1,那么以上拼接后的sql語句為:
        select id,username from front_user where username='zhiliao' or '1=1'
    以上sql語句的條件是username='zhiliao'或者是一個字符串,毫無疑問,字符串的判斷是肯定成立的。因此會將front_user表中所有的數據都提取出來。

################# sql注入防御:
    以上便是sql注入的原理。他通過傳遞一些惡意的參數來破壞原有的sql語句以便達到自己的目的。
    當然sql注入遠遠沒有這么簡單,我們現在講到的只是冰山一角。那么如何防御sql注入呢?歸類起來主要有以下幾點:
        1.永遠不要信任用戶的輸入。對用戶的輸入進行校驗,可以通過正則表達式,或限制長度;對單引號和 雙"-"進行轉換等。
        2.永遠不要使用動態拼裝sql,可以使用參數化的sql或者直接使用存儲過程進行數據查詢存取。比如:
             def index(request):
                 user_id = "1 or 1=1"
                 cursor = connection.cursor()
                 cursor.execute("select id,username from front_user where id=%s",(user_id,))
                 rows = cursor.fetchall()
                 for row in rows:
                     print(row)
                 return HttpResponse('success')
        3.永遠不要使用管理員權限的數據庫連接,為每個應用使用單獨的權限有限的數據庫連接。
        4.不要把機密信息直接存放,加密或者hash掉密碼和敏感的信息。
        5.應用的異常信息應該給出盡可能少的提示,最好使用自定義的錯誤信息對原始錯誤信息進行包裝。
## 在Django中如何防御sql注入:
    1.使用ORM來做數據的增刪改查。因為ORM使用的是參數化的形式執行sql語句的。
    2.如果萬一要執行原生sql語句,那么建議不要拼接sql,而是使用參數化的形式。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM