前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >前端安全之XSS攻防之道

前端安全之XSS攻防之道

原创
作者头像
MarsBoy
发布2019-09-03 15:41:01
9300
发布2019-09-03 15:41:01
举报
文章被收录于专栏:前端安全

1 什么是XSS

XSS全称Cross Site Script,意为跨站脚本攻击。本质上是一种“HTML注入”,由于历史原因,最初这种攻击在演示的时候是跨域攻击的,所以就叫跨域脚本攻击。但是目前,XSS指所有通过外部注入,导致浏览器执行了攻击者的脚本而产生的攻击行为,已经不特指跨站。

2 XSS的分类

XSS攻击根据攻击效果可以分为以下三类:

1.反射型XSS

按照字面意思理解,就是需要把黑客的代码反射给浏览器执行,这种攻击一般是用户点击了黑客构造的一个url链接,然后url链接中参数具有攻击性,页面脚本直接按照正常的逻辑去解析了这个参数,导致恶意脚本被执行。

2.存储型XSS

存储型XSS顾名思义,是将攻击代码通过某种方式存储到服务器端,等到某个特定环境的时候,再在前端展示解析并执行,达到攻击的目的。

比如一个某个博客网站,黑客写一篇带有可执行脚本的内容发表之后,内容存储到服务器端。后面,每个访问这篇文章的用户,页面都将执行这段脚本,并受到攻击。

3.DOM XSS

DOM XSS不是按照是否存储数据到服务器来划分,它特指通过修改DOM节点的内容,然后触发脚本执行的一种攻击方式。

所以当一个反射型XSS通过DOM节点输出脚本控制,它就属于DOM XSS,一个存储型XSS通过DOM节点输出控制,也属于DOM XSS。

比如一个网站的搜索引擎输入框,会将你输入的搜索关键词,显示在另一个DOM中,如果没做任何过滤和转义,那么输入的而已内容将被解析,从而导致XSS。

3 XSS的典型案例分析和防御

在分析案例之前,我们需要了解XSS的两个关键因素:输入源,输出点。

输入源是XSS攻击中,攻击代码的来源,可以是url,可以是表单内容,可以是事件消息数据等。

输出点是攻击代码被触发的最直接的方式,比如innerHTML执行,eval执行,javascript:方式触发。

3.1 url参数攻击

下面的示例给出了一个典型的反射性XSS的行为:

代码语言:txt
复制
<!--  a.test.com/username.html -->
<html>
<head>
	<title>attack</title>
</head>
<body>
<div>
Hello,<span id="username"></span>
</div>
<script>
	var userName=decodeURIComponent(milo.request('username'));
	document.getElementById('username').innerHTML=userName;
</script>
</body>
</html>

上面是一个简单的取url上的username参数作为用户名,直接显示到页面的span元素中的逻辑。

假如该页面位于:a.test.com/username.html

那么攻击者可以让用户访问如下链接:

a.test.com/username.html?username=%3Cscript%3Ealert(document.cookie)%3C%2Fscript%3E

即可达到攻击目的,用户访问后,将会弹出用户端cookie。

1 输入源

这种攻击的输入源很明显,就是url上的参数。

2 输出点

这种攻击的输出点可以是多种,看具体的执行方式,本案例中的输出点是innerHTML执行导致了脚本节点被解析。

3 防御

针对本案例,我们可以用以下两种方式进行防御:

url参数过滤,对url上取到的username参数进行xss过滤,转义。使innerHTML的时候不能被解析成script节点。

使用innerText方式,或者jquery的$.text方法写入内容,就不会被解析。

3.2 表单用户输入攻击

表单输入一般会制造存储型XSS,输入的内容存到了后端,然后再在其它的页面显示出来,显示的时候执行了相关的脚本逻辑,导致被攻击。

例如有某博客网站:www.xxblog.com

写博客的页面在 www.xxblog.com/write.html ,

看文章的页面在 www.xxblog.com/blogs/xxx.html。

下面简要列一下两个页面的核心代码:

写博客的页面

