## 什么是SQL注入
SQL注入攻擊(SQL Injection),簡稱注入攻擊,是Web開發中最常見的一種安全漏洞。可以用它來從數據庫獲取敏感信息,或者利用數據庫的特性執行添加用戶,導出文件等一系列惡意操作,甚至有可能獲取數據庫乃至系統用戶最高權限。
而造成SQL注入的原因是因為程序沒有有效過濾用戶的輸入,使攻擊者成功的向服務器提交惡意的SQL查詢代碼,程序在接收后錯誤的將攻擊者的輸入作為查詢語句的一部分執行,導致原始的查詢邏輯被改變,額外的執行了攻擊者精心構造的惡意代碼。
## [](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/09.4.md#sql注入實例)SQL注入實例
很多Web開發者沒有意識到SQL查詢是可以被篡改的,從而把SQL查詢當作可信任的命令。殊不知,SQL查詢是可以繞開訪問控制,從而繞過身份驗證和權限檢查的。更有甚者,有可能通過SQL查詢去運行主機系統級的命令。
下面將通過一些真實的例子來詳細講解SQL注入的方式。
考慮以下簡單的登錄表單:
~~~
<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里面`--`是注釋標記,所以查詢語句會在此中斷。這就讓攻擊者在不知道任何合法用戶名和密碼的情況下成功登錄了。
對于MSSQL還有更加危險的一種SQL注入,就是控制系統,下面這個可怕的例子將演示如何在某些版本的MSSQL數據庫上執行系統命令。
~~~
sql:="SELECT * FROM products WHERE name LIKE '%"+prod+"%'"
Db.Exec(sql)
~~~
如果攻擊提交`a%' exec master..xp_cmdshell 'net user test testpass /ADD' --`作為變量 prod的值,那么sql將會變成
~~~
sql:="SELECT * FROM products WHERE name LIKE '%a%' exec master..xp_cmdshell 'net user test testpass /ADD'--%'"
~~~
MSSQL服務器會執行這條SQL語句,包括它后面那個用于向系統添加新用戶的命令。如果這個程序是以sa運行而 MSSQLSERVER服務又有足夠的權限的話,攻擊者就可以獲得一個系統帳號來訪問主機了。
> 雖然以上的例子是針對某一特定的數據庫系統的,但是這并不代表不能對其它數據庫系統實施類似的攻擊。針對這種安全漏洞,只要使用不同方法,各種數據庫都有可能遭殃。
## [](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/09.4.md#如何預防sql注入)如何預防SQL注入
也許你會說攻擊者要知道數據庫結構的信息才能實施SQL注入攻擊。確實如此,但沒人能保證攻擊者一定拿不到這些信息,一旦他們拿到了,數據庫就存在泄露的危險。如果你在用開放源代碼的軟件包來訪問數據庫,比如論壇程序,攻擊者就很容易得到相關的代碼。如果這些代碼設計不良的話,風險就更大了。目前Discuz、phpwind、phpcms等這些流行的開源程序都有被SQL注入攻擊的先例。
這些攻擊總是發生在安全性不高的代碼上。所以,永遠不要信任外界輸入的數據,特別是來自于用戶的數據,包括選擇框、表單隱藏域和 cookie。就如上面的第一個例子那樣,就算是正常的查詢也有可能造成災難。
SQL注入攻擊的危害這么大,那么該如何來防治呢?下面這些建議或許對防治SQL注入有一定的幫助。
1. 嚴格限制Web應用的數據庫的操作權限,給此用戶提供僅僅能夠滿足其工作的最低權限,從而最大限度的減少注入攻擊對數據庫的危害。
2. 檢查輸入的數據是否具有所期望的數據格式,嚴格限制變量的類型,例如使用regexp包進行一些匹配處理,或者使用strconv包對字符串轉化成其他基本類型的數據進行判斷。
3. 對進入數據庫的特殊字符('"\尖括號&*;等)進行轉義處理,或編碼轉換。Go 的`text/template`包里面的`HTMLEscapeString`函數可以對字符串進行轉義處理。
4. 所有的查詢語句建議使用數據庫提供的參數化查詢接口,參數化的語句使用參數而不是將用戶輸入變量嵌入到SQL語句中,即不要直接拼接SQL語句。例如使用`database/sql`里面的查詢函數`Prepare`和`Query`,或者`Exec(query string, args ...interface{})`。
5. 在應用發布之前建議使用專業的SQL注入檢測工具進行檢測,以及時修補被發現的SQL注入漏洞。網上有很多這方面的開源工具,例如sqlmap、SQLninja等。
6. 避免網站打印出SQL錯誤信息,比如類型錯誤、字段不匹配等,把代碼里的SQL語句暴露出來,以防止攻擊者利用這些錯誤信息進行SQL注入。
## [](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/09.4.md#總結)總結
通過上面的示例我們可以知道,SQL注入是危害相當大的安全漏洞。所以對于我們平常編寫的Web應用,應該對于每一個小細節都要非常重視,細節決定命運,生活如此,編寫Web應用也是這樣。
- 第一章 Go環境配置
- 1.1 Go安裝
- 1.2 GOPATH 與工作空間
- 1.3 Go 命令
- 1.4 Go開發工具
- 1.5 小結
- 第二章 Go語言基礎
- 2.1 你好,Go
- 2.2 Go基礎
- 2.3 流程和函數
- 2.4 struct類型
- 2.5 面向對象
- 2.6 interface
- 2.7 并發
- 2.8 總結
- 第三章 Web基礎
- 3.1 Web工作方式
- 3.2 Go搭建一個Web服務器
- 3.3 Go如何使得Web工作
- 3.4 Go的http包詳解
- 3.5 小結
- 第四章 表單
- 4.1 處理表單的輸入
- 4.2 驗證表單的輸入
- 4.3 預防跨站腳本
- 4.4 防止多次遞交表單
- 4.5 處理文件上傳
- 4.6 小結
- 第五章 訪問數據庫
- 5.1 database/sql接口
- 5.2 使用MySQL數據庫
- 5.3 使用SQLite數據庫
- 5.4 使用PostgreSQL數據庫
- 5.5 使用beedb庫進行ORM開發
- 5.6 NOSQL數據庫操作
- 5.7 小結
- 第六章 session和數據存儲
- 6.1 session和cookie
- 6.2 Go如何使用session
- 6.3 session存儲
- 6.4 預防session劫持
- 6.5 小結
- 第七章 文本處理
- 7.1 XML處理
- 7.2 JSON處理
- 7.3 正則處理
- 7.4 模板處理
- 7.5 文件操作
- 7.6 字符串處理
- 7.7 小結
- 第八章 Web服務
- 8.1 Socket編程
- 8.2 WebSocket
- 8.3 REST
- 8.4 RPC
- 8.5 小結
- 第九章 安全與加密
- 9.1 預防CSRF攻擊
- 9.2 確保輸入過濾
- 9.3 避免XSS攻擊
- 9.4 避免SQL注入
- 9.5 存儲密碼
- 9.6 加密和解密數據
- 9.7 小結
- 第十章 國際化和本地化
- 10.1 設置默認地區
- 10.2 本地化資源
- 10.3 國際化站點
- 10.4 小結
- 第十一章 錯誤處理,調試和測試
- 11.1 錯誤處理
- 11.2 使用GDB調試
- 11.3 Go怎么寫測試用例
- 11.4 小結
- 第十二章 部署與維護
- 12.1 應用日志
- 12.2 網站錯誤處理
- 12.3 應用部署
- 12.4 備份和恢復
- 12.5 小結
- 第十三章 如何設計一個Web框架
- 13.1 項目規劃
- 13.2 自定義路由器設計
- 13.3 controller設計
- 13.4 日志和配置設計
- 13.5 實現博客的增刪改
- 13.6 小結
- 第十四章 擴展Web框架
- 14.1 靜態文件支持
- 14.2 Session支持
- 14.3 表單及驗證支持
- 14.4 用戶認證
- 14.5 多語言支持
- 14.6 pprof支持
- 14.7 小結
- 附錄A 參考資料