XSS(Cross Site Scripting):跨站脚本攻击,攻击者会在有漏洞的程序中插入恶意脚本以盗取、修改相关信息。
对XSS的防护应结合以下方法:
- 验证所有输入数据,有效检测攻击
- 对所有输出数据进行适当处理,以防止任何成功注入的脚本在浏览器运行
Golang的html/template带有几个函数进行转义,以达到防护XSS攻击的目的
- func HTMLEscape(w io.Writer,b []byte) //将b进行转义之后写入w
- func HTMLEscapeString(s string) string //转义s之后返回结果
- func HTMLEscaper(args ...interface{}) string //支持多参数转义
示例如下:
-- my_server2.go
package myserver
import (
"log"
"net/http"
"text/template"
)
func login2(rw http.ResponseWriter, r *http.Request) {
//解析请求参数
r.ParseForm()
log.Println("HTTP Method : ", r.Method)
if r.Method == "GET" {
//解析模板文件
t, err := template.ParseFiles("./resources/html/login.html")
if err != nil {
log.Fatal("Parse file error ", err.Error())
}
//将渲染后的模板写入响应
t.Execute(rw, nil)
} else {
//记录转义后的结果
log.Println("username:", template.HTMLEscapeString(r.Form.Get("username")))
log.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
//将转义后的username返回
template.HTMLEscape(rw, []byte(r.Form.Get("username")))
}
}
//StartMyServer3 start server3
func StartMyServer3() {
log.Println("Server3 starting")
//配置访问路由
http.HandleFunc("/login", login2)
//监听端口
err := http.ListenAndServe(":9090", nil)
if err != nil {
log.Fatal("ListenAndServe error:", err.Error())
}
}
-- main.go
package main
import "GoWebAppNotes/src/myserver"
func main() {
myserver.StartMyServer3()
}向localhost:9090/login发送POST请求,username为<script>alter()</scrip>
curl -X POST -d "username=<script>alter()</scrip>" 127.0.0.1:9090/login
<script>alter()</scrip>此处的js脚本会被转义,过滤了html标签
若想要输出正常的html标签,可使用template包的函数
//在方法login2上加上如下语句
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
if err != nil {
log.Fatal("ParseError:", err.Error())
}
err = t.ExecuteTemplate(rw, "T", "<script>alert('you have been pwned')</script>")此时可返回正常的html标签
curl -X POST 127.0.0.1:9090/login
</br>Hello, <script>alert('you have been pwned')</script>!