自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

舉世聞名的 SQL 注入是什么?這個(gè)漫畫(huà)告訴你!

數(shù)據(jù)庫(kù) SQL Server
相信大家對(duì)于學(xué)校們?cè)愀獾木W(wǎng)絡(luò)環(huán)境和運(yùn)維手段都早有體會(huì),在此就不多做吐槽了。今天我們來(lái)聊一聊 SQL 注入相關(guān)的內(nèi)容。

先來(lái)看一副很有意思的漫畫(huà):

相信大家對(duì)于學(xué)校們?cè)愀獾木W(wǎng)絡(luò)環(huán)境和運(yùn)維手段都早有體會(huì),在此就不多做吐槽了。今天我們來(lái)聊一聊 SQL 注入相關(guān)的內(nèi)容。

何謂 SQL 注入

SQL 注入是一種非常常見(jiàn)的數(shù)據(jù)庫(kù)攻擊手段,SQL 注入漏洞也是網(wǎng)絡(luò)世界中最普遍的漏洞之一。大家也許都聽(tīng)過(guò)某某學(xué)長(zhǎng)通過(guò)攻擊學(xué)校數(shù)據(jù)庫(kù)修改自己成績(jī)的事情,這些學(xué)長(zhǎng)們一般用的就是 SQL 注入方法。

SQL 注入其實(shí)就是惡意用戶(hù)通過(guò)在表單中填寫(xiě)包含 SQL 關(guān)鍵字的數(shù)據(jù)來(lái)使數(shù)據(jù)庫(kù)執(zhí)行非常規(guī)代碼的過(guò)程。簡(jiǎn)單來(lái)說(shuō),就是數(shù)據(jù)「越俎代庖」做了代碼才能干的事情。

這個(gè)問(wèn)題的來(lái)源是,SQL 數(shù)據(jù)庫(kù)的操作是通過(guò) SQL 語(yǔ)句來(lái)執(zhí)行的,而無(wú)論是執(zhí)行代碼還是數(shù)據(jù)項(xiàng)都必須寫(xiě)在 SQL 語(yǔ)句之中,這就導(dǎo)致如果我們?cè)跀?shù)據(jù)項(xiàng)中加入了某些 SQL 語(yǔ)句關(guān)鍵字(比如說(shuō) SELECT、DROP 等等),這些關(guān)鍵字就很可能在數(shù)據(jù)庫(kù)寫(xiě)入或讀取數(shù)據(jù)時(shí)得到執(zhí)行。

多言無(wú)益,我們拿真實(shí)的案例來(lái)說(shuō)話。下面我們先使用 SQLite 建立一個(gè)學(xué)生檔案表。

