一、SQL注入簡介
SQL注入是比較常見的網絡攻擊方式之一,它不是利用操作系統的BUG來實現攻擊,而是針對程序員編程時的疏忽,通過SQL語句,實現無帳號登錄,甚至篡改數據庫。
二、SQL注入攻擊的總體思路
1.尋找到SQL注入的位置
2.判斷服務器類型和后台數據庫類型
3.針對不通的服務器和數據庫特點進行SQL注入攻擊
三、SQL注入攻擊實例
1、字符串拼接查詢,造成注入
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()
其實用戶可以這樣輸入實現免帳號登錄:
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 那么這個條件一定會成功;然后后面加兩個-,這意味着注釋,它將后面的語句注釋,讓他們不起作用,這樣語句永遠都能正確執行,用戶輕易騙過系統,獲取合法身份。
解決方法:
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注入漏洞。
2、使用存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()