常见的攻击手段
XSS
攻击者将可以执行的代码注入到网页中。
持久型
非持久型
注入点:
HTML
节点内容HTML
属性(img onerror属性)JavaScrit
代码富文本
持久型就是将攻击代码写入到了数据库中,这种危害性很大,会导致大量正常访问网站的用户受到攻击。
举个例子,对于评论功能来说,就得防范持久型 XSS
攻击,因为可以在评论中输入以下内容
这种情况如果前后端没有做好防御的话,这段评论就会被存在数据库中,这样每个打开页面的用户都会被攻击到。
非持久型相比危害小的多,一般通过修改 URL 参数的方式加入攻击代码,诱导用户访问链接从而攻击。举个例子,如果页面需要从 URL 中获取某些参数作为内容的话,不经过过滤会导致攻击代码被执行
<!-- http://www.test.com?test=<script>alert(1)</script> -->
<div>{{test}}</div>
但是对于这种攻击方式,如果用户使用 Chrome 这类浏览器的话,浏览器就能自动帮助用户防御攻击。但是我们不能因此就不防御,因为不用确保用户使用了哪类浏览器。
对于 XSS
攻击来说,通常有两种方式用来防御:
转义字符
用户的输入是不可信任的。最普遍的做法就是转义输入输出的内容,对于引号、尖括号、斜杆进行转义处理。
{
// 将str中的html符号转义,将转义“',&,<,",>”五个字符
escapeHtml (str) {
return str
? str.replace(
reg || /[&<">'](?:(amp|lt|quot|gt|#39|nbsp|#\d+);)?/g,
function (a, b) {
if (b) {
return a
} else {
return {
'<': '<',
'&': '&',
'"': '"',
'>': '>',
"'": '''
}[a]
}
}
)
: ''
},
decodehtml (str) {
return str
? str.replace(/&((g|l|quo)t|amp|#39|nbsp);/g, function (m) {
return {
'<': '<',
'&': '&',
'"': '"',
'>': '>',
''': "'",
' ': ' '
}[m]
})
: ''
}
}
通过转义可以将攻击代码 <script>alert(1)</script>
变成
// -> <script>alert(1)</script>
escapeHtml('<script>alert(1)</script>')
但是对于富文本来说,显然不能通过上面的方法来转义所有字符,因为这样会把需要的格式也会过滤掉。对于这种可以使用 js-xss 插件来实现,设置白名单过滤
const xss = require('xss')
let html = xss('<h1 id="title">XSS Demo</h1><script>alert("xss");</script>')
// -> <h1>XSS Demo</h1><script>alert("xss");</script>
console.log(html)
CSP
CSP 本质就是建立白名单。开发者明确浏览器哪些外部的资源可以加载和执行,只需要配置相关规则,如何拦截由浏览器自己实现;可以通过这种方式来尽量减少 XSS
攻击。
通过两种方式开启 CSP:
- 设置
HTTP Header
中的Content-Security-Policy
# 只允许加载本站资源
Content-Security-Policy: default-src ‘self’
# 只允许加载 HTTPS 协议图片
Content-Security-Policy: img-src https://*
# 允许加载任何来源框架
Content-Security-Policy: child-src 'none'
更多设置可以查看文档
- 设置
meta
标签的方式<meta http-equiv="Content-Security-Policy">
这种方式,只要开发者配置正确的规则,那么即使网站存在漏洞,攻击者页不能执行它的攻击代码,并且 CSP
的兼容性也不错。
TIP
幸运的是目前前端主流的框架已解决 XSS
攻击,如:Vue、React、Angular
CSRF
CSRF - 跨站请求伪造。
在其它的网站对目标网站发送请求,而这些请求是在用户不知情的情况下完成的。它是发生在匿名的情况下,第三方网站,带上Cookies,向你的网站发送请求,不访问你的前端。
攻击原理
用户登录
A
网站A
网站确认身份B
网站向A
网站发送请求(带A
网站的身份)
举个例子,假设网站由一个通过 GET
请求提交用户评论的接口,那么攻击者就可以在钓鱼网站中加入一个图片,图片的地址就是评论接口
<img src="http://www.test.com/xxx?comment='attack'"/>
那么你是否会想到使用 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
嵌套的点击劫持攻击。
header('X-Frame-Options:DENY')
该响应头有三个值可选,分别是
DENY
:表示页面不允许通过iframe
的方式展示SAMEORIGIN
:表示页面可以在相同域名下通过iframe
的方式展示ALLOW-FROM
:表示页面可以在指定来源的iframe
中展示
- JS 防御
JavaScript 禁止内嵌
<script>
if (top.location != window.location){
top.location = window.location
}
</script>
上传问题
上传文件
再次访问上传的文件
上传的文件被当成程序解析
上传问题防御
限制上传的后缀
检查文件类型
检查文件内容
程序输出
权限控制——可写可执行互斥
中间人攻击
中间人攻击是攻击方同时与服务端和客户端建立起了连接,并让对方认为连接是安全的,但是实际上整个通信过程都被攻击者控制了。攻击者不仅能获得双方的通信信息,还能修改通信信息。
通常来说不建议使用公共的 Wi-Fi
,因为很可能就会发生中间人攻击的情况。如果你在通信的过程中涉及到了某些敏感信息,就完全暴露给攻击方了。
防御
- 增加一个安全通道来传输信息
HTTPS
就可以用来防御中间人攻击,但是并不是说使用了 HTTPS
就可以高枕无忧了,因为如果你没有完全关闭 HTTP
访问的话,攻击方可以通过某些方式将 HTTPS
降级为 HTTP
从而实现中间人攻击。