对于网站开发,我们不得不面对各种网络攻击。而网络攻击的方式千姿百态,这次我们就将学习下常见的三种方式 —— XSS、CSRF、API接口攻击。
维基百科: 跨站脚本(英语:Cross-site scripting,通常简称为:XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。
比如,一个网站的评论区,用户可以输入script标签,如图
点击submit发送内容,如果前端后端都没有做任何处理的话,这段评论在提交以后就会原封不动地展示在html上。而这个时候,script里的代码执行了,导致所有访问这个页面的用户的cookie都发送到了黑客指定的API。
前端对于这种情况好像在发送到后端的过程中无能为力,即使在流程中加上前端转译,黑客也可以通过直接在控制台执行js的方式来提交评论。
前端倒是在渲染的时候可以做相应的处理,比如可以用以下方法处理:
processedContent(comment) {
return comment
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'")
}
这样就能处理掉非法符号了(代码仅列举了部分符号)。 &<>
这些字符叫做字符实体因为比如 < >
这样的字符游览器会认为是标签,所以,如果想正常显示 < >
,那么就得转成字符实体,而游览器默认也认识这些字符,在展示的时候,还是展示成字符实体对应的符号。 对于渲染阶段,像react,vue这样的库,又或者是juicer,ejs这样的前端模板,都会默认处理非法符号为字符实体。
字符实体详解可以看这里>> http://www.w3school.com.cn/html/html_entities.asp
后端在收到前端的提交以后,直接存起来就好。
这里的渲染指的是后端模板渲染,渲染模板可能是smarty,可能是laravel的blade,可能是node做中间层用的ejs,亦可能是vue或react的SSR。这些后端模板都自己内部会做转义。 转义的实现方法也无非是通过正则匹配,然后进行替换。
在遇到富文本编辑器的时候,处理方法就不同了。因为,在前端展示的时候,我们自然是有什么标签就展示什么标签,而不是转为字符实体,不然得到的不都是文本了嘛。 这种情况的话,就需要后端进行非法字符过滤了,把比如script这种标签给过滤掉,或者转义掉。当然,其实富文本还有很多过滤条件,比如,非本站的网页地址过滤,非法字符过滤等。
总之,无论是后端模板还是前端模板,其实都是前端的范畴。 上面也说了,现在的前端库、前端模板、后端模板,都已经内部做了转译了,开发者愉快的使用就好了。 所以,其实除了遇到富文本编辑器的情况(工作量在后端),我们几乎不用做任何额外的工作。但是,还是理解内部机制比较好。
跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
简单的说,就是利用游览器对用户的信任,比如,用户已经登录了ww.aaa.com,自然aaa这个网站就会将用户的登录状态session存在cookie中; 然后,aaa.com这个网页有一个对作品点赞的功能,点赞提交地址为 aaa.com/api.like?id=777
; 这时,另外一个叫www.bbb.com的网站,放了这样一个元素 src="aaa.com/api.like?id=888">
,我们知道,请求静态资源用的是get方法,这样的话,一旦用户进入这个bbb.com页面,就会请求aaa.com这个网站的点赞接口,而且点赞的用户对象是888; 最后因为用户的登录信息尚未过期,那就等于给id为888这个作品点赞了,然而,用户并不知情。
有两种方法:
后端判断referer是否合法(不推荐) 通过HTTP的referer可知道,用户是通过哪个网站发送这个请求的。但是referer的判断并不是好方法,有各种方式可以绕过的方法,具体可见 CSRF 花式绕过Referer技巧>>
https://www.ohlinge.cn/web/csrf_referer.html
每次请求带上token 比如laravel,在后端模板渲染的时候会提供一个csrf的token,这样的话,不同域的网站是拿不到token的,所以也就防止了csrf了。
使用iframe会引出一些不安全的问题,比如绕过referer验证,比如资源盗用等,所以,很多网站会设置 X-Frame-Options
为 DENY
,这也是一个安全的补充点。
问:既然请求静态资源都是get请求,那么要是后端把点赞接口改为post的方式也可以吧?
答:不可以。因为,bbb.com网站完全可以设置一个form表单,action为bbb.com,method为post,接着input的name为id,value为888,然后,script代码直接submit表单。为了页面不重定向,还可以在form外层加一个iframe。由于form表单其实是直接跳转,所以不存在跨域的问题。
防止CSRF的最好方法还是带token吧~
相信很多网站都会遇到也不知道是谁,毫无目的刷网站的接口的事情。 尤其是短信接口,好像所有网站都会被人刷接口,十有八九都是短信接口的提供商找人干的。。。 其次,登录接口也是经常被刷地方,因为可以被破坏者用来爆破用户的密码。 然后,注册接口也是,不过因为国家强制要求手机号注册的原因,现在还好刷注册接口很难了。
1、监控异常ip,发现异常ip,直接封ip(这种方法要是遇到使用肉鸡刷的人就没什么办法了) 2、使用验证码(这种方法缺点就是降低用户体验) 在实际项目中,这两种防御方式会一起使用。
这两种防御方式同样应用在爬虫的防御上。由于验证码这东西市面上有很多种,而好的交互和用户的体验息息相关,那么,现在有哪些种类的验证码呢,我们又该怎么选择呢?
缺点:用户体验差;攻击者可以用图像识别算法识别字母
缺点:用户体验差;同样可以通过算法识别,然后模拟点击定位
前几年比较火,几乎所有大网站都用了这种方法,但是也有问题 缺点:要是攻击者有了整套的图片资源,也能破解。极验验证码之前就因为滑块图片泄露,导致很多用他们家服务的网站被攻击了。后来他们紧急更新了滑块包和SDK(偷偷地),当时我们CTO打电话给他们才给我们说他们滑块资源被盗了,居然不也通知我们,我们问了才说,造成了公司的损失,浪费了人员的精力。
最为代表性的就是谷歌的reCAPTCHA了,但是毕竟是谷歌服务,国内用起来还是很鸡肋的。 不过,国内也有了这样的解决方案,比如极验就出了这项云服务了,不过名字叫做“智能验证码”。
无感知验证码可以说是目前最好的验证码解决方案了。 然而很多公司还是停留在图形验证码的阶段 ╮(╯_╰)╭
名称 | 发生场景列举 | 解决方案 |
---|---|---|
XSS | 用户图文编辑 | 非法标签过滤 |
CSRF | 骗赞 | csrf token |
API接口攻击 | 发送短信 | 无感知验证码 |
热 文 推 荐
☞ 可能这些是你想要的 H5 软键盘兼容方案
☞ React 中的高阶组件及其应用场景
☞ 从0到1完成一个Babel插件
☞ 如何优雅处理前端的异常?
☞ 面试官:自己搭建过vue开发环境吗?
你也“在看”吗?