xss攻击最终应对方案
Tag markdown, epiceditor, xss, 后端, 过滤, on by view 3702

今天终于解决了xss这个潜在的问题,编辑器使用的是Markdown编辑器EpicEditor,EpicEditor是一款Markdown编辑器,或者说是一款可以自己定制的编辑器。后台Markdown解析器用的是"github.com/russross/blackfriday",后台代码

func Markdown2HTML(content string) string {
	content = html.EscapeString(content)
	output := blackfriday.MarkdownCommon([]byte(content))
	return string(output)
}

直接将markdown语法的串解析为html语法的串,后台还设置了一个markdown解析api后面待用,api的controller代码如下

// parse markdown
type MarkdownController struct {
	controllers.BaseController
}

func (this *MarkdownController) Get() {
	this.Data["json"] = map[string]interface{}{
		"result": false,
		"msg":    "only post method support",
		"refer":  nil,
	}

	this.ServeJson()
}

func (this *MarkdownController) Post() {
	content := this.GetString("content")

	log.Blueln(content)
	rst := utils.Markdown2HTML(content)

	this.Data["json"] = map[string]interface{}{
		"result":  true,
		"msg":     "success",
		"preview": rst,
		"refer":   nil,
	}

	this.ServeJson()
}

前端将串传给后端,这个串期望是纯markdown的,因此如果其中夹杂着有html语法,html将会被转义,之后返回带有解析后的html串。

前端的EpicEditor默认是能够解析Markdown和兼容HTML的,甚至不过滤js(这个问题我已经向项目作者反馈过,他决定之后会给其添加选项以禁用js),由于我之前的文章提到css都会给用户机会造成页面混乱,而我所找到的过滤器只支持xss过滤,即只过滤js不过滤css,并且那个过滤器有一个依赖包在墙外,这将会是很蛋疼,所以决定使用markdown,是纯markdown。EpicEditor是兼容html的,因此不满足我的需求,于是我问EpicEditor的作者是否有禁用html的选项(传送),他告诉我EpicEditor不负责解析的,解析器可以自己定制,EpicEditor默认使用的解析器是markd解析器,然后给了我一个页面,其上有定制解析器的demo

var editor = new EpicEditor({
  parser: function (str) {
    var blacklist = ['foo', 'bar', 'baz'];
    return str.split(' ').map(function (word) {
      // If the word exists, replace with asterisks
      if (blacklist.indexOf(word) > -1) {
        return '****'
      }
      return word;
    }).join(' ');
  }
}).load();

自己重做一个解析器?看一下markd项目的代码有多少吧,重做工作量太大。仔细分析上面的代码发现parser是一个函数,它的作用是这样的,传入原串,返回解析后的串。这回我之前留的api起作用了,自己实现的parser函数如下

parser: function (str) {
	var rst = $.ajax({
		async: false,
		type: "post",
		url: "/api/markdown/preview",
		data: {"content": str},
		dataType:"json",

	}).responseText;
	var json = eval('('+rst+')')
	console.log(json);
	return json.preview;
},

是的,我将原数据传给服务器去解析,得到结果,这样还有一个好处就是保证了解析器的一致性,即最终结果与编辑器preview结果是一致的。当然这也是有一些缺点的,那就是给服务器增加了负担,不过我觉得这是值得的。最后附上编辑器工作的截图

epiceditor_back_end_anti_xss.png

问题能够得以解决应当感谢各个开源项目以及其作者的无私奉献,还有他们的热心答疑,取之于开源用之于开源,Goj也会是一个开源项目,愿早日完成。