1.什麼是 SQL 注入?
通過構造特殊的輸入參數傳入Web應用,導緻後端執行了惡意 SQL
通常由于程式員未對輸入過濾,直接動态拼接 SQL 産生
可以使用開源工具 sqlmap,SQLninja 檢測
2.SQL注入代碼示範示例
1)建立users表和插入相應資訊
-- 建立users資料表
CREATE TABLE `users`(
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(45) NULL,
`email` VARCHAR(45) NULL,
`password` VARCHAR(45) NULL,
PRIMARY KEY (`id`)
);
-- 插入users表三條資料
insert into users (name,email,password) values ('zhangsan','[email protected]',md5('zhangsan123'));
insert into users (name,email,password) values ('lisi','[email protected]',md5('lisi123'));
insert into users (name,email,password) values ('wangwu','[email protected]',md5('wangwu123'));
2) 存在SQL漏洞代碼示例:在終端下輸入名稱和密碼然後查詢使用者資訊
# sql 注入示範代碼
import os
import MySQLdb # pip install mysqlclient
# 建立資料庫連結
db = MySQLdb.connect(
host='localhost',
user='root',
passwd='123456',
db='test'
)
cur = db.cursor()
name = input('Enter name: ')
print('您輸入的使用者name是: {}'.format(name))
password = input('Enter password:')
print('您輸入的密碼是: {}'.format(password))
# 直接拼接 sql 參數,使用md5的 password
sql = "SELECT * FROM users WHERE name='" + name + "'"+"AND password=md5('" + password + "')"
print(sql)
cur.execute(sql)
for row in cur.fetchall():
print(row)
# 關閉連接配接
db.close()
3)SQL注入示範結果
# 輸入正确的使用者名和密碼
Enter name: lisi
您輸入的使用者name是: lisi
Enter password:lisi123
您輸入的密碼是: lisi123
SELECT * FROM users WHERE name='lisi'AND password=md5('lisi123')
(2, 'lisi', '[email protected]', 'c3cb6d12c40908943b64bc0681af47db')
# 輸出錯誤密碼,可以看到并沒有傳回使用者資訊
Enter name: lisi
您輸入的使用者name是: lisi
Enter password:1234
您輸入的密碼是: 1234
SELECT * FROM users WHERE name='lisi'AND password=md5('1234')
# 因為代碼有sql注入漏洞,在使用者名後面加入中線,這裡還輸錯誤密碼,還是傳回查詢結果。
Enter name: lisi' -- ' # -- 中線前後都有空格,中線在sql語句中表示注釋意思
您輸入的使用者name是: lisi' -- '
Enter password:123456
您輸入的密碼是: 123456
SELECT * FROM users WHERE name='lisi' -- ''AND password=md5('123456')
(2, 'lisi', '[email protected]', 'c3cb6d12c40908943b64bc0681af47db')
# 這裡就是通過SQL注入方式繞過網站的安全驗證
4)怎麼修複sql注入問題,其實隻要把使用拼接的地方直接換成占位符就可以
# 隻需要修改成以下方式
sql = "SELECT * from users WHERE name=%s and password=md5(%s)"
print(sql)
cur.execute(sql, (name, password)) # execute它會自動執行轉義操作
在終端再次執行就不會有結果傳回,并沒有像上面的一樣繞過安全驗證
Enter name: lisi' -- '
您輸入的使用者name是: lisi' -- '
Enter password:123456
您輸入的密碼是: 123456
SELECT * from users WHERE name=%s and password=md5(%s)
通過字元串占位符的方式,然後讓Mysqldbb幫我們解決SQL注入的問題,它會在底層幫我們做一個轉義操作。
2.如何防範 SQL 注入?
web 安全一大原則:永遠不要相信使用者的任何輸入
對輸入參數做好檢查(類型和範圍);過濾和轉義特殊字元
不要直接拼接sql,使用ORM可以大大降低 sql 注入風險
資料庫層:做好權限管理配置;不要明文存儲敏感資訊。
ORM 有安全性考慮,通過傳參的形式不會有 sql 注入問題,是以提倡使用而不是自己直接拼 sql