了解XSS漏洞,避免被恶意攻击

最近公司安全小组,检查到公司一个项目出现了XSS漏洞,要项目开发人员赶紧进行修复。我查了查资料,这里记录一下。

1、XSS是什么

XSS是跨站脚本攻击(Cross-Site Scripting)的简称。

      XSS是一种注入脚本式攻击,攻击者利用如提交表单、发布评论等方式将事先准备好的恶意脚本注入到那些良性可信的网站中,当其他用户进入该网站后,脚本就在用户不知情的情况下偷偷地执行了,这样的脚本可能会窃取用户的信息、修改页面内容、或者伪造用户执行其他操作等等,后果不可估量。

XSS攻击通常会发生在以下情况下:

  • 向一个web app中输入含有一些不良代码的内容,通常是一段含有http请求的代码
  • 这些内容包含在发给其他用户的动态内容之中,而且这些内容还没有经过校验

发送到Web浏览器的恶意内容通常采用JavaScript代码片段的形式,但也可能包括HTML,Flash或浏览器可能执行的任何其他类型的代码。 基于XSS的攻击方式几乎是无限的。但是它们通常的方式是:

  • 向攻击者发送包括诸如cookie或其他会话信息的私有数据
  • 攻击者篡改页面的内容
  • 在用户的机器上,以含有漏洞的网站为幌子,执行其他恶意操作

OWASP(Open Web Application Security Project)最新公布的2017 10项最严重的 Web 应用程序安全风险中,XSS榜上有名。

 

2、通过哪种方法“注入”恶意脚本的呢?

下面来系统的看下 XSS 有哪些注入的方法:

  • 在 HTML 中内嵌的文本中,恶意内容以 script 标签形成注入。
  • 在内联的 JavaScript 中,拼接的数据突破了原本的限制(字符串,变量,方法名等)。
  • 在标签属性中,恶意内容包含引号,从而突破属性值的限制,注入其他属性或者标签。
  • 在标签的 href、src 等属性中,包含 javascript: 等可执行代码。
  • 在 onload、onerror、onclick 等事件中,注入不受控制代码。
  • 在 style 属性和标签中,包含类似 background-image:url("javascript:..."); 的代码(新版本浏览器已经可以防范)。
  • 在 style 属性和标签中,包含类似 expression(...) 的 CSS 表达式代码(新版本浏览器已经可以防范)。

不仅仅是业务上的“用户的 UGC 内容”可以进行注入,包括 URL 上的参数等都可以是攻击的来源。在处理输入时,以下内容都不可信:

  • 来自用户的 UGC 信息
  • 来自第三方的链接
  • URL 参数
  • POST 参数
  • Referer (可能来自不可信的来源)
  • Cookie (可能来自其他子域注入)

 

总之,如果开发者没有将用户输入的文本进行合适的过滤,就贸然插入到 HTML 中,这很容易造成注入漏洞。攻击者可以利用漏洞,构造出恶意的代码指令,进而利用恶意代码危害数据安全。

3、XSS攻击的分类

一般会把XSS分为: 存储型XSS(Stored XSS)、反射型XSS(Reflected XSS)和 DOM-based XSS。

3.1 存储型 XSS

存储型 XSS 的攻击步骤:

  1. 攻击者将恶意代码提交到目标网站的数据库中。
  2. 用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返回给浏览器。
  3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。

3.2 反射型 XSS

反射型 XSS 的攻击步骤:

  1. 攻击者构造出特殊的 URL,其中包含恶意代码。
  2. 用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
  3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

反射型 XSS 跟存储型 XSS 的区别是:存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。

反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。

由于需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击。

POST 的内容也可以触发反射型 XSS,只不过其触发条件比较苛刻(需要构造表单提交页面,并引导用户点击),所以非常少见。

3.3 DOM 型 XSS

是指攻击者利用原生JavaScript代码篡改客户端的DOM结构,导致用户操作执行了“意外”的动作

DOM 型 XSS 的攻击步骤:

  1. 攻击者构造出特殊的 URL,其中包含恶意代码。
  2. 用户打开带有恶意代码的 URL。
  3. 用户浏览器接收到响应后解析执行,前端 JavaScript 取出 URL 中的恶意代码并执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。

关于DOM-Based型XSS可以看下面的例子

下面是一段网站的代码,它提供一个下拉框让你来选择语言,而且还根据你URL上的default参数来进行默认语言的推荐。

Select your language:

<select><script>

document.write("<OPTION value=1>"+document.location.href.substring(document.location.href.indexOf("default=")+8)+"</OPTION>");

document.write("<OPTION value=2>English</OPTION>");

</script></select>
…

通常情况下,这个页面的地址会是下面的样子:

http://www.some.site/page.html?default=French

而DOM-Based型XSS会利用这个页面DOM结构的漏洞,向受害者发送下面的链接

http://www.some.site/page.html?default=<script>alert(document.cookie)</script>

当受害者点开这个链接时,就会将用户的cookie全部alert出来了。

 

4、XSS的防范原则

关于XSS攻击的防范,我在OWASP上给出防范方法进行了精简,如果你有兴趣的话,可以去看详细内容

4.1 原则1——永远不要把不受信任的数据插入到原本允许JavaScript可以放置的地方

就像下面的代码中所示的那样:

<script>...永远不要把不受信任的数据放在这...</script>   直接放在script标签内
 
 <!--...永远不要把不受信任的数据放在这...-->             放在HTML注释内
 
 <div ...永远不要把不受信任的数据放在这...=test />       做为一个属性名
 
 <永远不要把不受信任的数据放在这... href="/test" />   做为一个标签名
 
 <style>...永远不要把不受信任的数据放在这...</style>   直接放在style标签内

 

