一个 Golang 版本 XSS 过滤模块
go-xss 根据白名单过滤 HTML(防止 XSS 攻击)
go-xss is a module used to filter input from users to prevent XSS attacks
go-xss是一个用于对用户输入的内容进行过滤,以避免遭受 XSS 攻击的模块(( 什么是 XSS 攻击? )。主要用于论坛、博客、网上商店等等一些可允许用户录入页面排版、格式控制相关的 HTML 的场景,xss模块通过白名单来控制允许的标签及相关的标签属性,另外还提供了一系列的接口以便用户扩展,比其他同类模块更为灵活。
English | 中文文档
特性
- 白名单控制允许的 HTML 标签及各标签的属性
- 通过自定义处理函数,可对任意标签及其属性进行处理
性能
speed: 24MB/s
安装
go get -u github.com/feiin/go-xss
使用
import ( "github.com/feiin/go-xss" ) source := "link" safeHtml := xss.FilterXSS(source,xss.XssOption{})
import ( "github.com/feiin/go-xss" ) source := "link" x := xss.NewXSS(xss.XssOption{}) safeHtml := x.Process(source)
自定义过滤规则(options)
在调用 xss
进行过滤时,可通过options参数来设置自定义规则:
source := "link" options := xss.XssOption{} safeHtml := xss.FilterXSS(source,options)
如果不想每次都传入一个 options 参数,可以创建一个 XSS 实例:
source := "link" options := xss.XssOption{} x := xss.NewXSS(options) safeHtml := x.Process(source)
白名单
通过 WhiteList 来指定,格式类型为: map[string][]string
。不在白名单上的标签将被过滤,不在白名单上的属性也会被过滤。以下是示例:
// 只允许a标签,该标签只允许href, title, target这三个属性 options.WhiteList = map[string][]string { "a":{"href","title","target"}, } // 使用以上配置后,下面的HTML // 大家好 // 将被过滤为 // 大家好
默认白名单参考 xss.GetDefaultWhiteList()
自定义匹配到标签时的处理方法
通过 OnTag
来指定相应的处理函数。以下是详细说明:
func onTag(tag, html string, options TagOption) *string { // tag是当前的标签名称,比如标签,则tag的值是'a' // html是该标签的HTML,比如标签,则html的值是'' // options是一些附加的信息,具体如下: // isWhite boolean类型,表示该标签是否在白名单上 // isClosing boolean类型,表示该标签是否为闭合标签,比如时为true // position integer类型,表示当前标签在输出的结果中的起始位置 // sourcePosition integer类型,表示当前标签在原HTML中的起始位置 // 如果返回一个字符串,则当前标签将被替换为该字符串 // 如果返回nil,则使用默认的处理方法: // 在白名单上: 通过onTagAttr来过滤属性,详见下文 // 不在白名单上:通过onIgnoreTag指定,详见下文 }
自定义匹配到标签的属性时的处理方法
通过 OnTagAttr
来指定相应的处理函数。以下是详细说明:
func OnTagAttr(tag, name, value string,isWhiteAttr bool) *string { // tag是当前的标签名称,比如标签,则tag的值是'a' // name是当前属性的名称,比如href="#",则name的值是'href' // value是当前属性的值,比如href="#",则value的值是'#' // isWhiteAttr是否为白名单上的属性 // 如果返回一个字符串,则当前属性值将被替换为该字符串 // 如果返回nil,则使用默认的处理方法 // 在白名单上: 调用safeAttrValue来过滤属性值,并输出该属性,详见下文 // 不在白名单上:通过onIgnoreTagAttr指定,详见下文 }
自定义匹配到不在白名单上的标签时的处理方法
通过 OnIgnoreTag
来指定相应的处理函数。以下是详细说明:
func OnIgnoreTag(tag, html string, options TagOption) *string { // 参数说明与onTag相同 // 如果返回非nil,则当前标签将被替换为该字符串 // 如果返回nil,则使用默认的处理方法(通过escape指定,详见下文) }
自定义匹配到不在白名单上的属性时的处理方法
通过 OnIgnoreTagAttr
来指定相应的处理函数。以下是详细说明:
func OnIgnoreTagAttr(tag,name, value string,isWhiteAttr bool) *string { // 参数说明与onTagAttr相同 // 如果返回一个字符串,则当前属性值将被替换为该字符串 // 如果返回nil,则使用默认的处理方法(删除该属) }
自定义 HTML 转义函数
通过 EscapeHtml
来指定相应的处理函数。以下是默认代码 (不建议修改) :
func EscapeHTML(html string) string { return regGT.ReplaceAllString(regLT.ReplaceAllString(html,"") }
自定义标签属性值的转义函数
通过 SafeAttrValue
来指定相应的处理函数。以下是详细说明:
func SafeAttrValue(tag, name, value string) string { // 参数说明与onTagAttr相同(没有options参数) // 返回一个字符串表示该属性值 }
自定义 CSS 过滤器
TODO
快捷配置
去掉不在白名单上的标签
通过 StripIgnoreTag
来设置:
- true:去掉不在白名单上的标签
- false:(默认),使用配置的escape函数对该标签进行转义 示例:
当设置 StripIgnoreTag = true时,以下代码
code:alert(/xss/);
过滤后将输出
code:alert(/xss/);
去掉不在白名单上的标签及标签体
通过 StripIgnoreTagBody
来设置:
nil []string{} []string{"tag1", "tag2"}
示例:
当设置 StripIgnoreTagBody = []string{"script"}时,以下代码
code:alert(/xss/);
过滤后将输出
code:
去掉 HTML 备注
通过 AllowCommentTag
来设置:
- true:不处理
- false:(默认),自动去掉 HTML 中的备注 示例:
当设置 AllowCommentTag = false
时,以下代码
code: END
过滤后将输出
code: END
应用实例
允许标签以 data-开头的属性
source := "hello"; html := xss.FilterXSS(source,xss.XssOption{ OnIgnoreTagAttr: func(tag,name, value string,isWhiteAttr bool) *string { if len(name)>=5 && name[0:5] == "data-" { ret := name + "=\"" + xss.EscapeAttrValue(value)+"\"" return &ret } return nil }, }) fmt.Printf("%s\nconvert to:\n%s", source, html);
运行结果:
helloconvert to:hello
允许名称以 x-开头的标签
source := "hewwww"; html := xss.FilterXSS(source,xss.XssOption{ OnIgnoreTag: func(tag, html string, options xss.TagOption) *string { if len(tag)>=2 && tag[0:2] == "x-" { return &html; } return nil }, }) fmt.Printf("%s\nconvert to:\n%s", source, html);
运行结果
hewwww convert to: hewwww
分析 HTML 代码中的图片列表
source := "a
b
c
d" var list []string html := xss.FilterXSS(source,xss.XssOption{ OnTagAttr: func(tag, name, value string ,isWhiteAttr bool) *string { if tag == "img" && name == "src" { list = append(list,value) } return nil }, }) fmt.Printf("image list:\n%s", strings.Join(list, ","));
运行结果:
image list: img1, img2, img3, img4
去除 HTML 标签(只保留文本内容)
source := "helloalert(/xss/);end" html := xss.FilterXSS(source,xss.XssOption{ WhiteList:map[string][]string{}, // // empty, means filter out all tags StripIgnoreTag:true, // filter out all HTML not in the whitelist StripIgnoreTagBody:[]string{"script"}, // the script tag is a special case, we need }) fmt.Printf("text: %s", html);
运行结果:
text: helloend
Inspirations
License
MIT