Files
build-web-application-with-…/zh-tw/04.3.md
2019-02-26 01:40:54 +08:00

73 lines
3.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 4.3 預防跨站指令碼
現在的網站包含大量的動態內容以提高使用者體驗比過去要複雜得多。所謂動態內容就是根據使用者環境和需要Web應用程式能夠輸出相應的內容。動態站點會受到一種名為“跨站指令碼攻擊”Cross Site Scripting, 安全專家們通常將其縮寫成 XSS的威脅而靜態站點則完全不受其影響。
攻擊者通常會在有漏洞的程式中插入JavaScript、VBScript、 ActiveX或Flash以欺騙使用者。一旦得手他們可以盜取使用者帳戶資訊修改使用者設定盜取/汙染cookie和植入惡意廣告等。
對XSS最佳的防護應該結合以下兩種方法一是驗證所有輸入資料有效檢測攻擊(這個我們前面小節已經有過介紹);另一個是對所有輸出資料進行適當的處理,以防止任何已成功注入的指令碼在瀏覽器端執行。
那麼Go裡面是怎麼做這個有效防護的呢Go的html/template裡面帶有下面幾個函式可以幫你轉義
- func HTMLEscape(w io.Writer, b []byte) //把b進行轉義之後寫到w
- func HTMLEscapeString(s string) string //轉義s之後返回結果字串
- func HTMLEscaper(args ...interface{}) string //支援多個引數一起轉義,返回結果字串
我們看4.1小節的例子
```Go
fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) //輸出到伺服器端
fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
template.HTMLEscape(w, []byte(r.Form.Get("username"))) //輸出到客戶端
```
如果我們輸入的username是`<script>alert()</script>`,那麼我們可以在瀏覽器上面看到輸出如下所示:
![](images/4.3.escape.png?raw=true)
圖4.3 Javascript過濾之後的輸出
Go的html/template套件預設幫你過濾了html標籤但是有時候你只想要輸出這個`<script>alert()</script>`看起來正常的資訊該怎麼處理請使用text/template。請看下面的例子
```Go
import "text/template"
...
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
```
輸出
Hello, <script>alert('you have been pwned')</script>!
或者使用template.HTML型別
```Go
import "html/template"
...
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
err = t.ExecuteTemplate(out, "T", template.HTML("<script>alert('you have been pwned')</script>"))
```
輸出
Hello, <script>alert('you have been pwned')</script>!
轉換成`template.HTML`後,變數的內容也不會被轉義
轉義的例子:
```Go
import "html/template"
...
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
```
轉義之後的輸出:
Hello, &lt;script&gt;alert(&#39;you have been pwned&#39;)&lt;/script&gt;!
## links
* [目錄](<preface.md>)
* 上一節: [驗證的輸入](<04.2.md>)
* 下一節: [防止多次遞交表單](<04.4.md>)