XSS
XSS全称是Cross Site Scripting即跨站脚本,当目标网站目标用户浏览器渲染HTML文档的过程中,出现了不被预期的脚本指令并执行时,XSS就发生了。
XSS简单来说,就是攻击者想尽一切方法将执行的代码注入到网页中。
XSS 可以分为多种类型,但是从时间角度,可以分为两类:持久型和非持久型。
持久型也就是攻击的代码被服务端写入到数据库中,这种攻击危害性很大,因为如果网站访问量很大的话,就会导致大量正常访问页面的用户都受到攻击。
举个例子,对于评论功能来说,就需要防范持久型XSS攻击,因为我们可以在评论中输入以下内容
这种情况如果前后端没有做好防御的话,这段评论会被存储到数据库中,这样每个打开盖页面的用户都会被受到影响。
非持久型相比前者危害就小很多,一般通过修改URL参数的方式加入攻击的代码,诱导用户访问链接从而进行攻击。
但是对于这种攻击方式来收,如果用户使用Chrome这类浏览器,浏览器就能自动帮助用户防御攻击。但是我们不能因此就不防御此类攻击了,因为我们无法确保用户都适用该类浏览器。
转义字符
首先,对于用户的输入应该是永远不可信任的。最普遍的做法就是转义输入输出的内容,对于引号、尖括号、斜杠等进行转义。
function escape(str) {
str = str.replace(/&/g, '&');
str = str.replace(/</g, '<').replace(/>/g, '>');
str = str.replacce(/"/g, '&quto;').replace(/'/g, ''');
str = str.replace(/`/g, '`');
str = str.replace(/\//g, '/');
return str;
}
通过转义可以将攻击代码<script>alert(1)</script
变成
escape('<script>alert(1)</script');
// <script>alert(1)</script>
对于显示富文本来说,显然不能通过上面的办法来转义,因为这样会把需要的格式也过滤掉。对于这种情况,通常采用白名单过滤的方法,当然也可以通过黑名单过滤,但是考虑到需要过滤的标签和标签属性实在太多,所以更加推荐白名单的方式。
CSP 内容安全策略
CSP: Content Security Policy本质上就是建立白名单,开发者明确告诉浏览器哪些外部资源可以加载和执行。我们只需要配置规则,如何拦截是浏览器内部实现的。我们可以通过这种方式来尽量减少XSS攻击。
通常可以通过设置来开启CSP:
- 设置HTTP Header 中
Content-Security-Policy
- 这是
meata
标签的方式<meta http-equiv="Content-Security-Policy">
设置HTTP Header的值(设置 Content-Security-Policy值)
属性值 | 含义 |
---|---|
default-src ‘self’ | 只允许加载本站资源 |
img-src https://* | 只允许家在HTTPS协议图片 |
child-src ‘none’ | 允许家在任何来源框架 |
其他属性值可以参考文档Content-Security-Policy
CSRF
CSRF跨站请求伪造(Cross-Site Request Forgery)。原理是攻击者构造出一个后端请求地址,诱导用户点击或者通过某些途径自动发起请求。如果用户是在登录状态的话,后端就误认为是用户在操作,从而进行相应的逻辑。
举个例子,假设网站中有一个通过GET
请求提及提交用户评论的接口,那么攻击者就可以在钓鱼网站中加入一张图片,图片的地址就是评论的接口。
<img src="https://api.juejin.cn/interact_api/v1/comment/publish?comment_content=test">
那么如果我们请求方式改为POST
是不是就没有这个问题了呢 ?并不是,POST
也不是百分百安全的,攻击者同样可以诱导用户接入某个页面,在页面中通过表单提交PoST
请求。
如何防御
防范CSRF攻击可以遵循以下几种原则
- GET请求不对数据进行修改
- 不让第三方网站访问到用户的Cookie
- 阻止第三方网站请求接口
- 请求时附带验证信息,比如验证码或者Token
SameSite
可以对Cookie设置SameSite
属性,该属性表示Cookie不随着跨域请求发送,可以很大程度上减少CSRF攻击,但该属性目前并不是所有浏览器都兼容。
验证Referer
对于需要防范CSRF的请求,我们可以通过验证Referer来判断是否为第三方网站发起。
Token
服务器下发一个随机Token,每次发起请求是将Token携带上,服务器验证Token是否有效。
点击劫持
点击劫持是一种视觉欺骗的点击手段。攻击者将需要攻击的网站通过iframe
嵌套的方式嵌入自己的网页中,并将iframe
设置为透明,在页面中透出一个按钮诱导用户点击。
对于这种攻击方式,推荐防御的方法有两种。
X-FRAME-OPTIONS
X-FRAME-OPTIONS
是一个HTTP响应头,在现代浏览器中有一个很好的支持。这个HTTP响应头就是为了防御用iframe
嵌套的点击劫持攻击。
该响应头有三个值可选,分别是:
值 | 含义 |
---|---|
DENY | 页面不允许通过iframe 的方式展示 |
SAMEORTGIN | 页面可以在相同域名下通过iframe 的方式展示 |
ALLOW-FROM | 页面可以在指定来源的iframe 中展示 |
JS防御
对于某些老浏览器来说,并不能支持上面的方式,那我们只能通过JS的方式来防御点击劫持了。
<head>
<style>
html {
display: none;
}
</style>
</head>
<body>
if(self == top) {
var style = document.getElementById('click-jack');
document.body.removeChild(style);
}
else {
top.location = self.location;
}
</body>
以上代码的作用就是点那个通过iframe
的方式夹在页面时,攻击者的页面直接不显示所有内容了。
中间人攻击
中间人攻击时攻击方同时与服务端和客户端建立起了连接,并让对方认为连接时安全的,但是实际上整个通信过程都被攻击者控制了。攻击者不仅能获得双方的通信信息,还能修改通信信息。
通常来说不建议使用公共的Wi-Fi,因为很可能就会发生中间人攻击的情况。如果我们在通信过程中设计到了某些敏感的信息,就完全暴露给了攻击方了。
当然防御中间人并不难,只需要增加一个安全通道来传输信息。HTTPS就可以用来防御中间人攻击,但是并不是使用了HTTPS就可以完全安全了,因为如果没有完全关闭HTTP访问的话,攻击方可以通过某些方式将HTTPS降级为HTTP从而实现中间人攻击。