一、XSS
1、定义
XSS,即 Cross Site Script,也叫跨站脚本攻击;其原本缩写是 CSS,但为了和层叠样式表(Cascading Style Sheet)有所区分,因而在安全领域叫做 XSS。
XSS攻击通过js代码劫持客户端跟服务器之间的会话。
2、攻击分类
XSS攻击可分为三类,分别为储存型、反射型、DOM型。
存储型
1、储存型XSS攻击将恶意代码提交到网站数据库当中
2、当用户使用客户端向网站请求数据时,恶意代码从服务器传回,拼接在HTML中返回给客户端
3、客户端在解析代码时,恶意代码被执行
常见应用场景:论坛发帖、商品评论、用户私信等
反射型
1、反射型XSS攻击构造出包含恶意代码的url,url指向目标网站,但是参数可以拼接恶意代码
2、诱导用户点击,点击后会向服务端发送请求,同时查询参数携带恶意代码
3、服务端返回时将恶意代码直接拼接在HTML中
4、客户端接收并解析执行代码时,恶意代码也被执行
常见应用场景:通过 URL 传递参数的场景,如网站搜索、跳转
DOM型
DOM型XSS攻击是通过恶意代码修改DOM的结构,是单纯发生在客户端的攻击。
以下情况有可能会被利用:
1、<script>标签
2、javascript:??执行符(a标签的href属性,url上)
3、innerHTML=?? 或 .outerHTML=?? 或 setTimeout(??) 或 setInterval(??)(执行js)
4、document.write(??) 或 eval(??)
5、location、onclick、onerror、onload、onmouseover等事件(执行js)
6、在 style 属性和标签中,包含类似 background-image:url(“javascript:…”);的代码(新版本浏览器已经可以防范)。
7、在 style 属性和标签中,包含类似 expression(…) 的 CSS 表达式代码(新版本浏览器已经可以防范)
总结以上三种类型的XSS攻击:
如果开发者没有将用户输入的文本进行合适的过滤,就贸然插入到 HTML 中,这很容易造成注入漏洞。攻击者可以利用漏洞,构造出恶意的代码指令,进而利用恶意代码危害数据安全。
3、防范方法
现在主流的浏览器内置了防范 XSS 的措施,例如 CSP。但对于开发者来说,也应该寻找可靠的解决方案来防止 XSS 攻击。
1、防范反射型、存储型 XSS:
-
采用纯前端渲染
-
拼接 HTML 时,要对 HTML 进行充分转义(利用一些转义库)
2、防范 DOM 型 XSS
- 将用户输入插入 HTML 或拼接 js 执行时,要进行编码,将一些特殊字符转义。
escapeHTML() 按照如下规则进行转义:
& -> &
<-> <
> -> >
"-> "
' -> '
/ -> /
- 对于 a 标签的 href 等外链请求,添加白名单进行过滤,禁止以 javascript: 开头的链接,和其他非法的 scheme。
3、其他防范措施
-
HttpOnly 防止劫取 Cookie
HttpOnly 最早由微软提出,至今已经成为一个标准。浏览器将禁止页面的Javascript 访问带有 HttpOnly 属性的Cookie。 -
输入检查
对于用户的任何输入要进行检查、过滤和转义。 -
输出检查
服务端的输出也可能会存在问题。一般来说,除富文本的输出外,在变量输出到 HTML 页面时,可以使用编码或转义的方式来防御 XSS 攻击。
CSRF
CSRF,即 Cross Site Request Forgery,中译是跨站请求伪造,是一种劫持受信任用户向服务器发送非预期请求的攻击方式。
举个例子:
小明在刷gmail,突然看到一条链接,好奇点开了发现是个空白链接,就不管他,继续刷其他的。看似没有什么事情发生,但实际上攻击者利用这个所谓的空白页给小明偷偷设置了一个过滤规则,这个规则使他收到的邮件都转发给了攻击者。
1、攻击特点
- 攻击一般发起在第三方网站,而不是被攻击的网站。被攻击的网站无法防止攻击发生。
- 攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作;而不是直接窃取数据。
- 整个过程攻击者并不能获取到受害者的登录凭证,仅仅是“冒用”。
- 跨站请求可以用各种方式:图片URL、超链接、CORS、Form提交等等。部分请求方式可以直接嵌入在第三方论坛、文章中,难以进行追踪。
2、攻击流程
- 受害者登录
a.com,并保留了登录凭证(Cookie)。 - 攻击者引诱受害者访问了
b.com。 b.com向a.com发送了一个请求:a.com/act=xx。浏览器会默认携带a.com的Cookie。a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。a.com以受害者的名义执行了act=xx。
攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。
3、防范措施
CSRF通常从第三方网站发起,被攻击的网站无法防止攻击发生,只能通过增强自己网站针对CSRF的防护能力来提升安全性。
方法一:同源验证
既然CSRF大多来自第三方网站,那么我们就直接禁止外域(或者不受信任的域名)对我们发起请求。
判断是否来自外域:
在HTTP协议中,每一个异步请求都会携带两个Header,用于标记来源域名:
- Origin Header
- Referer Header
这两个Header在浏览器发起请求时,大多数情况会自动带上,并且不能由前端自定义内容。 服务器可以通过解析这两个Header中的域名,确定请求的来源域。
注意:
Origin 在 IE11 中不存在,在 302 重定向中也不存在,Referrer 可以被前端隐藏不携带,如果不存在这两个请求头时,需要利用其它方式验证:
当访问源是外域时,直接拒绝访问,但要注意的是,需要过滤掉 html 页面请求,因为当请求来自搜索引擎结果页面时,也是外域访问,会被当做 CSRF 请求。
方法二、CSRF Token 验证
1、服务器生成一个Token,并把这个Token利用算法加密。要注意,这个Token不能放在Cookie中,要不然又会被冒用,一般是放在session中。
2、在页面加载时,在每个a标签和form标签中放入Token
3、服务器验证Token是否正确
缺点:实现较为复杂,工作量大,可能出现遗漏。
方法三、双重Cookie验证
利用CSRF攻击不能获取到用户Cookie的特点,我们可以要求Ajax和表单请求携带一个Cookie中的值。
1、在用户访问网站页面时,向请求域名注入一个Cookie,内容为随机字符串。
2、在前端向后端发起请求时,取出Cookie,并添加到URL的参数中。
3、后端接口验证Cookie中的字段与URL参数中的字段是否一致,不一致则拒绝。
优点:
无需使用Session,适用面更广,易于实施。
Token储存于客户端中,不会给服务器带来压力。
相对于Token,实施成本更低,可以在前后端统一拦截校验,而不需要一个个接口和页面添加。
缺点:
Cookie中增加了额外的字段。
如果有其他漏洞(例如XSS),攻击者可以注入Cookie,那么该防御方式失效。
难以做到子域名的隔离。
为了确保Cookie传输安全,采用这种防御方式的最好确保用整站HTTPS的方式,如果还没切HTTPS的使用这种方式也会有风险。
方法四、Samesite Cookie属性
Google起草了一份草案来改进HTTP协议,那就是为Set-Cookie响应头新增Samesite属性,它用来标明这个 Cookie是个“同站 Cookie”,同站Cookie只能作为第一方Cookie,不能作为第三方Cookie,Samesite 有两个属性值,分别是 Strict 和 Lax:
Set-Cookie: foo=1; Samesite=Strict
Set-Cookie: bar=2; Samesite=Lax
Samesite=Strict:严格模式
这个Cookie无论什么情况下都不能作为第三方的Cookie。
Samesite=lax:宽松模式
如果这个请求改变了当前页面或者打开新页面,且携带GET请求,则这个Cookie可作为第三方Cookie。
缺点:
1、Samesite 不支持子域,也就是说子域无法使用设置了 Samesite 的 cookie,这可能导致用户在主域登录后,前往子域页面仍需要重新登录
2、兼容性不好