跨站点攻击(XSS)是一个WEB应用经常面对的问题,一个安全性不好的网站,很容易就被一些低级的hacker通过xss来攻击。
在.NET里,微软有官方出品一个.NET AntiXSS Library
类库,用来帮助developer简单应对跨站点攻击的问题。在java里,同样也有一个类似的类库coverity-security-library
,这个类库是Coverity公司出品的。
关于Coverity公司: Coverity是开发测试行业的领头人,也是那些需要防止软件故障损害公司品牌和底线的公司的信赖标准。全球有超过1100个像Honeywell, NEC, BAE Systems, Juniper Networks, BMC Software, Samsung, France Telecom, Sega, 和 Schneider Electric这样的国际品牌依靠Coverity确保其产品和服务的质量与安全。诸多行业领先领头人利用Coverity交付高质量产品、维护竞争优势并增强客户满意度和创新能力。
类库支持
这套类库里主要有两种方式:
Escaper
Escaper是对输入的任何字符根据在Html中出现的位置不同,采用不同的转义方式,下面是类库中提供的方法以及对应的转义列表:
- Escape.cssString(String)
CSS string characters: ‘ (U+0022), “ (U+0027), \ (U+005C)
HTML characters: / (U+002F), < (U+003C), > (U+003E), & (U+0026)
Control characters: \b (U+0008), \t (U+0009), \n (U+000A), \f (U+000C), \r (U+000D)
Unicode newlines: LS (U+2028), PS (U+2029) - Escape.html(String)
HTML characters: ‘ (U+0022), “ (U+0027), \ (U+005C), / (U+002F), < (U+003C), > (U+003E), & (U+0026)
Control characters: \t (U+0009), \n (U+000A), \f (U+000C), \r (U+000D), SPACE (U+0020)
Unicode newlines: LS (U+2028), PS (U+2029) - Escape.htmlText(String)
HTML characters: ‘ (U+0022), “ (U+0027), < (U+003C), > (U+003E), & (U+0026)
- Escape.jsRegex(String)
Regex characters: \ (U+005C), / (U+002F), ( (U+0028), [ (U+005B), { (U+007B), ] (U+005D), } (U+007D), ) (U+0029), * (U+002A), + (U+002B), - (U+002D), . (U+002E), ? (U+003F), ! (U+0021), ^ (U+005E), $ (U+0024), | (U+007C)
Control characters: \t (U+0009), \n (U+000A), \v (U+000B), \f (U+000C), \r (U+000D) - Escape.jsString(String)
JS String characters: ‘ (U+0022), “ (U+0027), \ (U+005C)
URI encoding characters: % (U+0025)
HTML characters: / (U+002F), < (U+003C), > (U+003E), & (U+0026)
Control characters: \b (U+0008), \t (U+0009), \n (U+000A), 0x0b (U+000B), \f (U+000C), \r (U+000D)
Unicode newlines: LS (U+2028), PS (U+2029) - Escape.sqlLikeClause(String)
SQL LIKE characters: _ (U+005F), % (U+0025), @ (U+0040)
- Escape.sqlLikeClause(String, char)
和上面的
sqlLikeClause
一样,只是可以允许指定特定字符不需要转义 - Escape.uriParam(String)
URI characters: ‘ (U+0022), “ (U+0027), \ (U+005C), / (U+002F), < (U+003C), > (U+003E), & (U+0026), < (U+003C), > (U+003E), ! (U+0021), # (U+0023), $ (U+0024), % (U+0025), ( (U+0028), ) (U+0029), * (U+002A), + (U+002B), , (U+002C), . (U+002E), : (U+003A), ; (U+003B), = (U+003D), ? (U+003F), @ (U+0040), [ (U+005B), ] (U+005D)
Control characters: \t (U+0009), \n (U+000A), \f (U+000C), \r (U+000D), SPACE (U+0020) - Escape.uri(String)
目前实现和上面
uriParam
完全一样
Filter
Filter是单一转义不能满足的,对有些地方的输入是要求有特定的数据格式的,如果不符合,则转换为更安全的数据格式:
- Filter.asCssColor(String)
输入为颜色定义(暂时不支持rgb方式),如果输入的不是css颜色格式,则返回
invalid
- Filter.asCssColor(String, String)
同上,第二个参数为默认值,即,如果输入不是可识别的颜色格式,则返回默认值
- Filter.asNumber(String)
只接受八进制、十进制、十六进制的数字型内容,如不是,则返回0
- Filter.asNumber(String, String)
同上
asNumber
,如果不能,则返回默认值(第二个参数) - Filter.asURL(String)
对URL进行判断,如果schema为
http|https|ftp|mailto
则返回,否则返回相对路径(在input前面添加./
) - Filter.asFlexibleURL(String)
对URL进行判断,如果schema不为
javascript|vbscript|data|about
,则返回输入,否则返回相对路径(在input前面添加./
)
如何使用
使用时,根据出现的位置不同,使用不同的方法。唯一的区别是java代码和jsp代码中有些区别。
在jsp中,需要使用对应的jsp EL,如下:
<%@ taglib uri="http://coverity.com/security" prefix="cov" %> |
java代码中,按下面方式使用:
import com.coverity.security.Escape; |
使用时,需根据要转义代码出现的位置来使用,如果同时满足多个条件,则需要使用复合形式,如在a标签里href里出现的javascript代码,它满足:
- 在html属性里
- 在url的位置上
- 是javascript代码的一部分
这种情况则需要按照下面的方式才能输入更安全的代码:<a href="javascript:hello('${cov:htmlEscape(cov:uriEncode(cov:jsStringEscape(content)))}')">