代码语言:txt
复制
  <html>
 	<head>
		<title>写博客</title>
	</head>
	<body>
		<textadrea id="blog_content" placeholder="请输入博客内容"></textadrea>
		<a class="btn">发布博客</a>
		<script type="text/javascript">
			var blogContent=$('#blog_content').text();
			$.ajax({
				url:'api/submitBlog.php',
				type:'POST',
				data:{
					blog:blogContent
				},
				success:function(data){
					if(0 == data.iRet){
						alert('发表成功');
					}
				}
			})
		</script>
	</body>
 </html>

看博客的页面:

代码语言:txt
复制
  <html>
  	<head>
		<meta http-equiv="content-type" content="text/html;charset=utf-8" >
		<title>博客详情</title>
	</head>
	<body>
	<div id="details"></div>
	<script type="text/javascript">
		$.ajax({
			url:'api/getBlog.php',
			type:'GET',
			data:{
				blogId:'xx'
			},
			success:function(data){
				if(0 == data.iRet){
					//显示文章内容
					$('#details').html(data.blogContent);
				}
			}
		})
	</script>
	</body>
  </html>

当黑客写入博客的时候,插入一些可执行的脚本到比如script,onerror事件等地方。发布这些博客之后,带恶意代码的博客就被存储到了网站的数据库中,最后其它用户浏览这些博客的时候,可执行代码就会被解析执行,达到了攻击的目的。

1 输入源

本案例中的输入源可以说是网站数据库存储的数据,更源头的应该是存储的内容的来源:写博客的表单节点。

2 输出点

本案例中的输出点,同样是innerHTML直接输出,导致了html解析,然后可执行的js呗执行。

下图1是本案例中存储型XSS攻击的4个关键环节:

 图1 存储型XSS攻击的4个环节
图1 存储型XSS攻击的4个环节

3 防御

推荐1 后端过滤博客内容。存储型xss要过滤的话,最好是在后端过滤,因为后端可以认为是恶意代码源最可靠的拦截阶段了。

图3显示了存储型XSS经历4个环节:

(1)前端表单制造内容------(2)提交内容------(3)存储内容-------(4)前端HTML显示存储的内容

其中第2步可以伪造,可以不通过前端页面发布内容。所以过滤逻辑必须在第3步和第4步执行。选择第3步不选择第4步的原因是恶意代码可能会在多个页面(例如图中的PageB,PageC,PageD等)被使用和解析,但是恶意代码值保存一份。所以在入库的时候在后端逻辑中过滤是最直接也是最省事和安全的。

.

不推荐2 博客显示的时候使用innerText或者$.text()方法,但是这种方法不推荐使用。因为博客属于富文本内容,单纯的显示文本不可取,博客内容的本身就是一段拥有图片,颜色,字体等各种控制元素的html内容。

3.3 PostMessage攻击

有一类XSS是通过前端跨域的机制,让网站执行了跨域的不安全脚本导致的。

我们知道postMessage可以跨域通信,假如现在有一个场景是跨域设置cookie,在活动页面a.test.com需要将一些cookie对象设置到game.test.com中,这里需要活动页面通过postMessage将cookie数据传给game.test.com的页面B。这时,假如有一个黑客网站hack.com的页面,也通过postMessage向页面B发送带有攻击的数据,然后B获取到带有攻击数据的cookie数据,解析后导致B页面受到攻击,窃取game.test.com的cookie或者test.com下的cookie。

下面是game.test.com的页面B接收message消息的代码:

代码语言:txt
复制
//跨域设置cookie的message事件
function doSetCookie(e){
	var data=e.data;
	var oCookie='';
	eval('oCookie='+data);
	//拿oCookie去设置
	//...
}

if(window.addEventListener){
	window.addEventListener('message',doSetCookie,false)
}else{
	window.onmessage=doSetCookie;
}

正常情况下,a.test.com通过postMessage向B设置cookie,没有问题。下面将模拟黑客网站hack.com向B发送一个攻击信息:

代码语言:txt
复制
 //hack.com的攻击信息
 var oIframe=document.getElementById('winB');
 oIframe.contentWindow.postMessage("(alert(document['cookie']))","*");

