XSS攻击基础讲解及预防攻略

XSS攻击

XSS介绍

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节点内容

攻击脚本经过接口存入数据库中,当页面刷新时,插入的脚本替换页面HTML节点内容,脚本随即执行,引起漏洞攻击正则表达式

<!-- content变量被攻击脚本替换 -->
<div>
    {{content}}
</div>
<div>
    <script>
    </script>
</div>

复制代码
  • HTML属性

经过修改或者添加HTML属性,触发攻击事件数据库

<!-- 图片地址异常后,引起错误事件 -->
<img src="#{image}"/>
<img src=" 1"onerror="alert(1)" />
复制代码
  • JavaScript代码

经过获取用户输入的变量或者其余保存的变量,在脚本中打印后端

<script>
    var data = params;
    console.log(data)
    // 输入内容
    params = "hello":alert(1)
</script>
复制代码
  • 富文本

富文本须要保留HTML
HTML有XSS攻击风险浏览器

处理方法

总体思路:转义

转义时机:

  1. 存入数据库时转义
  2. 返回给前端时转义

转义方式更倾向于第一种:由于输入是一次性性能消费,而输出会是屡次,形成性能浪费,本文的示例代码内容因为我的编译、演示方便缘由是采用第二种方式-返回时转义,请各位读者知晓

HTML节点内容

处理思路:转义< >,使之不能以html标签的形式保存或者返回给前端

//转义函数
var escapeHtml = function(str){
    str = str.replace(/</g,'&lt;');
    str = str.replace(/>/g,'&gt;')
    return str
}
复制代码
// 转义前
<script>alert(111)</script>
// 转移后
&lt;script&gt;alert(111)&lt;/script&gt;
// 页面dom呈现
<script>alert(111)</script>//字符串类型
              ||
<span><script>alert(111)</script></span>
复制代码

HTML属性

处理思路:转义"引号,使标签内属性不能自闭合,引发触发事件

// 转义函数
var escapeHtmlProperty = function(str){
    if(!str)return '';
    str = str.replace(/"/g,'&quto;');//替换双引号
    str = str.replace(/'/g,'&#39;');//替换单引号
    str = str.replace(/ /g,'&#32;');//替换空格
    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,'&amp;');//&符号也须要转义,可是必定放在第一个转
    str = str.replace(/</g,'&lt;');
    str = str.replace(/>/g,'&gt;')
    str = str.replace(/"/g,'&quto;');//替换双引号
    str = str.replace(/'/g,'&#39;');//替换单引号
    // 空格的转义影响其实并不大,能够省略
    // str = str.replace(/ /g,'&#32;');//替换空格 
    return str
}

复制代码

JavaScript代码

处理思路:转义双引号或者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转义

JavaScript代码_JSON_encode转义

JSON_encode转义-JSON.stringify
演示代码:

// 转义函数
JSON.stringify(参数)
复制代码
//转义前
hello world";alert(1);"
//转义后
hello world";alert(1);"
复制代码

富文本

处理思路:过滤

  1. 黑名单过滤

好比 script标签、onerror标签...所有过滤掉

  • 利:实现简单-正则表达式就可处理
  • 弊:HTML标签过于庞杂,不免会留有漏洞
  1. 白名单过滤

按照白名单过滤保留部分标签和属性,只容许保留名单内的标签、属性

  • 利:比较完全,只容许指定的标签、属性存在
  • 弊:实现起来相对麻烦,将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 '';
	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介绍

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结构转换成可直接使用的数据结构,再循环去比较、移除。
那有没有现有的可直接使用的第三方框架吗?答案是确定的

js-XSS

xss是一个用于对用户输入的内容进行过滤,以免遭受 XSS 攻击的模块。主要用于论坛、博客、网上商店等等一些可容许用户录入页面排版、格式控制相关的 HTML 的场景,xss模块经过白名单来控制容许的标签及相关的标签属性,另外还提供了一系列的接口以便用户扩展,比其余同类模块更为灵活中文官网地址
示例代码:

//过滤函数
var xssFilter = function (html) {
	if (!html) return '';
	var xss = require('xss');
	var ret = xss(html);
	return ret;
}
复制代码

就是如此的简单,固然还须要调整,此处就不过多介绍了,下面介绍下xss模块的特性及基本使用方法。

特性

  • 白名单控制容许的 HTML 标签及各标签的属性
  • 经过自定义处理函数,可对任意标签及其属性进行处理

使用方法:

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

内容安全策略 (CSP) 是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本 (XSS) 和数据注入攻击等。不管是数据盗取、网站内容污染仍是散发恶意软件,这些攻击都是主要的手段。

  • Content Security Policy
  • 内容安全策略
  • 用于指定那些内容可执行

使用方法:

配置内容安全策略涉及到添加 Content-Security-Policy HTTP头部到一个页面,并配置相应的值,以控制用户代理(浏览器等)能够为该页面获取哪些资源。

常见用例:

示例1

一个网站管理者想要全部内容均来自站点的同一个源 (不包括其子域名)

Content-Security-Policy: default-src 'self'
复制代码

示例2

一个在线邮箱的管理者想要容许在邮件里包含HTML,一样图片容许从任何地方加载,但不容许JavaScript或者其余潜在的危险内容(从任意位置加载)。

Content-Security-Policy: default-src 'self' *.mailsite.com; img-src *
复制代码

更多示例及用法请参考MDN-CSP

结语

安全做为系统的壁垒,重要程度不用多说。 XSS攻击更是安全防护的重中之中。 本文记录的是笔者在开发过程当中遇到的问题及处理的思路。可供有相似问题的读者参考。 其余安全方面的文章笔者会持续更新,欢迎各位读者提出意见和建议。

相关文章
相关标签/搜索