4.2 原则2——在向元素中插入不受信任的HTML代码之前一定要进行转义

就像下面的代码中所示的那样:

<body>...将不受信任的数据转义后再放在这...</body>
 
 <div>...将不受信任的数据转义后再放在这...</div>
 
 any other normal HTML elements

常用的转义规则如下:

& --> &amp;
 < --> &lt;
 > --> &gt;
 " --> &quot;
 ' --> &#x27; 
 / --> &#x2F;

4.3 原则3——在向元素的属性插入不受信任的HTML代码之前一定要进行转义

看下面的代码:

<div attr=...将不受信任的数据转义后再放在这...>content</div>  
在没有加引号的属性值内
 
 <div attr='...将不受信任的数据转义后再放在这...'>content</div>
在加了单引号的属性值内

<div attr="...将不受信任的数据转义后再放在这...">content</div>
在加了双引号的属性值内

4.4 原则4——在用不受信任的数据向JavaScript代码赋值前,一定要进行转义

看下面的代码:

<script>alert('...将不受信任的数据转义后再放在这...')</script>     
在一个字符串之内
 
 <script>x='...将不受信任的数据转义后再放在这...'</script> 
在表达式的一侧
 
 <div onmouseover="x='...将不受信任的数据转义后再放在这...'"</div>  
在事件处理函数内

需要注意的是,有一些JavaScript函数永远无法安全的使用不受信任的数据作为输入,比如下面的代码:

<script>
 window.setInterval('即使你做了转义,但是仍然可能被XSS攻击');
 </script>

4.4.1 原则4.1——在HTML的上下文中对JSON值进行转义,并用JSON.parse()方法来读取值

一定要确保http response中的头部信息的content-type为application/json,而不是text/html,因为那样的话,很可能会被人利用进行XSS攻击。

一个坏的案例:

  HTTP/1.1 200
   Date: Wed, 06 Feb 2013 10:28:54 GMT
   Server: Microsoft-IIS/7.5....
   Content-Type: text/html; charset=utf-8 <-- bad
   ....
   Content-Length: 373
   Keep-Alive: timeout=5, max=100
   Connection: Keep-Alive
   {"Message":"No HTTP resource was found that matches the request URI 'dev.net.ie/api/pay/.html?HouseNumber=9&AddressLine
   =The+Gardens<script>alert(1)</script>&AddressLine2=foxlodge+woods&TownName=Meath'.","MessageDetail":"No type was found
   that matches the controller named 'pay'."}   <-- 这里script标签有可能会被执行

一个好的案例:

  HTTP/1.1 200
   Date: Wed, 06 Feb 2013 10:28:54 GMT
   Server: Microsoft-IIS/7.5....
   Content-Type: application/json; charset=utf-8 <--good
   .....
   .....

4.5 原则5——在将不受信任的数据作为CSS属性插入到文档之前一定要进行转义

看下面的代码

<style>selector { property : ...将不受信任的数据转义后再放在这...; } </style> 
属性值

 <style>selector { property : "...将不受信任的数据转义后再放在这..."; } </style>
属性值

 <span style="property : ...将不受信任的数据转义后再放在这...">text</span> 
属性值

需要注意的是,还是有一些CSS属性值对于“不受信任的”数据是无法确保万无一失的——即使做了转义,如下面的两个CSS属性:

{ background-url : "javascript:alert(1)"; }  
 { text-size: "expression(alert('XSS'))"; }   // only in IE

你应该确保所有CSS属性值引入的外部链接是由“http”开头的,而不是“javascript”开头的。

4.6 原则6——在向HTML的URL参数插入将不受信任的数据前,一定要将进行转义

看下面的代码

<a href="http://www.somesite.com?test=...将不受信任的数据转义后再放在这...">link</a >

5、加分原则

5.1 加分原则1——对于cookie使用httpOnly标识

使用httpOnly标识后的cookie JavaScript是无法获取的,又由于cookie是基于同源原则,所以一定程度上会防范那些利用客户cookie的XSS攻击。

5.2 加分原则2——在http header中使用Content Security Policy

利用http header中的属性值Content-Security-Policy来防范XSS。HTTP 响应头 Content-Security-Policy 允许站点管理者在指定的页面控制用户代理的资源。除了少数例外,这条政策将极大地指定服务源 以及脚本端点。

5.3 加分原则3——使用自动转义模板系统

许多Web应用程序框架提供了自动的上下文转义功能,如AngularJS严格的上下文转义Go模板。 尽可能使用这些技术。

5.4 加分原则4——在http header中使用X-XXS-Protection

HTTP X-XSS-Protection 响应头是Internet Explorer,Chrome和Safari的一个功能,当检测到跨站脚本攻击 (XSS)时,浏览器将停止加载页面。虽然这些保护在现代浏览器中基本上是不必要的,当网站实施一个强大的Content-Security-Policy来禁用内联的JavaScript ('unsafe-inline')时, 他们仍然可以为尚不支持 CSP 的旧版浏览器的用户提供保护。

这里,nginx统一加Security Header(add_header X-XSS-Protection '1; mode=block';),会增加安全性,但是不能完全避免攻击(我们还是会添加)

 

6. 开源项目

  公司有个开源项目,大家可以试试:

https://github.com/naver/lucy-xss-filter

7. 总结

XSS攻击的后果是不可估量的,而往往他又是容易被人忽视的。结合上面提到的几点,检查一下自己的Web App是否有上面的漏洞。

如果你坚持将全文都看完,你一定深爱着前端技术,那我觉得你有必要关注一下我的公众号——较真的前端,在那里会有更多的技术分享和前端干货等着你。

 

参考:

https://zhuanlan.zhihu.com/p/32237154

https://juejin.im/post/5bad9140e51d450e935c6d64#heading-24

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值