SQL 數(shù)據(jù)庫(kù)操作示例:

  1. import sqlite3 
  2. conn = sqlite3.connect('test.db'
  3. conn.executescript('''DROP TABLE IF EXISTS students; 
  4.        CREATE TABLE students 
  5.        (id INTEGER PRIMARY KEY AUTOINCREMENT, 
  6.        name TEXT NOT NULL);''') 
  7. students = ['Paul','Tom','Tracy','Lily'
  8.  
  9. for name in students: 
  10.     query = "INSERT INTO students (name) VALUES ('%s')" % (name
  11.     conn.executescript(query); 
  12. cursor = conn.execute("SELECT id, name from students"
  13. print('IDName'
  14. for row in cursor
  15.     print('{0}{1}'.format(row[0], row[1])) 
  16.  
  17. conn.close() 

點(diǎn)擊運(yùn)行按鈕將會(huì)打印目前表中的內(nèi)容。上述程序中我們建立了一個(gè) test.db 數(shù)據(jù)庫(kù)以及一個(gè) students 數(shù)據(jù)表,并向表中寫(xiě)入了四條學(xué)生信息。

那么 SQL 注入又是怎么一回事呢?我們嘗試再插入一條惡意數(shù)據(jù),數(shù)據(jù)內(nèi)容就是漫畫(huà)中的 "Robert');DROP TABLE students;--",看看會(huì)發(fā)生什么情況。

SQL 數(shù)據(jù)庫(kù)注入示例:

  1. conn = sqlite3.connect('test.db'
  2. name = "Robert');DROP TABLE students;--" 
  3. query = "INSERT INTO students (name) VALUES ('%s')" % (name
  4.  
  5. conn.executescript(query) 
  6. cursor = conn.execute("SELECT id, name from students"
  7. print('IDName'
  8. for row in cursor
  9.     print('{0}{1}'.format(row[0], row[1])) 
  10.  
  11. conn.close() 

你將會(huì)發(fā)現(xiàn),運(yùn)行后,程序沒(méi)有輸出任何數(shù)據(jù)內(nèi)容,而是返回一條錯(cuò)誤信息:表單 students 無(wú)法找到!

這是為什么呢?問(wèn)題就在于我們所插入的數(shù)據(jù)項(xiàng)中包含 SQL 關(guān)鍵字 DROP TABLE,這兩個(gè)關(guān)鍵字的意義是從數(shù)據(jù)庫(kù)中清除一個(gè)表單。

而關(guān)鍵字之前的 Robert'); 使得 SQL 執(zhí)行器認(rèn)為上一命令已經(jīng)結(jié)束,從而使得危險(xiǎn)指令 DROP TABLE 得到執(zhí)行。

也就是說(shuō),這段包含 DROP TABLE 關(guān)鍵字的數(shù)據(jù)項(xiàng)使得原有的簡(jiǎn)單的插入姓名信息的 SQL 語(yǔ)句:

  1. INSERT INTO students (nameVALUES ('Robert'
  2. INSERT INTO students (nameVALUES ('Robert');DROP TABLE students; 

而 SQL 數(shù)據(jù)庫(kù)執(zhí)行上述操作后,students 表單被清除,因而表單無(wú)法找到,所有數(shù)據(jù)項(xiàng)丟失。

如何防止 SQL 注入問(wèn)題呢?

大家也許都想到了,注入問(wèn)題都是因?yàn)閳?zhí)行了數(shù)據(jù)項(xiàng)中的 SQL 關(guān)鍵字,那么,只要檢查數(shù)據(jù)項(xiàng)中是否存在 SQL 關(guān)鍵字不就可以了么?

的確是這樣,很多數(shù)據(jù)庫(kù)管理系統(tǒng)都是采取了這種看似『方便快捷』的過(guò)濾手法,但是這并不是一種根本上的解決辦法,如果有個(gè)美國(guó)人真的就叫做『Drop Table』呢?你總不能逼人家改名字吧。

合理的防護(hù)辦法有很多。首先,盡量避免使用常見(jiàn)的數(shù)據(jù)庫(kù)名和數(shù)據(jù)庫(kù)結(jié)構(gòu)。在上面的案例中,如果表單名字并不是 students,則注入代碼將會(huì)在執(zhí)行過(guò)程中報(bào)錯(cuò),也就不會(huì)發(fā)生數(shù)據(jù)丟失的情況——SQL 注入并不像大家想象得那么簡(jiǎn)單,它需要攻擊者本身對(duì)于數(shù)據(jù)庫(kù)的結(jié)構(gòu)有足夠的了解才能成功,因而在構(gòu)建數(shù)據(jù)庫(kù)時(shí)盡量使用較為復(fù)雜的結(jié)構(gòu)和命名方式將會(huì)極大地減少被成功攻擊的概率。

使用正則表達(dá)式等字符串過(guò)濾手段限制數(shù)據(jù)項(xiàng)的格式、字符數(shù)目等也是一種很好的防護(hù)措施。理論上,只要避免數(shù)據(jù)項(xiàng)中存在引號(hào)、分號(hào)等特殊字符就能很大程度上避免 SQL 注入的發(fā)生。

另外,就是使用各類(lèi)程序文檔所推薦的數(shù)據(jù)庫(kù)操作方式來(lái)執(zhí)行數(shù)據(jù)項(xiàng)的查詢(xún)與寫(xiě)入操作,比如在上述的案例中,如果我們稍加修改,首先使用 execute() 方法來(lái)保證每次執(zhí)行僅能執(zhí)行一條語(yǔ)句,然后將數(shù)據(jù)項(xiàng)以參數(shù)的方式與 SQL 執(zhí)行語(yǔ)句分離開(kāi)來(lái),就可以完全避免SQL 注入的問(wèn)題,如下 SQL 數(shù)據(jù)庫(kù)反注入示例。

  1. conn = sqlite3.connect('test.db'
  2. name = "Robert');DROP TABLE students;--" 
  3. query = "INSERT INTO students (name) VALUES (?)" 
  4.  
  5. conn.execute(query, [name]) 
  6. cursor = conn.execute("SELECT id, name from students"
  7. print('IDName'
  8. for row in cursor
  9.     print('{0}{1}'.format(row[0], row[1])) 
  10.  
  11. conn.close() 

而對(duì)于 PHP 而言,則可以通過(guò) mysql_real_escape_string 等方法對(duì) SQL 關(guān)鍵字進(jìn)行轉(zhuǎn)義,必要時(shí)審查數(shù)據(jù)項(xiàng)目是否安全來(lái)防治SQL 注入。

當(dāng)然,做好數(shù)據(jù)庫(kù)的備份,同時(shí)對(duì)敏感內(nèi)容進(jìn)行加密永遠(yuǎn)是最重要的。某些安全性問(wèn)題可能永遠(yuǎn)不會(huì)有完美的解決方案,只有我們做好最基本的防護(hù)措施,才能在發(fā)生問(wèn)題的時(shí)候亡羊補(bǔ)牢,保證最小程度的損失。

 

責(zé)任編輯:未麗燕 來(lái)源: Java專(zhuān)欄
相關(guān)推薦

2019-11-28 08:59:03

SQL注入網(wǎng)絡(luò)攻擊網(wǎng)絡(luò)安全

2012-07-03 16:56:12

Hadoop

2021-01-19 14:43:05

數(shù)據(jù)

2011-08-01 14:33:44

SQL

2019-07-24 11:21:18

Node.jsHTMLCSS

2015-06-09 14:49:38

2022-04-29 08:00:36

web3區(qū)塊鏈比特幣

2019-12-09 17:31:00

華為云

2020-12-08 08:14:11

SQL注入數(shù)據(jù)庫(kù)

2021-01-15 07:44:21

SQL注入攻擊黑客

2021-02-27 10:38:56

Python結(jié)構(gòu)數(shù)據(jù)

2019-07-09 14:49:42

SaaS軟件云計(jì)算

2018-03-29 10:19:45

2021-11-08 13:05:54

SQL

2021-09-26 20:22:58

5GAI技術(shù)

2009-06-12 13:59:04

2021-09-26 05:41:13

數(shù)字困境IT領(lǐng)導(dǎo)數(shù)字轉(zhuǎn)型

2015-03-02 10:08:09

Apple Watch

2020-03-03 17:00:58

HDFS存儲(chǔ)數(shù)據(jù)

2021-04-15 09:37:05

大數(shù)據(jù)Maven
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)