跨站脚本(XSS)

1.1 XSS定义

XSS,即为(Cross Site Scripting),中文名为跨站脚本,是发生在目标用户的浏览器层面上的,当渲染DOM树的过程发生了不在预期内执行的JS代码时,就发生了XSS攻击。javascript

跨站脚本的重点不在“跨站”上,而在于“脚本”上。大多数XSS攻击的主要方式就是嵌入一段远程或者第三方域上的JS代码。其实是在目标网站的做用域下执行了这段JS代码。css

1.2 XSS攻击方式

1.2.1 反射型 XSS

反射型XSS,也叫非持久型XSS,是指发生请求时,XSS代码出如今请求URL中,做为参数提交到服务器,服务器解析并响应。响应结果中包含XSS代码,最后浏览器解析并执行。html

从概念上能够看出,反射型XSS代码是首先出如今URL中的,而后须要服务端解析,最后须要浏览器解析以后XSS代码才可以攻击。前端

 

举一个小例子java

使用express起一个web服务器,而后设置一下请求接口。经过ajax的GET请求将参数发往服务器,服务器解析成json后响应。将返回的数据解析后显示到页面上。(没有对返回的数据进行解码和过滤等操做。)node

 1 html
 2 <textarea name="txt" id="txt" cols="80" rows="10">
 3 <button type="button" id="test">测试</button>
 4 
 5 js
 6 var test = document.querySelector('#test')
 7 test.addEventListener('click', function () {
 8   var url = `/test?test=${txt.value}`   // 1. 发送一个GET请求
 9   var xhr = new XMLHttpRequest()
10   xhr.onreadystatechange = function () {
11     if (xhr.readyState === 4) {
12       if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
13         // 3. 客户端解析JSON,并执行
14         var str = JSON.parse(xhr.responseText).test
15         var node = `${str}`
16         document.body.insertAdjacentHTML('beforeend', node)
17       } else {
18         console.log('error', xhr.responseText)
19       }
20     }
21   }
22   xhr.open('GET', url, true)
23   xhr.send(null)
24 }, false)
25 
26 express
27 var express = require('express');
28 var router = express.Router();
29 
30 router.get('/test', function (req, res, next) {
31  // 2. 服务端解析成JSON后响应
32   res.json({
33     test: req.query.test
34   })
35 })
View Code

如今咱们经过给textarea添加一段有攻击目的的img标签,git

<img src="null" onerror='alert(document.cookie)' />

实际的页面时这样的。github

ok如今,咱们点击<测试>按钮,一个XSS攻击就发生了。下面图片中是获取了本地的部分cookie信息web

实际上,咱们只是模拟攻击,经过alert获取到了我的的cookie信息。可是若是是黑客的话,他们会注入一段第三方的js代码,而后将获取到的cookie信息存到他们的服务器上。这样的话黑客们就有机会拿到咱们的身份认证作一些违法的事情了。ajax

以上,存在的一些问题,主要在于没有对用户输入的信息进行过滤,同时没有剔除掉DOM节点中存在的一些有危害的事件和一些有危害的DOM节点。

1.2.3 存储型 XSS

存储型XSS,也叫持久型XSS,主要是将XSS代码发送到服务器(不论是数据库、内存仍是文件系统等。),而后在下次请求页面的时候就不用带上XSS代码了。

最典型的就是留言板XSS。用户提交了一条包含XSS代码的留言到数据库。当目标用户查询留言时,那些留言的内容会从服务器解析以后加载出来。浏览器发现有XSS代码,就当作正常的HTML和JS解析执行。XSS攻击就发生了。

1.2.4 DOM XSS

DOM XSS攻击不一样于反射型XSS和存储型XSS,DOM XSS代码不须要服务器端的解析响应的直接参与,而是经过浏览器端的DOM解析。这彻底是客户端的事情。

DOM XSS代码的攻击发生的可能在于咱们编写JS代码形成的。咱们知道eval语句有一个做用是将一段字符串转换为真正的JS语句,所以在JS中使用eval是很危险的事情,容易形成XSS攻击。避免使用eval语句。

如如下代码:

1 test.addEventListener('click', function () {
2   var node = window.eval(txt.value)
3   window.alert(node)
4 }, false)
5 
6 txt中的代码以下
7 <img src='null' onerror='alert(123)' />
View Code

以上经过eval语句就形成了XSS攻击。

1.2.5 XSS危害

  • 经过document.cookie盗取cookie

  • 使用js或css破环页面正常的结构与样式

  • 流量劫持(经过访问某段具备window.location.href定位到其余页面)

  • Dos攻击:利用合理的客户端请求来占用过多的服务器资源,从而使合法的用户没法获得服务器响应

  • 利用iframe、frame、XMLHttpRequest或上述Flash等方式,以(被攻击)用户的身份执行一些管理动做,或执行一些通常的如发微博、加好友、发私信等操做。

  • 利用可被攻击的域受到其余域信任的特色,以受信任来源的身份请求一些平时不容许的操做,如进行不当的投票活动。

