ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

前端安全问题总结(一)

2021-11-12 14:34:40  阅读:193  来源: 互联网

标签:总结 XSS temp 前端 用户 replace 安全 iframe 页面


很多时候我们在做开发的时候并不会主要考虑安全问题,但是现在从事的行业不同,前端安全也会相应的受到更多的重视,下面通过几个个方面具体了解和分析一下前端的安全相关问题:

  1. 熟悉的CSRF(跨站请求伪造)
  2. 老生常谈的XSS(跨站脚本攻击)
  3. iframe带来的风险
  4. 打开新页面也可能有风险

1、CSRF(跨站请求伪造)
攻击者盗用了用户身份,拿到了登录信息,以用户的名义进行恶意请求。危险is watching you:以用户的名义发送邮件、发信息、盗取账号、购买商品、虚拟货币转账等。总结起来就是:个人隐私暴露及财产安全问题。
CSRF 攻击思想:

  1. 浏览并登录信任网站(举例:淘宝)
  2. 登录成功后在浏览器产生信息存储(举例:cookie)
  3. 用户在没有登出淘宝的情况下,访问危险网站
  4. 危险网站中存在恶意代码,代码为发送一个恶意请求(举例:购买商品/余额转账)
  5. 携带刚刚在浏览器产生的信息进行恶意请求
  6. 淘宝验证请求为合法请求(区分不出是否是该用户发送)
  7. 达到了恶意目标

防御措施(推荐添加token / HTTP头自定义属性)

  • 涉及到数据修改操作严格使用 post 请求而不是 get 请求
  • HTTP-only Cookie: 禁止 JavaScript 读取某些敏感 Cookie,攻击者完成 XSS 注入后也无法窃取此 Cookie。
  • HTTP 协议中使用 Referer 属性来确定请求来源进行过滤(禁止外域)

   

   

  • 请求地址添加 token ,使黑客无法伪造用户请求
  • HTTP 头自定义属性验证(类似上一条)
  • 显示验证方式:添加验证码等

2、XSS(跨站脚本攻击)
XSS是跨站脚本攻击(Cross-Site Scripting)的简称,XSS这类安全问题发生的本质原因在于,浏览器错误的将攻击者提供的用户输入数据当做JavaScript脚本给执行了。

XSS分为:存储型 、反射型 、DOM型XSS

存储型XSS:存储型XSS,持久化,代码是存储在服务器中的,如在个人信息或发表文章等地方,插入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,用户访问该页面的时候触发代码执行。这种XSS比较危险,容易造成蠕虫,盗窃cookie

 

反射型XSS:非持久化,需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),一般容易出现在搜索页面。反射型XSS大多数是用来盗取用户的Cookie信息。


DOM型XSS:不经过后端,DOM-XSS漏洞是基于文档对象模型(Document Objeet Model,DOM)的一种漏洞,DOM-XSS是通过url传入参数去控制触发的,其实也属于反射型XSS。

 

例子1:
公司需要一个搜索页面,根据 URL 参数决定关键词的内容。
代码如下:

<input type="text" value="<%= getParameter("keyword") %>">
<button>搜索</button>
<div>
  您搜索的关键词是:<%= getParameter("keyword") %>
</div>

上线后不久,收到安全组发来的一个神秘链接:

http://xxx/search?keyword="><script>alert('XSS');</script>


当浏览器请求 http://xxx/search?keyword="><script>alert('XSS');</script> 时,服务端会解析出请求参数 keyword,得到 "><script>alert('XSS');</script>,拼接到 HTML 中返回给浏览器。形成了如下的 HTML:

<input type="text" value=""><script>alert('XSS');</script>">
<button>搜索</button>
<div>
    您搜索的关键词是:"><script>alert('XSS');</script>
</div>
// 卒~~


例子2:
公司需要一个根据 URL 参数决定决定跳转地址。代码如下:

<a :href="getParameter("redirect_to")">跳转...</a>


继续收到安全组神秘链接: 

http://xxx/?redirect_to=javascript:alert('XSS')


解析后:

<a href="javascript:alert('XSS';)">跳转...</a> // 卒~~

可能会被利用的地方

HTML 中内嵌的文本中:<div>{'</div><script>alert('XSS');</script><div>'}</div>
元素的属性(href、src 等):<a href={javascript:alert('XSS')}></a>
元素事件(onload、onerror、onclick 等):<img onl oad={javascript:alert('XSS')}></img>
URL的query:http://abc.com/xxx?search=<script>alert('XSS');</script>
style属性值:background-image:url("javascript:...");

如何防御:

编码:

把可运行的恶意代码编码成不可运行的单纯的数据

 

注:由于用户提交的数据可能会被使用到不同的场景,不同的场景不同的处理方式是不一样;甚至,同一个数据,可能会在不同的场景下使用。所以,在拿到数据之后往往不会立刻做处理。

相反的,在把数据render到HTML的时候,对数据进行处理,是我们较好处理时机。
根据显示场景的不同可以有不同的编码方式例如:

在HTML中显示: Node.textContent = userInput
在URL中使用:Window.encodeURIComponent(userInput)
作为属性使用:Element.style.XXX = userInput/Element.setAttribute(attribute, userInput)
JSON编码等


