XSS编码

对xss编码的思考:

一段文本输入,不是字符串就是代码。代码之所以为代码,是因为解析器认识他。

​ 以后端以PHP为例,常用的编码方式是htmlspecialchars($str),这种方式会将",<,>等转化成html实体编码,对于PHP来说这是一个文本替换处理。但是输送到了浏览器端,需要解析渲染他,html解析器会将将其转化为实体,就是真的是输出这个符号,而不是解析成html标签。解析器也不会为此发生状态变化。所以一段输入的内容被当作代码执行的关键点就是,关键词能够被解析,即能让解析器发生状态转移。而xss能够触发,需要转移到一个能够调用js解析器的状态。

截屏2020-05-09 下午12.03.29

​ 这里的html解析器,让状态机从data转移到tag open所consume的"<"是真正的"<"而不是"&lt;",所以这时如果有,<a href="javascrpt: alert(1)>click</a> 这句话中js被解释的地方显然是javascript:{}中,这个地方如何处理的呢? 首先看html是否解析他。

截屏2020-05-09 下午2.54.38

t编码成&#x74;

截屏2020-05-09 下午2.56.52

​ 我们看到解析了,成为了alert(1),点击也可以执行。为什么可以执行,在js被调用解析之前,字符&#x74已经被html解析器解析了,翻译成了t,html解析器知道这个t是实体,不做状态转化。但是js解析器处理起来,没有区别。在js解析器的落点里,我们同样可以用js认识的编码规则。可以使用unicode编码,甚至js内部函数。

截屏2020-05-09 下午3.11.38

​ 虽然在解析中,也需要遵循解析器本身的规则。如括号,引号等被unicode编码了就不解析(详见参考2)。url解析器也同样的,在<a href={}>中,因为是一个资源加在动作,所以可以触发url解析器。在url解析器规则中,包含协议名: 不能使用url编码。因此此处不可以将javascript:进行url编码,但是可以html编码。

​ 结合HTML, URL,Javascript三者的解析顺序、编码集、以及编码规则。根据我们输入的落点环境情况,就能够构造出可以"召唤"js解析器不能够绕过安全防护的payload。

CASE

截屏2020-05-09 下午4.27.11

规则1 - 属性名不能html编码

规则2 - javascript:不能url编码

规则3 - 括号不能unicode编码

参考

[1] 解析器

[2] https://www.attacker-domain.com/2013/04/deep-dive-into-browser-parsing-and-xss.html