鍍金池/ 教程/ GO/ 9.4 避免SQL注入
7 文本處理
3 Web基礎(chǔ)
14 擴(kuò)展Web框架
10.4 小結(jié)
2.2 Go基礎(chǔ)
2.8 總結(jié)
6.1 session和cookie
5.5 使用beedb庫(kù)進(jìn)行ORM開(kāi)發(fā)
8.3 REST
13.6 小結(jié)
5.4 使用PostgreSQL數(shù)據(jù)庫(kù)
14.6 pprof支持
14.1 靜態(tài)文件支持
11.2 使用GDB調(diào)試
7.7 小結(jié)
1 GO環(huán)境配置
14.5 多語(yǔ)言支持
7.1 XML處理
1.5 總結(jié)
13 如何設(shè)計(jì)一個(gè)Web框架
14.3 表單及驗(yàn)證支持
12 部署與維護(hù)
10 國(guó)際化和本地化
1.1 Go 安裝
6.2 Go如何使用session
5.6 NOSQL數(shù)據(jù)庫(kù)操作
6.5 小結(jié)
9.4 避免SQL注入
12.1 應(yīng)用日志
4.2 驗(yàn)證表單的輸入
10.1 設(shè)置默認(rèn)地區(qū)
1.3 Go 命令
9.6 加密和解密數(shù)據(jù)
4.1 處理表單的輸入
4.4 防止多次遞交表單
11.3 Go怎么寫(xiě)測(cè)試用例
8 Web服務(wù)
12.3 應(yīng)用部署
5.7 小結(jié)
12.5 小結(jié)
11 錯(cuò)誤處理,調(diào)試和測(cè)試
9.2 確保輸入過(guò)濾
14.2 Session支持
6.4 預(yù)防session劫持
12.4 備份和恢復(fù)
8.1 Socket編程
13.1 項(xiàng)目規(guī)劃
13.4 日志和配置設(shè)計(jì)
7.6 字符串處理
13.2 自定義路由器設(shè)計(jì)
6.3 session存儲(chǔ)
3.4 Go的http包詳解
8.2 WebSocket
10.3 國(guó)際化站點(diǎn)
7.5 文件操作
7.4 模板處理
9.1 預(yù)防CSRF攻擊
13.3 controller設(shè)計(jì)
2.6 interface
14.4 用戶認(rèn)證
2.3 流程和函數(shù)
附錄A 參考資料
11.1 錯(cuò)誤處理
9.5 存儲(chǔ)密碼
9.3 避免XSS攻擊
12.2 網(wǎng)站錯(cuò)誤處理
6 session和數(shù)據(jù)存儲(chǔ)
2.4 struct類型
3.3 Go如何使得Web工作
2.5 面向?qū)ο?/span>
3.1 Web工作方式
1.2 GOPATH與工作空間
2.1 你好,Go
9.7 小結(jié)
13.5 實(shí)現(xiàn)博客的增刪改
7.2 JSON處理
10.2 本地化資源
7.3 正則處理
2 Go語(yǔ)言基礎(chǔ)
5.1 database/sql接口
4.5 處理文件上傳
8.5 小結(jié)
4.3 預(yù)防跨站腳本
5.3 使用SQLite數(shù)據(jù)庫(kù)
14.7 小結(jié)
3.2 Go搭建一個(gè)Web服務(wù)器
2.7 并發(fā)
5 訪問(wèn)數(shù)據(jù)庫(kù)
4 表單
3.5 小結(jié)
1.4 Go開(kāi)發(fā)工具
11.4 小結(jié)
9 安全與加密
5.2 使用MySQL數(shù)據(jù)庫(kù)
4.6 小結(jié)
8.4 RPC

9.4 避免SQL注入

什么是SQL注入