HTML编码及转换方法:

 

 1 var HtmlUtil = {
 2         /*1.用浏览器内部转换器实现html编码(转义)*/
 3         htmlEncode:function (html){
 4             //1.首先动态创建一个容器标签元素,如DIV
 5             var temp = document.createElement ("div");
 6             //2.然后将要转换的字符串设置为这个元素的innerText或者textContent
 7             (temp.textContent != undefined ) ? (temp.textContent = html) : (temp.innerText = html);
 8             //3.最后返回这个元素的innerHTML,即得到经过HTML编码转换的字符串了
 9             var output = temp.innerHTML;
10             temp = null;
11             return output;
12         },
13         /*2.用浏览器内部转换器实现html解码(反转义)*/
14         htmlDecode:function (text){
15             //1.首先动态创建一个容器标签元素,如DIV
16             var temp = document.createElement("div");
17             //2.然后将要转换的字符串设置为这个元素的innerHTML(ie,火狐,google都支持)
18             temp.innerHTML = text;
19             //3.最后返回这个元素的innerText或者textContent,即得到经过HTML解码的字符串了。
20             var output = temp.innerText || temp.textContent;
21             temp = null;
22             return output;
23         },
24         /*3.用正则表达式实现html编码(转义)*/
25         htmlEncodeByRegExp:function (str){  
26              var temp = "";
27              if(str.length == 0) return "";
28              temp = str.replace(/&/g,"&amp;");
29              temp = temp.replace(/</g,"&lt;");
30              temp = temp.replace(/>/g,"&gt;");
31              temp = temp.replace(/\s/g,"&nbsp;");
32              temp = temp.replace(/\'/g,"&#39;");
33              temp = temp.replace(/\"/g,"&quot;");
34              return temp;
35         },
36         /*4.用正则表达式实现html解码(反转义)*/
37         htmlDecodeByRegExp:function (str){  
38              var temp = "";
39              if(str.length == 0) return "";
40              temp = str.replace(/&amp;/g,"&");
41              temp = temp.replace(/&lt;/g,"<");
42              temp = temp.replace(/&gt;/g,">");
43              temp = temp.replace(/&nbsp;/g," ");
44              temp = temp.replace(/&#39;/g,"\'");
45              temp = temp.replace(/&quot;/g,"\"");
46              return temp;  
47         },
48         /*5.用正则表达式实现html编码(转义)(另一种写法)*/
49         html2Escape:function(sHtml) {
50              return sHtml.replace(/[<>&"]/g,function(c){return {'<':'&lt;','>':'&gt;','&':'&amp;','"':'&quot;'}[c];});
51         },
52         /*6.用正则表达式实现html解码(反转义)(另一种写法)*/
53         escape2Html:function (str) {
54              var arrEntities={'lt':'<','gt':'>','nbsp':' ','amp':'&','quot':'"'};
55              return str.replace(/&(lt|gt|nbsp|amp|quot);/ig,function(all,t){return arrEntities[t];});
56         }
57     };

 

验证:
对我们接收到的数据进行过滤,过滤出恶意代码,得到合法代码。


- 黑名单

黑名单,即列举了恶意代码类型的名单。如果数据在黑名单里面,则被判定为非法代码;否则为合法代码。

缺陷:因为现实是复杂的,攻击者的手法是千奇百怪的,要创建一个包含所有可能的恶意代码的黑名单,往往是困难,甚至是不能的,很难做到全面覆盖,而且时效性短。

- 白名单

白名单是包含了合法代码的名单。通常来说,合法的情况是可以穷尽的,比如一个输入用户名的input,我就只接受字母,数字,下划线这三种类型的字符。

优势:可覆盖所有的合法场景,时效性长


验证结果处理 - 舍弃

当我们检测出用户的输入里面包含恶意代码的时候,直接舍弃掉这一条数据,这条数据不会出现在网站的任何地方,即叫做舍弃。

例如,有一个需要用户输入信用卡号码的input,用户不仅输入了数字,还输入了连接线(用户出于习惯)。我们直接舍弃这条数据,把这条数据判定为不合法。当然,相应地,你会给用户返回一个错误提醒。

验证结果处理 - 消毒

当我们检测出用户的输入里面包含恶意代码的时候,经过一定的处理方式,去掉恶意的部分,留下合法的代码,即叫做消毒。

还是用户输入信用卡号码的例子。对比舍弃的做法,消毒的做法是允许用户输入连接线,只是我们拿到数据之后,把连接线给去掉,最后得到只包含数字的信用卡号码

xss小游戏:

https://alf.nu/alert1 

 

3、iframe使用
a. 如何让自己的网站不被其他网站的 iframe 引用?(点击劫持--clickjacking)
利用透明 iframe 覆盖原网页诱导用户进行某些操作达成目的,进行点击劫持攻击。通常的攻击步骤是这样的:

  1. 攻击者精心构造一个诱导用户点击的内容,比如Web页面小游戏
  2. 将我们的页面放入到iframe当中
  3. 利用z-index等CSS样式将这个iframe叠加到小游戏的垂直方向的正上方
  4. 把iframe设置为100%透明度
  5. 受害者访问到这个页面后,肉眼看到的是一个小游戏,如果受到诱导进行了点击的话,实际上点击到的却是iframe中的我们的页面
  6. 点击劫持的危害在于,攻击利用了受害者的用户身份,在其不知情的情况下进行一些操作。如果只是迫使用户关注某个微博账号的话,看上去仿佛还可以承受,但是如果是删除某个重要文件记录,或者窃取敏感信息,那么造成的危害可就难以承受了。

如何防御

  • 在HTTP header中加入 X-FRAME-OPTIONS 属性:该响应头属性是用来给浏览器指示允许一个页面可否在<frame>,<iframe>,<embed>或者<object>中展现的标记。站点可以通过确保网站没有被嵌入到别人的站点里面。

          DENY:不能被所有网站嵌套或加载;
          SAMEORIGIN:只能被同域网站嵌套或加载;
          ALLOW-FROM URL:可以被指定网站嵌套或加载。

  • 判断当前网页是否被 iframe 嵌套
// 检测当前网站是否被第三方iframe引用
// 若相等证明没有被第三方引用,若不等证明被第三方引用。当发现被引用时强制跳转百度。
if(top.location != self.location){
    top.location.href = self.location
}

 

b. 如何防御被使用的 iframe 对当前网站某些操作
有些时候我们的前端页面需要用到第三方提供的页面组件,通常会以iframe的方式引入。例如使用iframe在页面上添加第三方提供的广告、天气预报、社交分享插件等等。
iframe在给我们的页面带来更多丰富的内容和能力的同时,也带来了不少的安全隐患。因为iframe中的内容是由第三方来提供的,默认情况下他们不受我们的控制,他们可以在iframe中运行JavaScirpt脚本、Flash插件、弹出对话框等等,这可能会破坏前端用户体验。
如何防御
在HTML5中,iframe有了一个叫做sandbox的安全属性,通过它可以对iframe的行为进行各种限制,充分实现“最小权限“原则。使用sandbox的最简单的方式就是只在iframe元素中添加上这个关键词就好,就像下面这样:

<iframe sandbox src="..."> ... </iframe>

当sandbox保持属性值为空,那么浏览器将会对iframe实施史上最严厉的调控限制,基本上来讲就是除了允许显示静态资源以外,其他什么都做不了。比如不准提交表单、不准弹窗、不准执行脚本等等,连Origin都会被强制重新分配一个唯一的值,换句话讲就是iframe中的页面访问它自己的服务器都会被算作跨域请求。
另外,sandbox也提供了丰富的配置参数,我们可以进行较为细粒度的控制。一些典型的参数如下:
allow-forms:允许iframe中提交form表单
allow-popups:允许iframe中弹出新的窗口或者标签页(例如,window.open(),showModalDialog(),target=”_blank”等等)
allow-scripts:允许iframe中执行JavaScript
allow-same-origin:允许iframe中的网页开启同源策略

 

4、打开新页面也可能有风险--opener
在项目中需要 打开新标签 进行跳转一般会有两种方式

// 1) HTML -> <a target='_blank' href='http://www.baidu.com'>
// 2) JS -> window.open('http://www.baidu.com')
/*
* 这两种方式看起来没有问题,但是存在漏洞。
* 通过这两种方式打开的页面可以使用 window.opener 来访问源页面的 window 对象。
* 场景:
* A 页面通过 <a> 或 window.open 方式,打开 B 页面。但是 B 页面存在恶意代码如下:
* window.opener.location.replace('https://www.baidu.com') 【此代码仅针对打开新标签有效】
* 此时,用户正在浏览新标签页,但是原来网站的标签页已经被导航到了百度页面。
* 恶意网站可以伪造一个足以欺骗用户的页面,使得进行恶意破坏。
* 即使在跨域状态下 opener 仍可以调用 location.replace 方法。
*/

 

如何防御
a、<a target="_blank" href="">

<a target="_blank" href="" rel="noopener noreferrer nofollow">a标签跳转url</a>
<!-- 
  通过 rel 属性进行控制:
  noopener:会将 window.opener 置空,从而源标签页不会进行跳转(存在浏览器兼容问题)
  noreferrer:兼容老浏览器/火狐。禁用HTTP头部Referer属性(后端方式)。
  nofollow:SEO权重优化,详情见 https://blog.csdn.net/qq_33981438/article/details/80909881
 -->


b、window.open()

<button onclick='openurl("http://www.baidu.com")'>click跳转</button>

function openurl(url) {
    var newTab = window.open();
    newTab.opener = null;
    newTab.location = url;
}

 

 

 

 

 


引用:
https://zhuanlan.zhihu.com/p/83865185
https://www.jianshu.com/p/734bcceb4f36
https://segmentfault.com/a/1190000016551188
https://insights.thoughtworks.cn/eight-security-problems-in-front-end/

标签:总结,XSS,temp,前端,用户,replace,安全,iframe,页面
来源: https://www.cnblogs.com/decayedTooth/p/15543598.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有