天天看點

SQL注入攻擊的原理和代碼示範示例 及 防範措施

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

繼續閱讀