1、SQL注入簡介python
SQL注入是比較常見的網絡攻擊方式之一,它不是利用操做系統的BUG來實現攻擊,而是針對程序員編程時的疏忽,經過SQL語句,實現無賬號登陸,甚至篡改數據庫。mysql
2、SQL注入攻擊的整體思路程序員
1.尋找到SQL注入的位置sql
2.判斷服務器類型和後臺數據庫類型數據庫
3.針對不通的服務器和數據庫特色進行SQL注入攻擊編程
3、SQL注入攻擊實例服務器
一、字符串拼接查詢,形成注入網絡
import pymysql conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='User') cursor = conn.cursor() username=input() password =input() # 正常構造語句的狀況 sql = "select user,pwd from User where user='%s' and pwd='%s'" % (username,password) row_count = cursor.execute(sql) row_1 = cursor.fetchone() print(row_count, row_1) conn.commit() cursor.close() conn.close()
其實用戶能夠這樣輸入實現免賬號登陸:ide
username: ‘or 1 = 1 –-函數
password:
如若沒有作特殊處理,那麼這個非法用戶直接登錄進去了.
當輸入了上面的用戶名和密碼,服務端的sql就變成:
sql = "select user,pwd from User where user=‘'or 1 = 1 –-' and pwd='%s'"
由於條件後面username=」or 1=1 用戶名等於 」 或1=1 那麼這個條件必定會成功;而後後面加兩個-,這意味着註釋,它將後面的語句註釋,讓他們不起做用,這樣語句永遠都能正確執行,用戶輕易騙過系統,獲取合法身份。
解決方法:
一、使用pymysql提供的參數化語句防止注入
#! /usr/bin/env python # -*- coding:utf-8 -*- import pymysql conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='User') cursor = conn.cursor() username= input() password =input() #執行參數化查詢 row_count=cursor.execute("select user,pwd from User where user='%s' and pwd='%s'" ,(username,password)) #execute()函數自己就有接受SQL語句變量的參數位,只要正確的使用(直白一點就是:使用」逗號」,而不是」百分號」)就能夠對傳入的值進行correctly轉義,從而避免SQL注入的發生。 #內部執行參數化生成的SQL語句,對特殊字符進行了加\轉義,避免注入語句生成。 # sql=cursor.mogrify("select user,pwd from User where user='%s' and pwd='%s'" ,(username,password)) # print (sql) row_1 = cursor.fetchone() print(row_count,row_1) conn.commit() cursor.close() conn.close()
注意:excute執行SQL語句的時候,必須使用參數化的方式,不然必然產生SQL注入漏洞。
二、使用存mysql儲過程動態執行SQL防注入
使用MYSQL存儲過程自動提供防注入,動態傳入SQL到存儲過程執行語句。
delimiter \\ DROP PROCEDURE IF EXISTS proc_sql \\ CREATE PROCEDURE proc_sql ( in nid1 INT, in nid2 INT, in callsql VARCHAR(255) ) BEGIN set @nid1 = nid1; set @nid2 = nid2; set @callsql = callsql; PREPARE myprod FROM @callsql; -- PREPARE prod FROM 'select * from tb2 where nid>? and nid<?'; 傳入的值爲字符串,?爲佔位符 -- 用@p1,和@p2填充佔位符 EXECUTE myprod USING @nid1,@nid2; DEALLOCATE prepare myprod; END\\ delimiter ;
set @nid1=12; set @nid2=15; set @callsql = 'select * from User where nid>? and nid<?'; CALL proc_sql(@nid1,@nid2,@callsql)
pymsql中調用
#! /usr/bin/env python # -*- coding:utf-8 -*- import pymysql conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='User') cursor = conn.cursor() mysql="select * from User where nid>? and nid<?" cursor.callproc('proc_sql', args=(11, 15, mysql)) rows = cursor.fetchall() print (rows #((12, 'u1', 'u1pass', 11111), (13, 'u2', 'u2pass', 22222), (14, 'u3', 'u3pass', 11113))) conn.commit() cursor.close() conn.close()