消减XSS攻击的几种编码

一、实体编码

将不可信数据插入到HTML标签之间时,应对这些数据进行HTML Entity编码,具体编码对照表如下。

显示结果描述实体名称实体编号
  空格    
< 小于号 &lt; &#60;
> 大于号 &gt; &#62;
& 和号 &amp; &#38;
" 引号 &quot; &#34;
' 撇号  &apos; (IE不支持) &#39;
分(cent) &cent; &#162;
£ 镑(pound) &pound; &#163;
¥ 元(yen) &yen; &#165;
欧元(euro) &euro; &#8364;
§ 小节 &sect; &#167;
© 版权(copyright) &copy; &#169;
® 注册商标 &reg; &#174;
商标 &trade; &#8482;
× 乘号 &times; &#215;
÷ 除号 &divide; &#247;

‘——&#x27;    不推荐将单引号( ‘ )编码为 &apos; 因为它并不是标准的HTML标签

/ ——&#x2F;

推荐使用OWASP提供的ESAPI函数库,它提供了一系列非常严格的用于进行各种安全编码的函数。HTML实体编码接口:

String encodedContent = ESAPI.encoder().encodeForHTML(request.getParameter(“input”));

二、HTML属性编码

将不可信数据插入到HTML属性里时,对这些数据进行HTML属性编码,不过需要注意的是,当要往HTML标签的事件处理属性(例如onmouseover)里插入数据的时候,应该对这些数据进行JavaScript编码。

[编码规则]

除了阿拉伯数字和字母,对其他所有的字符进行编码。编码后输出的格式为 &#xHH; (以&#x开头,HH则是指该字符对应的十六进制数字,分号作为结束符)。

可以使用ESAPI提供的函数进行HTML属性编码:

String encodedContent = ESAPI.encoder().encodeForHTMLAttribute(request.getParameter(“input”));

三、Script编码

在将不可信数据插入到script里时,对这些数据进行script编码。

主要针对动态生成的JavaScript代码,这包括脚本部分以及HTML标签的事件处理属性(Event Handler,如onmouseover, onload等)。

[编码规则]

除了阿拉伯数字和字母,对其他所有的字符进行编码,只要该字符的ASCII码小于256。编码后输出的格式为 \xHH (以 \x 开头,HH则是指该字符对应的十六进制数字)

可以使用ESAPI提供的函数进行JavaScript编码:


String encodedContent = ESAPI.encoder().encodeForJavaScript(request.getParameter(“input”));
四、CSS编码

当需要往Stylesheet,Style标签或者Style属性里插入不可信数据的时候,需要对这些数据进行CSS编码。传统印象里CSS不过是负责页面样式的,但是实际上它比我们想象的要强大许多,而且还可以用来进行各种攻击。因此,不要对CSS里存放不可信数据掉以轻心,应该只允许把不可信数据放入到CSS属性的值部分,并进行适当的编码。除此以外,最好不要把不可信数据放到一些复杂属性里,比如url, behavior等,只能被IE认识的Expression属性允许执行JavaScript脚本,因此也不推荐把不可信数据放到这里。

<style>
selector { property : …插入不可信数据前,进行CSS编码…}
 </style>
<style>
selector { property :  …插入不可信数据前,进行CSS编码… “}
 </style>
<span style=” property : …插入不可信数据前,进行CSS编码… ”></span>

[编码规则]

除了阿拉伯数字和字母,对其他所有的字符进行编码,只要该字符的ASCII码小于256。编码后输出的格式为 \HH (以 \ 开头,HH则是指该字符对应的十六进制数字)

可以使用ESAPI提供的函数进行CSS编码:

String encodedContent = ESAPI.encoder().encodeForCSS(request.getParameter(“input”));
五、URL编码

当需要往HTML页面中的URL里插入不可信数据的时候,需要对其进行URL编码,如下:


[编码规则]

除了阿拉伯数字和字母,对其他所有的字符进行编码,只要该字符的ASCII码小于256。编码后输出的格式为 %HH (以 % 开头,HH则是指该字符对应的十六进制数字)

在对URL进行编码的时候,有两点是需要特别注意的:

1) URL属性应该使用引号将值部分包围起来,否则攻击者可以很容易突破当前属性区域,插入后续攻击代码

2) 不要对整个URL进行编码,因为不可信数据可能会被插入到href, src或者其他以URL为基础的属性里,这时需要对数据的起始部分的协议字段进行验证,否则攻击者可以改变URL的协议,例如从HTTP协议改为DATA伪协议,或者javascript伪协议。

可以使用ESAPI提供的函数进行URL编码:


String encodedContent = ESAPI.encoder().encodeForURL(request.getParameter(“input”));

ESAPI还提供了一些用于检测不可信数据的函数,在这里我们可以使用其来检测不可信数据是否真的是一个URL:

String userProvidedURL = request.getParameter(“userProvidedURL”);
boolean isValidURL = ESAPI.validator().isValidInput
(“URLContext”, userProvidedURL, URL”, 255, false);
if (isValidURL) 
{<a href=”<%= encoder.encodeForHTMLAttribute(userProvidedURL) %>”>
</a>}

六、使用富文本时,使用XSS规则引擎进行编码过滤

Web应用一般都会提供用户输入富文本信息的功能,比如BBS发帖,写博客文章等,用户提交的富文本信息里往往包含了HTML标签,甚至是JavaScript脚本,如果不对其进行适当的编码过滤的话,则会形成XSS漏洞。但我们又不能因为害怕产生XSS漏洞,所以就不允许用户输入富文本,这样对用户体验伤害很大。

针对富文本的特殊性,我们可以使用XSS规则引擎对用户输入进行编码过滤,只允许用户输入安全的HTML标签,如<b>, <i>, <p>等,对其他数据进行HTML编码。需要注意的是,经过规则引擎编码过滤后的内容只能放在<div>, <p>等安全的HTML标签里,不要放到HTML标签的属性值里,更不要放到HTML事件处理属性里,或者放到<script>标签里。

推荐XSS规则过滤引擎:OWASP AntiSamp或者Java HTML Sanitizer

七、其他配合消减措施

1、对输入的数据进行黑白名单过滤;
2、为Cookie设置HttpOnly和Secure属性

附:使用ESAPI接口进行编码效果截图

 

 

 
posted @ 2020-03-23 21:17  Eleven_Liu  阅读(1297)  评论(0编辑  收藏  举报