XSS攻击一般指的是经过利用网页开发时留下的漏洞,经过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序一般是JavaScript,但实际上也能够包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能获得包括但不限于更高的权限(如执行一些操做)、私密网页内容、会话和cookie等各类内容。(内容摘自百度百科)javascript
xss攻击类型可分为两种,反射型和存储型,顾名思义一种是保存进了数据库,另外一种是在url中直接触发,没保存进数据库,下面一一介绍。html
url参数直接注入前端
场景说明:在网站的搜索框内直接输入攻击脚本java
// 搜索框搜索
http://localhost/?keyWord=<script>alert(111)</script>
复制代码
存储到DB后读取时注入git
场景说明:攻击脚本做为留言内容,提交给后台保存,刷新页面后端返回攻击脚本给前端github
// 留言板插入数据库
留言测试<script>alert(222)</script>//留言内容 复制代码
攻击脚本经过接口存入数据库中,当页面刷新时,插入的脚本替换页面HTML节点内容,脚本随即执行,引起漏洞攻击正则表达式
<!-- content变量被攻击脚本替换 -->
<div>
{{content}}
</div>
<div>
<script>
</script>
</div>
复制代码
经过修改或者添加HTML属性,触发攻击事件数据库
<!-- 图片地址异常后,引起错误事件 -->
<img src="#{image}"/>
<img src=" 1"onerror="alert(1)" />
复制代码
经过获取用户输入的变量或者其余保存的变量,在脚本中打印后端
<script>
var data = params;
console.log(data)
// 输入内容
params = "hello":alert(1)
</script>
复制代码
富文本须要保留HTML
HTML有XSS攻击风险浏览器
总体思路:转义
转义时机:
转义方式更倾向于第一种:由于输入是一次性性能消费,而输出会是屡次,形成性能浪费,本文的示例代码内容因为我的编译、演示方便缘由是采用第二种方式-返回时转义,请各位读者知晓
处理思路:转义< >
,使之不能以html
标签的形式保存或者返回给前端
//转义函数
var escapeHtml = function(str){
str = str.replace(/</g,'<');
str = str.replace(/>/g,'>')
return str
}
复制代码
// 转义前
<script>alert(111)</script>
// 转移后
<script>alert(111)</script>
// 页面dom呈现
<script>alert(111)</script>//字符串类型
||
<span><script>alert(111)</script></span>
复制代码
处理思路:转义"
引号,使标签内属性不能自闭合,引发触发事件
// 转义函数
var escapeHtmlProperty = function(str){
if(!str)return '';
str = str.replace(/"/g,'&quto;');//替换双引号
str = str.replace(/'/g,''');//替换单引号
str = str.replace(/ /g,' ');//替换空格
return str;
}
复制代码
// 转义前
<img src=" 1"onerror="alert(1)" />
// 转义后
<img src="1&quto; onerror=&quto;alert(1)" />
// 页面dom呈现
<img src="1&quto; onerror=&quto;alert(1)" />
复制代码
那么问题来了,转义了HTML
属性中的大于号、小于号,会对元素产生其余影响吗?转义了HTML
节点内容中的单引号、双引号、空格,会对元素产生其余影响吗?
答案是不会产生影响的,读者能够自行验证。
此时能够合并上面的两个函数,总体处理HTML
节点和属性,合并函数以下:
// 转义函数
var escapeHtml = function(str){
str = str.replace(/&/g,'&');//&符号也须要转义,可是必定放在第一个转
str = str.replace(/</g,'<');
str = str.replace(/>/g,'>')
str = str.replace(/"/g,'&quto;');//替换双引号
str = str.replace(/'/g,''');//替换单引号
// 空格的转义影响其实并不大,能够省略
// str = str.replace(/ /g,' ');//替换空格
return str
}
复制代码
处理思路:转义双引号或者JSON_encode
//转义函数
var escapeForJs =function(str){
if(!str)return '';
str = str.replace(/"/g,'\\"');//js中双引号的转义和HTML中不一样,不能使用HTML转义方法
return str;
}
复制代码
原函数:
<script>
var str = "!{keyWord}";
console.log(str)
</script>
//hello world";alert(1);"
//转义前
<script> hello world alert(1)已经被弹出 </script>
//转义后
hello world";alert(1);"
复制代码
然而这样就安全了吗?
答案确定不是!
单引号、script标签、双引号、空格...均可以引起攻击,更为安全的方式-JSON_encode转义
JSON_encode转义-JSON.stringify
演示代码:
// 转义函数
JSON.stringify(参数)
复制代码
//转义前
hello world";alert(1);"
//转义后
hello world";alert(1);"
复制代码
处理思路:过滤
好比
script
标签、onerror
标签...所有过滤掉
按照白名单过滤保留部分标签和属性,只容许保留名单内的标签、属性
示例攻击代码:
<!-- 可能输入的攻击脚本 -->
<font color=\"red\">这是红色字</font><script>alert('富文本')</script>
<a href=\"javascript:alert(1)\"></a>
<img src=\"abc\" onerror=\"alert(1)\">
..onfocus,
..onmounseover,
..onmenucontext,
...
复制代码
//过滤函数
var xssFilter = function (html) {
if (!html) return '';
html = html.replace(/<\s*\/?script\s*>/g,'');
html = html.replace(/javascript:[^'"]*/g,'');
html = html.replace(/onerror\s*=\s*['"]?[^'"]*['"]?/g,'');
...
return html
}
复制代码
HTML中带有事件触发的都有可能成为攻击的突破口,面对这种状况,怎么防护呢?下面介绍白名单过滤。
处理思路:整理富文本中全部的标签属性,过滤只容许这些属性经过,其余属性则不容许经过
处理方式:将HTML解析成树状结构,和浏览器解析HTML过程相似,再去遍历树状结构元素,在过滤范围内的容许经过,没在过滤范围内的,则去掉
示例攻击代码:
//可能输入的攻击脚本
<font color=\"red\">这是红色字</font><script>alert('富文本')</script>
<a href=\"javascript:alert(1)\"></a>
<img src=\"abc\" onerror=\"alert(1)\">
..onfocus,
..onmounseover,
..onmenucontext,
...
复制代码
//过滤代码
var xssFilter = function (html) {
if (!html) return '';
//白名单
var whiteList = {
'img': ['src'],
'font':['color','size'],
'a':['href']
};
var cheerio = require('cheerio');
var $ = cheerio.load(html);
$('*').each(function (index, elem) {
if (!whiteList[elem.name]) {
$(elem).remove();
return;
}
for (var attr in elem.attribs) {
if (whiteList[elem.name].indexOf(attr) === -1) {
$(elem).attr(attr, null);
}
}
})
return $.html()
}
复制代码
cheerio是为服务器特别定制的,快速、灵活、实施的以jQuery为核心实现的对DOM操做方案
//基础用法
const cheerio = require('cheerio');
const $ = cheerio.load('<h2 class="title">Hello world</h2>');
$('h2.title').text('Hello there!');
$('h2').addClass('welcome');
$.html();
//=> <html><head></head><body><h2 class="title welcome">Hello there!</h2></body></html>
复制代码
安装方式、语法等此处不过多介绍,须要的读者请跳转官网阅读
代码中主要使用它把HTML
结构转换成可直接使用的数据结构,再循环去比较、移除。
那有没有现有的可直接使用的第三方框架吗?答案是确定的
xss
是一个用于对用户输入的内容进行过滤,以免遭受 XSS 攻击的模块。主要用于论坛、博客、网上商店等等一些可容许用户录入页面排版、格式控制相关的 HTML 的场景,xss模块经过白名单来控制容许的标签及相关的标签属性,另外还提供了一系列的接口以便用户扩展,比其余同类模块更为灵活中文官网地址
示例代码:
//过滤函数
var xssFilter = function (html) {
if (!html) return '';
var xss = require('xss');
var ret = xss(html);
return ret;
}
复制代码
就是如此的简单,固然还须要调整,此处就不过多介绍了,下面介绍下xss
模块的特性及基本使用方法。
在Node.js
中使用
var xss = require("xss");
var html = xss('<script>alert("xss");</script>');
console.log(html);
复制代码
在浏览器端使用
<script src="https://rawgit.com/leizongmin/js-xss/master/dist/xss.js"></script>
<script> // 使用函数名 filterXSS,用法同样 var html = filterXSS('<script>alert("xss");</scr' + 'ipt>'); alert(html); </script> 复制代码
其余使用模式及用法请参考官网案例
若是须要简单、快速、安全的开发选用第三方的库固然更好,可是使用过程可能会有这样或者那样的问题,达不到业务的要求等等,相较于第三方的库本身设置白名单去处理的话,就更容易控制、定制化效果明显,相对问题可能会更少,仁者见仁智者见智,读者根据实际状况可自行选择。
内容安全策略 (CSP) 是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本 (XSS) 和数据注入攻击等。不管是数据盗取、网站内容污染仍是散发恶意软件,这些攻击都是主要的手段。
配置内容安全策略涉及到添加 Content-Security-Policy HTTP头部到一个页面,并配置相应的值,以控制用户代理(浏览器等)能够为该页面获取哪些资源。
一个网站管理者想要全部内容均来自站点的同一个源 (不包括其子域名)
Content-Security-Policy: default-src 'self'
复制代码
一个在线邮箱的管理者想要容许在邮件里包含HTML,一样图片容许从任何地方加载,但不容许JavaScript或者其余潜在的危险内容(从任意位置加载)。
Content-Security-Policy: default-src 'self' *.mailsite.com; img-src *
复制代码
更多示例及用法请参考MDN-CSP
安全做为系统的壁垒,重要程度不用多说。 XSS攻击更是安全防护的重中之中。 本文记录的是笔者在开发过程当中遇到的问题及处理的思路。可供有相似问题的读者参考。 其余安全方面的文章笔者会持续更新,欢迎各位读者提出意见和建议。