xss解决方案
XSS的本质还是一种“HTML注入”,用户的数据被当成了HTML代码一部分来执行,从而混淆了原本的语义,产生了新的语义。
一、HttpOnly
游览器将禁止页面的javascript访问带有HttpOnly属性的cookie
HttpOnly并非为了对抗XSS——HttpOnly解决的是XSS后的Cookie劫持攻击。
如果该Cookie设置了HttpOnly,则这种攻击会失败,因为JavaScript读取不到Cookie的值。
一个Cookie的使用过程如下。
- Step1:浏览器向服务器发起请求,这时候没有Cookie。
- Step2:服务器返回时发送Set-Cookie头,向客户端浏览器写入Cookie。
- Step3:在该Cookie到期前,浏览器访问该域下的所有页面,都将发送该Cookie。
二、输入检查
常见的Web漏洞如XSS、SQL Injection等,都要求攻击者构造一些特殊字符,这些特殊字符可能是正常用户不会用到的,所以输入检查就有存在的必要了。
在XSS的防御上,输入检查一般是检查用户输入的数据中是否包含一些特殊字符,如<
、>
、'
、"
等。如果发现存在特殊字符,则将这些字符过滤或者编码。比较智能的“输入检查”,可能还会匹配XSS的特征。比如查找用户数据中是否包含了<script>
、javascript
等敏感字符。
这种输入检查的方式,可以称为XSS Filter
。互联网上有很多开源的XSS Filter
的实现。
三、输出检查
一般来说,除了富文本的输出外,在变量输出到HTML页面时,可以使用编码或转义的方式来防御XSS攻击。
安全的编码函数
编码分为很多种,
1、HTML代码的编码方式是HtmlEncode
。对抗XSS,在HtmlEncode中要求至少转换以下字符:
& --> &
< --> <
> --> >
" --> "
' --> '
/ --> /
- 包含反斜线是因为它可能会闭合一些
HTML entity
- 所有在标签中输出的变量,如果未做任何处理,都能导致直接产生XSS
2、JavaScript的编码方式可以使用JavascriptEncode。
方法使用“\”对特殊字符进行转义。在对抗XSS时,还要求输出的变量必须在引号内部,
- <script>标签中输出在<script>标签中输出时
- 在事件中输出
<a href="#" onclick="funcA('$var')">test</a>
3、在CSS中输出在CSS和style、style attribute中形成XSS 使用encodeForCSS()
。
- 尽可能禁止用户可控制的变量在“<style>标签”、“HTML标签的style属性” “CSS文件” 输出
- 将除了字母、数字外的所有字符都编码成十六进制形式”\uHH“。
4、在地址中输出: 在URL的path(路径)或者search(参数)中输出,使用URLEncode
。
方法使用“\”对特殊字符进行转义。在对抗XSS时,还要求输出的变量必须在引号内部,
- URLEncode会将字符转换为“%HH”形式,比如空格就是“%20”,“<”符号是“%3c”
<a href="http://www.evil.com/?test=" onclick=alert(1)"" >test</a>
四、处理富文本
如何区分安全的“富文本”和有攻击性的XSS呢?在处理富文本时,还是要回到“输入检查”的思路上来。“输入检查”的主要问题是,在检查时还不知道变量的输出语境。但用户提交的“富文本”数据,其语义是完整的HTML代码,在输出时也不会拼凑到某个标签的属性中。因此可以特殊情况特殊处理。
列出了所有在HTML中可能执行脚本的地方。而一个优秀的“XSS Filter”,也应该能够找出HTML代码中所有可能执行脚本的地方。
HTML是一种结构化的语言,比较好分析。通过htmlparser可以解析出HTML代码的标签、标签属性和事件。
在过滤富文本时,“事件”应该被严格禁止,因为“富文本”的展示需求里不应该包括“事件”这种动态效果。而一些危险的标签,比如<iframe>、<script>、<base>、<form>等,也是应该严格禁止的。
在标签的选择上,应该使用白名单,避免使用黑名单。比如,只允许<a>、<img>、<div>等比较“安全”的标签存在。“白名单原则”不仅仅用于标签的选择,同样应该用于属性与事件的选择。
如果一定要允许用户自定义样式,则只能像过滤“富文本”一样过滤“CSS”。这需要一个CSSParser对样式进行智能分析,检查其中是否包含危险代码。有一些比较成熟的开源项目,实现了对富文本的XSS检查。
CSRF的防御
概述: CSRF攻击的过程,往往是在用户不知情的情况下构造了网络请求。
防御方法
一、验证码
验证码强制用户必须与应用进行交互,才能完成最终请求。因此在通常情况下,验证码能够很好地遏制CSRF攻击。但是验证码并非万能。很多时候,出于用户体验考虑,网站不能给所有的操作都加上验证码。因此,验证码只能作为防御CSRF的一种辅助手段,而不能作为最主要的解决方案。
二、Referer Check
Referer Check在互联网中最常见的应用就是“防止图片盗链”。同理,Referer Check也可以被用于检查请求是否来自合法的“源”。
Referer Check的缺陷在于,服务器并非什么时候都能取到Referer。很多用户出于隐私保护的考虑,限制了Referer的发送。在某些情况下,浏览器也不会发送Referer,比如从HTTPS跳转到HTTP,出于安全的考虑,浏览器也不会发送Ref-erer。
三、Anti CSRF Token
现在业界针对CSRF的防御,一致的做法是使用一个Token。
点击劫持
点击劫持是一种视觉上的欺骗手段。攻击者使用一个透明的、不可见的iframe,覆盖在一个网页上,然后诱使用户在该网页上进行操作,此时用户将在不知情的情况下点击透明的iframe页面。通过调整iframe页面的位置,可以诱使用户恰好点击在iframe页面的一些功能性按钮上。
防御方法
一、frame busting
通常可以写一段JavaScript代码,以禁止iframe的嵌套。这种方法叫frame busting。
但是frame busting也存在一些缺陷。由于它是用JavaScript写的,控制能力并不是特别强,因此有许多方法可以绕过它。
二、HTTP头 X-Frame-Options
它有三个可选的值:
-
DENY
: 浏览器会拒绝当前页面加载任何frame页面; -
SAMEORIGIN
:则frame页面的地址只能为同源域名下的页面 - ALLOW-FROM origin:可以定义允许frame加载的页面地址。
参考《白帽子讲web安全》
网友评论