XSLT是一种把xml标记语言转换成其他语言的标准?
基本上碰到的模式就是用户的data tree和描述样式的stylesheet通过浏览器或者其他XSLT的解析引擎Transform后生成html给前端浏览器解析和展示。
从时间点上来看,XSLT是浏览器在html解析前执行的一个转换操作,是在js/html 解析之前的行为。
XSLT通过内建的编码机制来防止xss问题。在data tree进入XSLT过程中会先对data tree中的节点进行一次HTMLDECODE,然后再作为源进行Transform。这样原有的通过编码方式防止XSS的方法就直接不起作用了。
测试中发现,在正常的输出过程中,如果data tree的某个节点的数据中包含html tag的话,则默认xslt引擎会对其中的<和>进行Encode处理,确保不会由数据生成一个新的html tag。
但是在w3c中没有找到相关的描述,只有以下这段:
Normally, the xml output method escapes & and < (and possibly other characters) when outputting text nodes. This ensures that the output is well-formed XML
比较疑惑的是全文没有提到在html output中是否也遵循这样的规范,只是提了一句:
The html output method should not output an element differently from the xml output method unless the expanded-name of the element has a null namespace URI
测试中发现MSXML和Transformiix中对这点是有支持的,即从data tree中来的数据不会破坏stylesheet中描述的html 结构。这样,就保证了用户数据通过Transform后不会造成html inject(不会注入新的tag,不会跳出原有的event等属性).
其中,MSXML还支持另外一个属性
For this reason, XSLT provides a mechanism for disabling output escaping. An xsl:value-of or xsl:text element may have a disable-output-escaping attribute; the allowed values are yes or no; the default is no; if the value is yes, then a text node generated by instantiating the xsl:value-of or xsl:text element should be output without any escaping.
即如果在构造stylesheet的时候对输出标明了disable-output-escaping="yes"
则直接可以输出原样输出data tree的内容,这些点很容易就可以造成XSS,好在默认是no的。只需要确保stylesheet中不出现disable-output-escaping="yes"就可以了。
比较郁闷的是以下这段:
The html output method should not perform escaping for the content of the script and style elements.
The html output method should not escape < characters occurring in attribute values.
测试发现,无论是MSXML还是Transformiix都很“严格”的遵守了规范,对attribute value 和script/style中的输出没做encode的处理。导致可以通过data tree中节点的构造往里面插入自己的js代码
如:
<script>
<xsl:value-of select="catalog/cd/testdata" />
</script>
其中的testdata节点如下:
<testdata>var s = /suddy/; alert(s);alert("s");</testdata>
经过Transform后,则变成
<SCRIPT>var s = /suddy/; alert(s);alert("s");</SCRIPT>
目前的想法只能是清洗删除data tree中碰到的" ' /符号,这样就算注入后,也无法定义js的string对象。但是无法防止注入alert(1);这种的纯数字参数的js函数或调用。
不过这样会对业务方产生影响,他们将无法通过数据输入" ' / 。
收工,先记录这些,回头想想看有没其他可以用的办法。
附推荐看到的一个工具:Internet Explorer Tools for Validating XML and Viewing XSLT Output
可以看到IE中经过XSLT后输出的html文档代码的样子,这个在有些时候很好用,安装完成后右键->查看生成的源码。 就可以看了。
http://www.microsoft.com/downloads/details.aspx?FamilyID=d23c1d2c-1571-4d61-bda8-adf9f6849df9&displaylang=en
FF下也有一款同样强大的扩展:XSL Results
https://addons.mozilla.org/zh-CN/firefox/addon/5023
使用他们能够很方便的查看XSLT后输出的html代码而不需要像原来一样在dom里面查找。强力推荐。
参考:
http://www.w3.org/TR/xslt
http://hi.baidu.com/lanxmail/blog/item/0a699fb77d1c41f530add1cf.html
http://www.w3schools.com/xsl/
https://developer.mozilla.org/en/XSLT/Elements
附上test case:
a.rar
#1