Merging other languages
This commit is contained in:
136
en/04.3.md
136
en/04.3.md
@@ -1,68 +1,68 @@
|
||||
# 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小节的例子
|
||||
|
||||
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>`,那么我们可以在浏览器上面看到输出如下所示:
|
||||
|
||||

|
||||
|
||||
图4.3 Javascript过滤之后的输出
|
||||
|
||||
Go的html/template包默认帮你过滤了html标签,但是有时候你只想要输出这个`<script>alert()</script>`看起来正常的信息,该怎么处理?请使用text/template。请看下面的例子:
|
||||
|
||||
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类型
|
||||
|
||||
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`后,变量的内容也不会被转义
|
||||
|
||||
转义的例子:
|
||||
|
||||
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, <script>alert('you have been pwned')</script>!
|
||||
|
||||
|
||||
|
||||
## links
|
||||
* [目录](<preface.md>)
|
||||
* 上一节: [验证的输入](<04.2.md>)
|
||||
* 下一节: [防止多次递交表单](<04.4.md>)
|
||||
# 4.3 Cross site scripting
|
||||
|
||||
Today's websites have much more dynamic content in order to improve user experience, which means that we must provide dynamic information depending on every individual's behavior. Unfortunately, there is a thing called "Cross site scripting" (known as "XSS") always attacking dynamic websites, from which static websites are completely fine at this time.
|
||||
|
||||
Attackers often inject malicious scripts like JavaScript, VBScript, ActiveX or Flash into those websites that have loopholes. Once they have successfully injected their scripts, user information can be stolen and your website can be flooded with spam. The attackers can also change user settings to whatever they want.
|
||||
|
||||
If you want to prevent this kind of attack, you should combine the two following approaches:
|
||||
|
||||
- Verification of all data from users, which we talked about in the previous section.
|
||||
- Carefully handle data that will be sent to clients in order to prevent any injected scripts from running on browsers.
|
||||
|
||||
So how can we do these two things in Go? Fortunately, the `html/template` package has some useful functions to escape data as follows:
|
||||
|
||||
- `func HTMLEscape(w io.Writer, b []byte)` escapes b to w.
|
||||
- `func HTMLEscapeString(s string) string` returns a string after escaping from s.
|
||||
- `func HTMLEscaper(args ...interface{}) string` returns a string after escaping from multiple arguments.
|
||||
|
||||
Let's change the example in section 4.1:
|
||||
|
||||
fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) // print at server side
|
||||
fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
|
||||
template.HTMLEscape(w, []byte(r.Form.Get("username"))) // responded to clients
|
||||
|
||||
If someone tries to input the username as `<script>alert()</script>`, we will see the following content in the browser:
|
||||
|
||||

|
||||
|
||||
Figure 4.3 JavaScript after escaped
|
||||
|
||||
Functions in the `html/template` package help you to escape all HTML tags. What if you just want to print `<script>alert()</script>` to browsers? You should use `text/template` instead.
|
||||
|
||||
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>")
|
||||
|
||||
Output:
|
||||
|
||||
Hello, <script>alert('you have been pwned')</script>!
|
||||
|
||||
Or you can use the `template.HTML` type :
|
||||
Variable content will not be escaped if its type is `template.HTML`.
|
||||
|
||||
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>"))
|
||||
|
||||
Output:
|
||||
|
||||
Hello, <script>alert('you have been pwned')</script>!
|
||||
|
||||
One more example of escaping:
|
||||
|
||||
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>")
|
||||
|
||||
Output:
|
||||
|
||||
Hello, <script>alert('you have been pwned')</script>!
|
||||
|
||||
## Links
|
||||
|
||||
- [Directory](preface.md)
|
||||
- Previous section: [Verification of inputs](04.2.md)
|
||||
- Next section: [Duplicate submissions](04.4.md)
|
||||
|
||||
Reference in New Issue
Block a user