SQL注入攻擊(SQL Injection),簡(jiǎn)稱注入攻擊,是Web開(kāi)發(fā)中最常見(jiàn)的一種安全漏洞??梢杂盟鼇?lái)從數(shù)據(jù)庫(kù)獲取敏感信息,或者利用數(shù)據(jù)庫(kù)的特性執(zhí)行添加用戶,導(dǎo)出文件等一系列惡意操作,甚至有可能獲取數(shù)據(jù)庫(kù)乃至系統(tǒng)用戶最高權(quán)限。

而造成SQL注入的原因是因?yàn)槌绦驔](méi)有有效過(guò)濾用戶的輸入,使攻擊者成功的向服務(wù)器提交惡意的SQL查詢代碼,程序在接收后錯(cuò)誤的將攻擊者的輸入作為查詢語(yǔ)句的一部分執(zhí)行,導(dǎo)致原始的查詢邏輯被改變,額外的執(zhí)行了攻擊者精心構(gòu)造的惡意代碼。

SQL注入實(shí)例

很多Web開(kāi)發(fā)者沒(méi)有意識(shí)到SQL查詢是可以被篡改的,從而把SQL查詢當(dāng)作可信任的命令。殊不知,SQL查詢是可以繞開(kāi)訪問(wèn)控制,從而繞過(guò)身份驗(yàn)證和權(quán)限檢查的。更有甚者,有可能通過(guò)SQL查詢?nèi)ミ\(yùn)行主機(jī)系統(tǒng)級(jí)的命令。

下面將通過(guò)一些真實(shí)的例子來(lái)詳細(xì)講解SQL注入的方式。

考慮以下簡(jiǎn)單的登錄表單:

<form action="/login" method="POST">
<p>Username: <input type="text" name="username" /></p>
<p>Password: <input type="password" name="password" /></p>
<p><input type="submit" value="登陸" /></p>
</form>

我們的處理里面的SQL可能是這樣的:

username:=r.Form.Get("username")
password:=r.Form.Get("password")
sql:="SELECT * FROM user WHERE username='"+username+"' AND password='"+password+"'"

如果用戶的輸入的用戶名如下,密碼任意

myuser' or 'foo' = 'foo' --

那么我們的SQL變成了如下所示:

SELECT * FROM user WHERE username='myuser' or 'foo'=='foo' --'' AND password='xxx'

在SQL里面--是注釋標(biāo)記,所以查詢語(yǔ)句會(huì)在此中斷。這就讓攻擊者在不知道任何合法用戶名和密碼的情況下成功登錄了。

對(duì)于MSSQL還有更加危險(xiǎn)的一種SQL注入,就是控制系統(tǒng),下面這個(gè)可怕的例子將演示如何在某些版本的MSSQL數(shù)據(jù)庫(kù)上執(zhí)行系統(tǒng)命令。

sql:="SELECT * FROM products WHERE name LIKE '%"+prod+"%'"
Db.Exec(sql)

如果攻擊提交a%' exec master..xp_cmdshell 'net user test testpass /ADD' --作為變量 prod的值,那么sql將會(huì)變成

sql:="SELECT * FROM products WHERE name LIKE '%a%' exec master..xp_cmdshell 'net user test testpass /ADD'--%'"

MSSQL服務(wù)器會(huì)執(zhí)行這條SQL語(yǔ)句,包括它后面那個(gè)用于向系統(tǒng)添加新用戶的命令。如果這個(gè)程序是以sa運(yùn)行而 MSSQLSERVER服務(wù)又有足夠的權(quán)限的話,攻擊者就可以獲得一個(gè)系統(tǒng)帳號(hào)來(lái)訪問(wèn)主機(jī)了。

雖然以上的例子是針對(duì)某一特定的數(shù)據(jù)庫(kù)系統(tǒng)的,但是這并不代表不能對(duì)其它數(shù)據(jù)庫(kù)系統(tǒng)實(shí)施類似的攻擊。針對(duì)這種安全漏洞,只要使用不同方法,各種數(shù)據(jù)庫(kù)都有可能遭殃。

