|
@@ -15,6 +15,7 @@ import (
|
|
|
"github.com/PuerkitoBio/goquery"
|
|
|
"github.com/microcosm-cc/bluemonday"
|
|
|
"github.com/shopspring/decimal"
|
|
|
+ xhtml "golang.org/x/net/html"
|
|
|
"html"
|
|
|
"image"
|
|
|
"image/png"
|
|
@@ -2299,6 +2300,72 @@ func GetColorMap() map[int]string {
|
|
|
return colorMap
|
|
|
}
|
|
|
|
|
|
+// 检查src属性是否以http或data:image开头
|
|
|
+func isValidSrc(src string) bool {
|
|
|
+ validSchemes := regexp.MustCompile(`^(http|https|data:image):[\w\./?%&=]*$`)
|
|
|
+ return validSchemes.MatchString(src)
|
|
|
+}
|
|
|
+
|
|
|
+// ContentXssCheck 校验文本中的JS代码
|
|
|
+func ContentXssCheck(content string) (err error) {
|
|
|
+ // 解析HTML内容
|
|
|
+ node, err := xhtml.Parse(strings.NewReader(content))
|
|
|
+ if err != nil {
|
|
|
+ err = fmt.Errorf(" html.Parse Err: %v", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 遍历解析后的节点树,查找特定标签
|
|
|
+ var visit func(n *xhtml.Node) error
|
|
|
+ visit = func(n *xhtml.Node) error {
|
|
|
+ if n.Type == xhtml.ElementNode {
|
|
|
+ lowerData := strings.ToLower(n.Data)
|
|
|
+ switch lowerData {
|
|
|
+ case "script", "javascript":
|
|
|
+ err = fmt.Errorf(" script is forbidden")
|
|
|
+ return err
|
|
|
+ default:
|
|
|
+ for _, attr := range n.Attr { //判断事件
|
|
|
+ lowerKey := strings.ToLower(attr.Key)
|
|
|
+ lowerVal := strings.ToLower(attr.Val)
|
|
|
+ if lowerKey == "src" || lowerKey == "dynsrc" || lowerKey == "background" || lowerKey == "lowsrc" {
|
|
|
+ if !isValidSrc(lowerVal) {
|
|
|
+ err = fmt.Errorf("invalid src attribute value: %s", attr.Val)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if strings.HasPrefix(lowerKey, "on") {
|
|
|
+ err = fmt.Errorf("the event is forbidden: %s:%s", attr.Key, attr.Val)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if lowerKey == "style" {
|
|
|
+ if strings.Contains(lowerVal, "javascript:") || strings.Contains(lowerVal, "script:") {
|
|
|
+ err = fmt.Errorf("invalid style attribute value: %s", attr.Val)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* case "src":
|
|
|
+ // 如果<src>是某个标签的属性,你可能需要递归检查其父节点
|
|
|
+ // 这里简单起见,我们假设<src>不是有效的HTML标签,并忽略它
|
|
|
+ // 在实际中,你可能需要更复杂的逻辑来处理这种情况
|
|
|
+ fmt.Println("Warning: Unexpected 'src' tag found.")*/
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
|
|
|
+ if err = visit(c); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ // 检查HTML文档中的事件
|
|
|
+ if err = visit(node); err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
func ContentXssFilter(content string) (cleanContent string) {
|
|
|
p := customXssPolicy()
|
|
|
// The policy can then be used to sanitize lots of input and it is safe to use the policy in multiple goroutines
|