以上信息代码会 B页面的message事件,然后执行eval函数,导致cookie被窃取。

其实纵观整个流程我们发现了B页面很明显的几个漏洞:

1.接受message信息的时候,没有判断来源origin

2.取message数据data之后,使用了eval函数直接解析数据

我们来分析本案例中的XSS输入源,输出点。

1. 输入源

本案例中的输入源是postMessage通信信息。

2. 输出点

本案例中,通过eval函数解析message数据。输出点是eval函数。

3. 防御

针对本类postMessage通信引起的XSS漏洞,其本质上属于反射性XSS。postMessage通信可以跨域,但是我们可以控制来源域,一般我们业务逻辑接受message信息,只针对白名单的来源域即可,这样可以屏蔽白名单之外的黑客网站页面发送的有害信息。还有一种方案同样是作用在输出点上,就是避免message的data被直接解析,避免使用eval,innerHTML等危险的方式处理data。可以给数据制定一个规范,比如用竖线分割不同字段的值等等。

总结来说就是2点:

1 对来源域进行判断,最好加上白名单验证机制。如下:

代码语言:txt
复制
function onMessage(event){
	var origin=event.origin || event.originalEvent.origin;
	if(isLegal(origin)){
		//do something
	}else{
		//origin不在白名单内,直接return
		return;
	}
}

2 对message中拿到的数据进行过滤,避免使用高危方法处理数据。比如针对本案例,可以这么做:

代码语言:txt
复制
//拿到信息
var data=event.data;
//假如cookie是固定格式为:a=xx; b=xxx; c=xxx
var arrCookie=data.split(' ;');
//do something

3.4 第三方组件漏洞

这种类型的XSS危害性很大,第三方组件的漏洞导致的XSS不是特指某一种类型的XSS,而是指页面中引用第三方组件,调用第三方组件的方法时,由于第三方组件的漏洞导致的XSS安全问题。

曾经的jquery就曝出了XSS漏洞,在jquery的1.11版本之前,使用jquery的选择器方法,如果传入的选择器字符串是非法的,可能会导致选择器字符串被执行。

如下所示:

代码语言:txt
复制
//假设有以下表单页面a.html供用户填写个人信息
var domId=location.hash;
var sTel=$(domId).val();//获取用户输入的电话号码

假如用户点击了非法的链接进入个人信息填写页面,可能会导致XSS漏洞:如下链接就直接会窃取用户的cookie

代码语言:txt
复制
<a href="./a.html#userinfo<img src=1 onerror=alert(document.cookie)>">填写个人信息</a>

上面的链接跳转到信息填写页面,然后hash参数是个具有危害性的内容,在jquery1.11之前的版本中作为选择器传入,都会导致页面创建HTML,从而执行了onerror中的js代码,导致XSS攻击。

1 输入源

本案例中的输入源是url上的hash参数

2 输出点

本案例中的输出点是jquery组件的选择器方法$,导致了恶意参数传入后被解析成HTML执行。

3 预防

针对本案例,如何有效的避免这类XSS攻击呢。下面支招:

1 输入检查,从hash获取的元素id,需要进行过滤,因为id不可能带有括号,冒号,等于号等特殊字符,所以制定相关的策略进行过滤即可

.

2 多关注业界XSS相关的动态,禁止使用会触发XSS的第三方组件和版本。

4 XSS小结

XSS攻击的案例数不胜数,这里笔者只列举了几种常见的常见加以分析。其实,综合来看,XSS攻击的本质还是一种“HTML”和脚本注入。在实际工作中,面对XSS,不要惊慌,分析输入源和输出点综合进行防御即可。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 什么是XSS
  • 2 XSS的分类
  • 3 XSS的典型案例分析和防御
    • 3.1 url参数攻击
      • 3.2 表单用户输入攻击
        • 3.3 PostMessage攻击
          • 3.4 第三方组件漏洞
          • 4 XSS小结
          相关产品与服务
          云数据库 Redis
          腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档