如何預(yù)防SQL注入

也許你會(huì)說(shuō)攻擊者要知道數(shù)據(jù)庫(kù)結(jié)構(gòu)的信息才能實(shí)施SQL注入攻擊。確實(shí)如此,但沒(méi)人能保證攻擊者一定拿不到這些信息,一旦他們拿到了,數(shù)據(jù)庫(kù)就存在泄露的危險(xiǎn)。如果你在用開(kāi)放源代碼的軟件包來(lái)訪問(wèn)數(shù)據(jù)庫(kù),比如論壇程序,攻擊者就很容易得到相關(guān)的代碼。如果這些代碼設(shè)計(jì)不良的話,風(fēng)險(xiǎn)就更大了。目前Discuz、phpwind、phpcms等這些流行的開(kāi)源程序都有被SQL注入攻擊的先例。

這些攻擊總是發(fā)生在安全性不高的代碼上。所以,永遠(yuǎn)不要信任外界輸入的數(shù)據(jù),特別是來(lái)自于用戶的數(shù)據(jù),包括選擇框、表單隱藏域和 cookie。就如上面的第一個(gè)例子那樣,就算是正常的查詢也有可能造成災(zāi)難。

SQL注入攻擊的危害這么大,那么該如何來(lái)防治呢?下面這些建議或許對(duì)防治SQL注入有一定的幫助。

  1. 嚴(yán)格限制Web應(yīng)用的數(shù)據(jù)庫(kù)的操作權(quán)限,給此用戶提供僅僅能夠滿足其工作的最低權(quán)限,從而最大限度的減少注入攻擊對(duì)數(shù)據(jù)庫(kù)的危害。
  2. 檢查輸入的數(shù)據(jù)是否具有所期望的數(shù)據(jù)格式,嚴(yán)格限制變量的類型,例如使用regexp包進(jìn)行一些匹配處理,或者使用strconv包對(duì)字符串轉(zhuǎn)化成其他基本類型的數(shù)據(jù)進(jìn)行判斷。
  3. 對(duì)進(jìn)入數(shù)據(jù)庫(kù)的特殊字符('"\尖括號(hào)&*;等)進(jìn)行轉(zhuǎn)義處理,或編碼轉(zhuǎn)換。Go 的text/template包里面的HTMLEscapeString函數(shù)可以對(duì)字符串進(jìn)行轉(zhuǎn)義處理。
  4. 所有的查詢語(yǔ)句建議使用數(shù)據(jù)庫(kù)提供的參數(shù)化查詢接口,參數(shù)化的語(yǔ)句使用參數(shù)而不是將用戶輸入變量嵌入到SQL語(yǔ)句中,即不要直接拼接SQL語(yǔ)句。例如使用database/sql里面的查詢函數(shù)PrepareQuery,或者Exec(query string, args ...interface{})。
  5. 在應(yīng)用發(fā)布之前建議使用專業(yè)的SQL注入檢測(cè)工具進(jìn)行檢測(cè),以及時(shí)修補(bǔ)被發(fā)現(xiàn)的SQL注入漏洞。網(wǎng)上有很多這方面的開(kāi)源工具,例如sqlmap、SQLninja等。
  6. 避免網(wǎng)站打印出SQL錯(cuò)誤信息,比如類型錯(cuò)誤、字段不匹配等,把代碼里的SQL語(yǔ)句暴露出來(lái),以防止攻擊者利用這些錯(cuò)誤信息進(jìn)行SQL注入。

總結(jié)

通過(guò)上面的示例我們可以知道,SQL注入是危害相當(dāng)大的安全漏洞。所以對(duì)于我們平常編寫(xiě)的Web應(yīng)用,應(yīng)該對(duì)于每一個(gè)小細(xì)節(jié)都要非常重視,細(xì)節(jié)決定命運(yùn),生活如此,編寫(xiě)Web應(yīng)用也是這樣。