1.1 XSS定义

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

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

1.2 XSS攻击方式

1.2.1 反射型 XSS

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

从概念上可以看出,反射型XSS代码是首先出现在URL中的,然后需要服务端解析,最后需要浏览器解析之后XSS代码才能够攻击。

举一个小例子

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

 html
<textarea name="txt" id="txt" cols="80" rows="10">
<button type="button" id="test">测试</button> js
var test = document.querySelector('#test')
test.addEventListener('click', function () {
var url = `/test?test=${txt.value}` // 1. 发送一个GET请求
var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// 3. 客户端解析JSON,并执行
var str = JSON.parse(xhr.responseText).test
var node = `${str}`
document.body.insertAdjacentHTML('beforeend', node)
} else {
console.log('error', xhr.responseText)
}
}
}
xhr.open('GET', url, true)
xhr.send(null)
}, false) express
var express = require('express');
var router = express.Router(); router.get('/test', function (req, res, next) {
// 2. 服务端解析成JSON后响应
res.json({
test: req.query.test
})
})

现在我们通过给textarea添加一段有攻击目的的img标签,

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

实际的页面时这样的。

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

实际上,我们只是模拟攻击,通过alert获取到了个人的cookie信息。但是如果是黑客的话,他们会注入一段第三方的js代码,然后将获取到的cookie信息存到他们的服务器上。这样的话黑客们就有机会拿到我们的身份认证做一些违法的事情了。

以上,存在的一些问题,主要在于没有对用户输入的信息进行过滤,同时没有剔除掉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语句。

如以下代码:

 test.addEventListener('click', function () {
var node = window.eval(txt.value)
window.alert(node)
}, false) txt中的代码如下
<img src='null' onerror='alert(123)' />

以上通过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)

 <script src='/javascripts/htmlparse.js'></script>
<script src='/javascripts/he.js'></script>
// 第三方库资源在文章底部给出 // parse函数实现如下 function parse (str) {
// str假如为某个DOM字符串
// 1. result为处理之后的DOM节点
let result = ''
// 2. 解码
let decode = he.unescape(str, {
strict: true
})
HTMLParser(decode, {
start (tag, attrs, unary) {
// 3. 过滤常见危险的标签
if (tag === 'script' || tag === 'img' || tag === 'link' || tag === 'style' || tag === 'iframe' || tag === 'frame') return
result += `<${tag}`
for (let i = 0; i < attrs.length; i++) {
let name = (attrs[i].name).toLowerCase()
let value = attrs[i].escaped
// 3. 过滤掉危险的style属性和js事件
if (name === 'style' || name === 'href' || name === 'src' || ~name.indexOf('on')) continue
result += ` ${name}=${value}`
}
result += `${unary ? ' /' : ''} >`
},
chars (text) {
result += text
},
comment (text) {
result += `<!-- ${text} -->`
},
end (tag) {
result += `</${tag}>`
}
})
return result
}

因此,有了以上的parse函数之后,就可以避免大部分的xss攻击了。

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

那么,例子说完了

稍微总结一下

  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