1.3 XSS防护

从以上的反射型DOM XSS能够看出,咱们不能原样的将用户输入的数据直接存在服务器,须要对数据进行一些处理,以上代码的一些问题以下:

  • 没有过滤危险的DOM节点。若是具备执行脚本能力的script,具备显示广告和色情图片的img,具备改变样式的link,style,具备内嵌页面的iframe,frame等元素节点。

  • 没有过滤危险的属性节点。如事件,style,src,href等

  • 没有对cookie设置httpOnly

  • 若是将以上三点都在渲染过程当中过滤,那么出现的XSS攻击的改了也就小不少。

解决方法以下

1.3.1 对cookie的保护

1.对重要的cookie设置httpOnly,防止客户端经过document.cookie读取cookie。服务端能够设置此字段。

 

1.3.2 对用户输入数据的处理

1.编码:不能对用户输入的内容都保持原样,对用书输入的数据进行字符实体编码。对于字符实体

2.解码:原样显示内容的时候必须解码,否则显示不到内容了。

3.过滤:把输入的一些不合法的东西都过滤掉,从而保证安全性。如移除用户上传的DOM属性,如onerror,移除用户上传的Style节点,iframe, script节点等。

经过一个例子讲解一下如何处理用户输入的数据。

实现原理以下:

  1. 存在一个parse函数,对输入的数据进行处理,返回处理以后的数据

  2. 对输入的数据(如DOM节点)进行解码(使用第三方库 he.js)

  3. 过滤掉一些元素有危害的元素节点与属性节点。如script标签,onerror事件等。(使用第三方库HTMLParser.js)

 1 <script src='/javascripts/htmlparse.js'></script>
 2 <script src='/javascripts/he.js'></script>
 3 // 第三方库资源在文章底部给出
 4 
 5 // parse函数实现以下
 6 
 7 function parse (str) {
 8       // str假如为某个DOM字符串
 9       // 1. result为处理以后的DOM节点
10       let result = ''
11       // 2. 解码
12       let decode = he.unescape(str, {
13           strict: true
14       })
15       HTMLParser(decode, {
16           start (tag, attrs, unary) {
17               // 3. 过滤常见危险的标签
18               if (tag === 'script' || tag === 'img' || tag === 'link' || tag === 'style' || tag === 'iframe' || tag === 'frame') return
19               result += `<${tag}`
20               for (let i = 0; i < attrs.length; i++) {
21                   let name = (attrs[i].name).toLowerCase()
22                   let value = attrs[i].escaped
23                   // 3. 过滤掉危险的style属性和js事件
24                   if (name === 'style' || name === 'href' || name === 'src' || ~name.indexOf('on')) continue
25                   result += ` ${name}=${value}`
26               }
27               result += `${unary ? ' /' : ''} >`
28           },
29           chars (text) {
30               result += text
31           },
32           comment (text) {
33               result += `<!-- ${text} -->`
34           },
35           end (tag) {
36               result += `</${tag}>`
37           }
38       })
39       return result
40   }
View Code

所以,有了以上的parse函数以后,就能够避免大部分的xss攻击了。

 1 test.addEventListener('click', function () {
 2   // ... 省略部分代码
 3   xhr.onreadystatechange = function () {
 4     if (xhr.readyState === 4) {
 5       if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
 6         // 3. 客户端解析JSON,并执行
 7         // test按钮的点击事件中惟一的变化就是使用parse对服务端返回的数据进行了解码和过滤的处理。
 8         var str = parse(JSON.parse(xhr.responseText).test)
 9         // 经过parse解析以后返回的数据就是安全的DOM字符串
10         var node = `${str}`
11         document.body.insertAdjacentHTML('beforeend', node)
12       }
13     }
14   }
15   // ... 省略部分代码
16 }, false)
View Code

那么,例子说完了

稍微总结一下

  1. 一旦在DOM解析过程成出现不在预期内的改变(JS代码执行或样式大量变化时),就可能发生XSS攻击

  2. XSS分为反射型XSS,存储型XSS和DOM XSS

  3. 反射型XSS是在将XSS代码放在URL中,将参数提交到服务器。服务器解析后响应,在响应结果中存在XSS代码,最终经过浏览器解析执行。

  4. 存储型XSS是将XSS代码存储到服务端(数据库、内存、文件系统等),在下次请求同一个页面时就不须要带上XSS代码了,而是从服务器读取。

  5. DOM XSS的发生主要是在JS中使用eval形成的,因此应当避免使用eval语句。

  6. XSS危害有盗取用户cookie,经过JS或CSS改变样式,DDos形成正经常使用户没法获得服务器响应。

  7. XSS代码的预防主要经过对数据解码,再过滤掉危险标签、属性和事件等。

参考资源

  1. 《WEB前端黑客技术揭秘》

  2. 浅谈XSS攻击的那些事(附经常使用绕过姿式)

  3. XSS实战:我是如何拿下你的百度帐号

  4. HTMLParser

  5. he

  6. Web安全-XSS

相关文章
相关标签/搜索