共计 2232 个字符,预计需要花费 6 分钟才能阅读完成。
一、简介
跨站脚本(cross site script)为了避免与样式 css 混淆,所以简称为 XSS。
XSS 是指恶意攻击者利用网站没有对用户提交数据进行转义处理或者过滤不足的缺点,进而添加一些代码,嵌入到 web 页面中去。使别的用户访问都会执行相应的嵌入代码。从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。
XSS 是一种经常出现在 web 应用中的计算机安全漏洞,也是 web 中最主流的攻击方式。
二、原因解析
主要原因:过于信任客户端提交的数据!
解决办法:不信任任何客户端提交的数据,只要是客户端提交的数据就应该先进行相应的过滤处理然后方可进行下一步的操作。
进一步分析细节:
客户端提交的数据本来就是应用所需要的,但是恶意攻击者利用网站对客户端提交数据的信任,在数据中插入一些符号以及 javascript 代码,那么这些数据将会成为应用代码中的一部分了。那么攻击者就可以肆无忌惮地展开攻击啦。
因此我们绝不可以信任任何客户端提交的数据!!!
三、XSS 攻击分类
1、反射型 xss 攻击
又称为非持久性跨站点脚本攻击,它是最常见的类型的 XSS。漏洞产生的原因是攻击者注入的数据反映在响应中。一个典型的非持久性 XSS 包含一个带 XSS 攻击向量的链接(即每次攻击需要用户的点击)。
2、存贮型 xss 攻击
又称为持久型跨站点脚本,它一般发生在 XSS 攻击向量 (一般指 XSS 攻击代码) 存储在网站数据库,当一个页面被用户打开的时候执行。每当用户打开浏览器, 脚本执行。持久的 XSS 相比非持久性 XSS 攻击危害性更大, 因为每当用户打开页面,查看内容时脚本将自动执行。
3、DOMBasedXSS(基于 dom 的跨站点脚本攻击)
基于 DOM 的 XSS 有时也称为 type0XSS。当用户能够通过交互修改浏览器页面中的 DOM(DocumentObjectModel)并显示在浏览器上时,就有可能产生这种漏洞,从效果上来说它也是反射型 XSS。
通过修改页面的 DOM 节点形成的 XSS,称之为 DOMBasedXSS
前提是易受攻击的网站有一个 HTML 页面采用不安全的方式从 document.location 或 document.URL 或 document.referrer 获取数据(或者任何其他攻击者可以修改的对象)。
四、XSS 漏洞修复
XSS 漏洞的起因就是没有对用户提交的数据进行严格的过滤处理。因此在思考解决 XSS 漏洞的时候,我们应该重点把握如何才能更好的将用户提交的数据进行安全过滤。
1、html 实体
在 html 中有些字符,像 (<) 这类的,对 HTML(标准通用标记语言下的一个应用)来说是有特殊意义的,所以这些字符是不允许在文本中使用的。要在 HTML 中显示 (<) 这个字符,我们就必须使用实体字符。
html 实体的存在是导致 XSS 漏洞的主要原因之一。
因此我们需要将这些实体全部转换为相应的实体编号。
2、HTML Encode
用户将数据提交上来的时候进行 HTML 编码,将相应的符号转换为实体名称再进行下一步的处理。
3、修复漏洞方针 1、将重要的 cookie 标记为 http only, 这样的话 Javascript 中的 document.cookie 语句就不能获取到 cookie 了.
2、表单数据规定值的类型,例如:年龄应为只能为 int、name 只能为字母数字组合。。。。
4、对数据进行 Html Encode 处理
5、过滤或移除特殊的 Html 标签,例如: <script>, <iframe> , < for <, > for >, " for
6、过滤 JavaScript 事件的标签。例如 “onclick=”, “onfocus” 等等。
【特别注意:】
在有些应用中是允许 html 标签出现的,甚至是 javascript 代码出现。因此我们在过滤数据的时候需要仔细分析哪些数据是有特殊要求(例如输出需要 html 代码、javascript 代码拼接、或者此表单直接允许使用等等),然后区别处理!
// HTML 和实体相互转换
String.prototype.convertEntity=(function(){
// 字符实体表
let entity = {
quot : ‘”‘,
lt : ‘<‘,
gt : ‘>’,
amp : ‘&’,
nbsp : ‘ ‘
}
let entity_cover_key=”,entity_cover={};
for(let item in entity){
entity_cover_key+=entity[item];
entity_cover[entity[item]]=’&’+item+’;’;
}
return function(type){
if(type == 1){
return this.replace(/&([^&;]+);/g,function(a,b){
return typeof entity[b] === ‘string’ ? entity[b] : a;
})
}else{
let reg=new RegExp(‘[‘+entity_cover_key+’]’,’g’)
return this.replace(reg,function(c){
return entity_cover;
});
}
}
})()
console.log(‘"><& &asds;’.covert(1)); // “”><& ”
console.log(‘<div>121212</div>’.covert()); // <div>121212</div>