跨站脚本(XSS)的更多相关文章

  1. 跨站脚本 XSS<一:介绍>

    *XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任 跨站脚本(Cross-site scripting,通常简称为XSS)是一种网站应用程序的安全漏洞攻击,是代码注入 ...

  2. 跨站脚本 XSS<一:防御方法>

    1. 过滤特殊字符 避免XSS的方法之一主要是将用户所提供的内容进行过滤,许多语言都有提供对HTML的过滤: PHP的htmlentities()或是htmlspecialchars(). Pytho ...

  3. 预防跨站脚本(xss)

    对xss的防护方法结合在两点上输入和输出,一是严格控制用户表单的输入,验证所有输入数据,有效监测到攻击,go web表单中涉及到.二是对所有输出的数据进行处理,防止已成功注入的脚本在浏览器端运行. 在 ...

  4. Struts1.x 跨站脚本(XSS)漏洞的解决

    一. 演示XSS   当访问一个不存在的网址时,例如[url]http://localhost:8080/demo/noAction.do[/url],那么Struts处理后都会跳到提示“Invali ...

  5. 跨站脚本(XSS)攻击

    https://blog.csdn.net/extremebingo/article/details/81176394

  6. web前端安全 XSS跨站脚本 CSRF跨站请求伪造 SQL注入

    web安全,从前端做起,总结下web前端安全的几种技术: 1,XSS XSS的全称是Cross Site Scripting,意思是跨站脚本,XSS的原理也就是往HTML中注入脚本,HTML指定了脚本 ...

  7. 【前端安全】JavaScript防http劫持与XSS

    作为前端,一直以来都知道HTTP劫持与XSS跨站脚本(Cross-site scripting).CSRF跨站请求伪造(Cross-site request forgery).但是一直都没有深入研究过 ...

  8. ASP.NET Core中的OWASP Top 10 十大风险-跨站点脚本攻击 (XSS)

    不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译自: https://dotnetcoretutorials.com/201 ...

  9. 【前端安全】JavaScript防http劫持与XSS (转)

    作为前端,一直以来都知道HTTP劫持与XSS跨站脚本(Cross-site scripting).CSRF跨站请求伪造(Cross-site request forgery).但是一直都没有深入研究过 ...

随机推荐

  1. printf函数中*修饰符的作用,如:%*d

    在printf函数中,我们可以用数字修饰来控制打印的字段宽度和精度,如下(为强调视觉效果,均填充0): #include <stdio.h> int main() { ; float f= ...

  2. windows10家庭版的策略组

    策略组是个好东西,可惜家庭版没有 但是,请看大佬博客https://blog.csdn.net/cangsheng45/article/details/82262037

  3. ACM 英文学习系列

    因为ACM题目描述全是英文,所以有必要学习学习相关词汇...内心极为无奈 废话不多说 rooted binary tree 有根二叉树     integers n 英[ˈɪntɪdʒəz] 整数   ...

  4. CDQ分治笔记+例题

    CDQ分治是一种离线分治算法,它基于时间顺序对操作序列进行分治. 看这样一个问题: 在一个三维坐标系中,有若干个点,每个点都有对应的坐标 \((X_i , Y_i , Z_i)\) ,我们要对于每个点 ...

  5. Windows10访问Ubuntu子系统(WSL)的桌面环境

    原文地址:https://blog.csdn.net/xmh19936688/article/details/90212960 Windows10访问Ubuntu子系统(WSL)的桌面环境文章目录Wi ...

  6. 记一个开发是遇到的坑之Oralce 字符串排序

    简单描述一下情况,就是存储过程中用一个字符串类型的字段作为患者就诊的排序号,结果莫名发现叫完1号后叫了11.12等患者.用户的反馈不一定准确,自己加了日志的,赶紧拷贝日志来观察一下.结果发现实际情况就 ...

  7. Html介绍,认识html文件基本结构

    一个HTML文件的基本机构如下: <html><head>...</head><body>...</body></html>代码 ...

  8. Java学习之String、StringBuffer、StringBuilder

    String 我们知道字符串的分配和其他对象分配一样,是需要消耗高昂的时间和空间的,而且字符串我们使用的非常多.JVM为了提高性能和减少内存的开销,在实例化字符串的时候进行了一些优化:使用字符串常量池 ...

  9. spring cloud微服务快速教程之(九) Spring Cloud Alibaba--sentinel-限流、熔断降级

    0.前言 sentinel的限流.降级功能强大,可以在控制面板中任意制定规则,然后推送到微服务中: 可以根据URL单独制定规则,也可以根据资源名批量制定规则: 需要注意的地方是:1.GITHUB文件在 ...

  10. unity目前学的一些操作

    目前是根据b站的一位迈扣老师的30集基础教学学习的,用的是sunny land这个资源包进行的教学,这位老师讲得很清晰,吐词清晰,思路也清晰,推荐哦.其实我比较喜欢这样的老师,思路 吐词清晰.就像以前 ...