摘要: 本文探讨web前端平安问题以及应答措施,浏览器同源策略以及对资源跨域拜访的几种解决方案

本文分享自华为云社区《Web平安和浏览器跨域拜访》,原文作者:kg-follower 。

明天说一说和前端相干的Web平安问题和开发过程中常常遇到的跨域问题。

1.Web平安

1.1 XSS

基本原理

XSS (Cross-Site Scripting),跨站脚本攻打通过在用户的浏览器内运行非法的HTML标签或JavaScript进行的一种攻打。

攻打伎俩

攻击者往 Web 页面里插入歹意网页脚本代码,当用户浏览该页面时,嵌入 Web 页面外面的脚本代码会被执行,从而达到攻击者盗取用户信息或其余进犯用户平安隐衷的目标。

XSS攻打分类

反射型xss攻打。通过给被攻击者发送带有歹意脚本的URL或将不可信内容插入页面,当URL地址被关上或页面被执行时,浏览器解析、执行歹意脚本。

反射型xss的攻打步骤:1. 攻击者结构出非凡的 URL或非凡数据;2. 用户关上带有恶意代码的 URL 时,Web服务器将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器;3. 用户浏览器接管到响应后解析执行,混在其中的恶意代码也被执行;4. 恶意代码窃取用户数据并发送到攻击者的网站,或者假冒用户的行为,调用指标网站接口执行攻击者指定的操作。

进攻:1.Web页面渲染的所有内容或数据都必须来自服务端;2. 客户端对用户输出的内容进行平安符本义,服务端对上交内容进行平安本义;3.防止拼接html。

存储型xss。歹意脚本被存储在指标服务器上。当浏览器申请数据时,脚本从服务器传回浏览器去执行。

存储型xss的攻打步骤:1. 攻击者将恶意代码提交到指标网站的数据库中;2.用户浏览到指标网站时,前端页面取得数据库中读出的歹意脚本时将其渲染执行。

进攻:防备存储型XSS攻打,须要咱们减少字符串的过滤:前端输出时过滤;服务端减少过滤;前端输入时过滤。

通常有三种形式进攻XSS攻打:1. Content Security Policy(CSP)。CSP 实质上就是建设白名单,开发者明确通知浏览器哪些内部资源能够加载和执行。咱们只须要配置规定,如何拦挡是由浏览器本人实现的。咱们能够通过这种形式来尽量减少 XSS 攻打。通常能够通过两种形式开启,例如只容许加载雷同域下的资源:

设置 HTTP Header 中的 CSP(Content-Security-Policy: default-src 'self')

设置meta 标签的形式(<meta http-equiv="Content-Security-Policy" content="form-action 'self';">)

2. 转义字符。用户的输出永远不可信赖的,最广泛的做法就是本义输入输出的内容,对于引号、尖括号、斜杠进行本义:

function escape(str) {  str = str.replace(/&/g, '&amp;')  str = str.replace(/</g, '&lt;')  str = str.replace(/>/g, '&gt;')  str = str.replace(/"/g, '&quto;')  str = str.replace(/'/g, '&#39;')  str = str.replace(/`/g, '&#96;')  str = str.replace(/\//g, '&#x2F;')  return str}

然而对于显示富文本来说,显然不能通过下面的方法来本义所有字符,因为这样会把须要的格局也过滤掉。对于这种状况,通常采纳白名单过滤的方法:

const xss = require('xss')let html = xss('<h1 id="title">XSS Demo</h1><script>alert("xss");</script>')console.log(html)<h1>XSS Demo</h1>&lt;script&gt;alert("xss");&lt;/script&gt;

通过白名单过滤,dom中蕴含的<script>标签将不会被执行。

HTTP-only Cookie: 禁止 JavaScript 读取某些敏感 cookie,使得 cookie只有http可能拜访。

1.2 CSRF

基本概念

CSRF(Cross-site request forgery跨站申请伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻打网站发送跨站申请。利用受害者在被攻打网站曾经获取的注册凭证,绕过后盾的用户验证,达到假冒用户对被攻打的网站执行某项操作的目标。

CSRF攻打类型

主动型攻打。用户拜访网站A并在浏览器保留A的登录状态(cookie等信息),攻击者诱导受害者拜访网站B,网站B含有拜访A接口的恶意代码,受害者拜访B时带着A的登录状态,攻击者便能够假冒用户执行对A的歹意操作。

被动型攻打。攻击者在网站A公布带有歹意链接的评论或内容(提交对A带有增删改的诱导型标签),当其余领有登录状态的受害者点击评论的歹意链接时,就会冒用受害者登录凭证发动攻打。

CSRF攻打防备

验证HTTP Referer字段。在HTTP头中有Referer字段,他记录该HTTP申请的起源地址,如果跳转的网站与起源地址相符,那就是非法的,如果不符则可能是csrf攻打,回绝该申请。

SameSite。能够对 Cookie 设置 SameSite 属性。该属性示意 Cookie 不随着跨域申请发送,能够很大水平缩小 CSRF 的攻打。

申请中退出token。服务端给用户生成一个token,加密后传递给用户,用户在提交申请时,须要携带这个token,服务端发现token不存在或者token校验不胜利,那么就回绝该申请。

1.3 流量劫持

DNS劫持

DNS劫持就是通过劫持了DNS服务器,通过某些伎俩来获得某个域名的解析控制权,进而批改此域名的解析后果,导致对该域名的拜访由原IP地址转入到批改后的IP,其后果就是对特定的网站不能拜访或拜访的是假网址。

进攻:应用https校验通信单方身份和数据完整性。

点击劫持

攻击者构建了一个十分有吸引力的网页,将被攻打的页面搁置在以后页面的 iframe 中,应用款式将 iframe 叠加到十分有吸引力内容的上方,将iframe设置为100%通明,其实就是通过笼罩不可见的页面,诱导用户点击而造成的攻击行为。

进攻措施。1. X-FRAME-OPTIONS设置容许iframe加载的域 2. 限度iframe页面中的JavaScript脚本执行。

无论是xss、csrf还是点击劫持,下面探讨的这几种攻打属于前端攻打,起因大多是开发者的脚本或模板代码存在不平安的隐患或是没有思考网络传输平安问题。上面简略说一说歹意攻打利用网站后盾破绽发动的攻打。

1.4 SQL注入

SQL 注入破绽存在的起因,就是拼接 SQL 参数。也就是将用于输出的查问参数,间接拼接在 SQL 语句中,歹意攻击者能够结构非凡的sql语句绕过平安验证。

SQL注入条件:1.攻击者能够管制输出的数据;2.服务器要执行的代码拼接了被管制的数据。

SQL注入进攻。1. 严格限度Web利用的数据库的操作权限;2. 对进入数据库的特殊字符(’,”,,<,>,&,*,; 等)进行本义解决,或编码转换,相似进攻xss攻打时对输出本义;3. 所有的查问语句倡议应用数据库提供的参数化查问接口,如应用占位参数或对象关系映射ORM。

1.5 DDOS攻打

DOS攻打通过在网站的各个环节进行攻打,使得整个流程跑不起来,以达到瘫痪服务为目标。最常见的就是发送大量申请导致服务器过载宕机。DDOS攻打的原理就是利用分布式的客户端,向指标发动大量看上去非法的申请,耗费/占用大量资源,从而达到拒绝服务的目标。

攻击方式:1.端口扫描;2.ping洪水;3.SYN洪水;4.FTP跳转攻打;

DDOS防备。1.在服务器上删除未应用的服务,敞开未应用的端口。2. 进行实时监控,封禁某些歹意密集型申请IP段;3. 进行动态资源缓存,隔离源文件的拜访,比方CDN减速;4. 暗藏服务器的实在IP地址

3 跨域和同源策略

同源策略是一个重要的安全策略,它用于限度一个源的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮忙阻隔歹意文档,缩小可能被攻打的媒介。所谓同源是指“协定+域名+端口”三者均雷同。

同源策略限度了客户端js代码的以下行为:

1.Cookie、LocalStorage 和 IndexDB 无奈读取;

2.DOM节点。来自一个源的js只能读写本人源的DOM树不能读取其余源的DOM树。如果两个网页不同源,就无奈拿到对方的DOM。典型的例子是iframe窗口和window.open办法关上的窗口,它们与父窗口无奈通信。

网站不开启同源策略,钓鱼网站便能够应用iframe标签加载中国银行登录界面,执行脚本进而拿到用户名明码。

当设置了同源策略,父子窗口执行获取对方DOM时会报错。

3.AJAX申请限度

跨域并不是申请发不进来,申请能收回去,服务端能收到申请并失常返回后果,只是后果被浏览器拦挡了。

除了架设服务器代理,还有以下几种办法躲避同源限度:JSONP,WebSocket,CORS,本文具体探讨下后两种办法的实现。

WebSocket。WebSocket是一种通信协议,应用ws://(非加密)和wss://(加密)作为协定前缀。该协定不履行同源政策,只有服务器反对,就能够通过它进行跨源通信。WebSocket 是一种双向通信协定,在建设连贯之后,WebSocket 的 server 与 client 都能被动向对方发送或接收数据。Websocket申请头信息蕴含一个origin字段,服务器依据这个字段判断是否容许本次通信。

CORS。CORS跨域资源共享是W3C规范,是解决跨域Ajax申请的最常见解决办法。整个CORS通信过程,都是浏览器主动实现,不须要用户参加。对于开发者来说,CORS通信与同源的AJAX通信没有差异,代码齐全一样。浏览器一旦发现AJAX申请跨源,就会主动增加一些附加的头信息,有时还会多出一次附加的申请,但用户不会有感觉。

浏览器将CORS申请分成两类:简略申请(simple request)和非简略申请(not-so-simple request)。只有同时满足以下两大条件,就属于简略申请:

(1) 申请办法是以下三种办法之一:HEAD、GET、POST

(2)HTTP的头信息不超出以下几种字段:Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

对于简略申请,浏览器间接收回CORS申请。具体来说,就是在头信息之中,减少一个Origin字段,该字段用来阐明,本次申请来自哪个源。服务器依据这个值,决定是否批准这次申请。如果Origin指定的源,不在许可范畴内,服务器会返回一个失常的HTTP回应。若该响应的头信息没有蕴含Access-Control-Allow-Origin字段,就抛出一个谬误,被XMLHttpRequest的onerror回调函数捕捉。若Origin指定的域名在许可范畴内,服务器返回的响应,会多出几个头信息字段。其中Access-Control-Allow-Origin字段是必须的。它的值要么是申请时Origin字段的值,要么是一个*,示意承受任意域名的申请。

对于非简略申请,在正式通信之前,会减少一次HTTP查问申请,称为"预检"申请(preflight)。浏览器先询问服务器,以后网页所在的域名是否在服务器的许可名单之中,以及能够应用哪些HTTP办法和头信息字段。只有失去必定回答,浏览器才会收回正式的XMLHttpRequest申请,否则就报错。

"预检"申请用的申请办法是OPTIONS,示意这个申请是用来询问的。头信息外面,关键字段是Origin,示意申请来自哪个源。

除了Origin字段,"预检"申请的头信息包含两个非凡字段。

(1)Access-Control-Request-Method。该字段是必须的,用来列出浏览器的CORS申请会用到哪些HTTP办法

(2)Access-Control-Request-Headers。该字段是一个逗号分隔的字符串,指定浏览器CORS申请会额定发送的头信息字段。

预检申请的回应。

服务器收到"预检"申请当前,查看了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段当前,确认容许跨源申请,就能够做出回应。回应最要害的是Access-Control-Allow-Origin字段,示意容许该源的申请,若没有任何CORS相干头信息字段则阐明服务器否定该申请。若服务器容许,则Access-Control-Allow-Methods字段是必须的,它的值是一个逗号分隔的字符串,表明服务器反对的办法。如果预检申请蕴含Access-Control-Request-Headers字段,则返回体中该字段也是必须的,它也是一个逗号分隔的字符串,表明服务器反对的所有头信息字段,不限于浏览器在"预检"中申请的字段。预检申请失去容许回应后,浏览器便发送失常CORS申请。

最近在开发一个前端poc我的项目时遇到了跨域资源拜访被限度的问题,在本地启动angular我的项目,其他人能够通过ip拜访到动态资源,发送ajax申请时被限度。于是想通过配置代理的形式解决这个跨域问题:在和package.json同级的目录中新建proxy.conf.json文件,target字段是后端服务实在的ip,changeOrigin字段设置为true,敞开secure字段。

{    "/": {      "target": "http://10.173.99.224:8081/",      "changeOrigin": true,      "secure": false,      "loglevel": "debug"    }}

在package.json的启动命令中增加

 "scripts": {    "ng": "ng",    "start": "ng serve --proxy-config proxy.conf.json --host 0.0.0.0",    "build": "ng build",    "watch": "ng build --watch --configuration development",    "test": "ng test"  },

--host 0.0.0.0 示意监听所有起源的主机。解决

点击关注,第一工夫理解华为云陈腐技术~