UNPKG

13.9 kBMarkdownView Raw
1[![NPM version][npm-image]][npm-url]
2[![build status][travis-image]][travis-url]
3[![Test coverage][coveralls-image]][coveralls-url]
4[![David deps][david-image]][david-url]
5[![node version][node-image]][node-url]
6[![npm download][download-image]][download-url]
7[![npm license][license-image]][download-url]
8
9[npm-image]: https://img.shields.io/npm/v/xss.svg?style=flat-square
10[npm-url]: https://npmjs.org/package/xss
11[travis-image]: https://img.shields.io/travis/leizongmin/js-xss.svg?style=flat-square
12[travis-url]: https://travis-ci.org/leizongmin/js-xss
13[coveralls-image]: https://img.shields.io/coveralls/leizongmin/js-xss.svg?style=flat-square
14[coveralls-url]: https://coveralls.io/r/leizongmin/js-xss?branch=master
15[david-image]: https://img.shields.io/david/leizongmin/js-xss.svg?style=flat-square
16[david-url]: https://david-dm.org/leizongmin/js-xss
17[node-image]: https://img.shields.io/badge/node.js-%3E=_0.10-green.svg?style=flat-square
18[node-url]: http://nodejs.org/download/
19[download-image]: https://img.shields.io/npm/dm/xss.svg?style=flat-square
20[download-url]: https://npmjs.org/package/xss
21[license-image]: https://img.shields.io/npm/l/xss.svg
22
23# 根据白名单过滤 HTML(防止 XSS 攻击)
24
25![xss](https://nodei.co/npm/xss.png?downloads=true&stars=true)
26
27---
28
29`xss`是一个用于对用户输入的内容进行过滤,以避免遭受 XSS 攻击的模块([什么是 XSS 攻击?](http://baike.baidu.com/view/2161269.htm))。主要用于论坛、博客、网上商店等等一些可允许用户录入页面排版、格式控制相关的 HTML 的场景,`xss`模块通过白名单来控制允许的标签及相关的标签属性,另外还提供了一系列的接口以便用户扩展,比其他同类模块更为灵活。
30
31**项目主页:** http://jsxss.com
32
33**在线测试:** http://jsxss.com/zh/try.html
34
35---
36
37## 特性
38
39* 白名单控制允许的 HTML 标签及各标签的属性
40* 通过自定义处理函数,可对任意标签及其属性进行处理
41
42## 参考资料
43
44* [XSS 与字符编码的那些事儿 ---科普文](http://drops.wooyun.org/tips/689)
45* [腾讯实例教程:那些年我们一起学 XSS](http://www.wooyun.org/whitehats/%E5%BF%83%E4%BC%A4%E7%9A%84%E7%98%A6%E5%AD%90)
46* [mXSS 攻击的成因及常见种类](http://drops.wooyun.org/tips/956)
47* [XSS Filter Evasion Cheat Sheet](https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet)
48* [Data URI scheme](http://en.wikipedia.org/wiki/Data_URI_scheme)
49* [XSS with Data URI Scheme](http://hi.baidu.com/badzzzz/item/bdbafe83144619c199255f7b)
50
51## 性能(仅作参考)
52
53* xss 模块:8.2 MB/s
54* validator@0.3.7 模块的 xss()函数:4.4 MB/s
55
56测试代码参考 benchmark 目录
57
58## 安装
59
60### NPM
61
62```bash
63npm install xss
64```
65
66### Bower
67
68```bash
69bower install xss
70```
71
72或者
73
74```bash
75bower install https://github.com/leizongmin/js-xss.git
76```
77
78## 使用方法
79
80### 在 Node.js 中使用
81
82```javascript
83var xss = require("xss");
84var html = xss('<script>alert("xss");</script>');
85console.log(html);
86```
87
88### 在浏览器端使用
89
90Shim 模式(参考文件 `test/test.html`):
91
92```html
93<script src="https://rawgit.com/leizongmin/js-xss/master/dist/xss.js"></script>
94<script>
95// 使用函数名 filterXSS,用法一样
96var html = filterXSS('<script>alert("xss");</scr' + 'ipt>');
97alert(html);
98</script>
99```
100
101AMD 模式(参考文件 `test/test_amd.html`):
102
103```html
104<script>
105require.config({
106 baseUrl: './',
107 paths: {
108 xss: 'https://rawgit.com/leizongmin/js-xss/master/dist/xss.js'
109 },
110 shim: {
111 xss: {exports: 'filterXSS'}
112 }
113})
114require(['xss'], function (xss) {
115 var html = xss('<script>alert("xss");</scr' + 'ipt>');
116 alert(html);
117});
118</script>
119```
120
121**说明:请勿将 URL https://rawgit.com/leizongmin/js-xss/master/dist/xss.js 用于生产环境。**
122
123### 使用命令行工具来对文件进行 XSS 处理
124
125### 处理文件
126
127可通过内置的 `xss` 命令来对输入的文件进行 XSS 处理。使用方法:
128
129```bash
130xss -i <源文件> -o <目标文件>
131```
132
133例:
134
135```bash
136xss -i origin.html -o target.html
137```
138
139### 在线测试
140
141执行以下命令,可在命令行中输入 HTML 代码,并看到过滤后的代码:
142
143```bash
144xss -t
145```
146
147详细命令行参数说明,请输入 `$ xss -h` 来查看。
148
149## 自定义过滤规则
150
151在调用 `xss()` 函数进行过滤时,可通过第二个参数来设置自定义规则:
152
153```javascript
154options = {}; // 自定义规则
155html = xss('<script>alert("xss");</script>', options);
156```
157
158如果不想每次都传入一个 `options` 参数,可以创建一个 `FilterXSS` 实例(使用这种方法速度更快):
159
160```
161options = {}; // 自定义规则
162myxss = new xss.FilterXSS(options);
163// 以后直接调用 myxss.process() 来处理即可
164html = myxss.process('<script>alert("xss");</script>');
165```
166
167`options` 参数的详细说明见下文。
168
169### 白名单
170
171通过 `whiteList` 来指定,格式为:`{'标签名': ['属性1', '属性2']}`。不在白名单上的标签将被过滤,不在白名单上的属性也会被过滤。以下是示例:
172
173```javascript
174// 只允许a标签,该标签只允许href, title, target这三个属性
175var options = {
176 whiteList: {
177 a: ["href", "title", "target"]
178 }
179};
180// 使用以上配置后,下面的HTML
181// <a href="#" onclick="hello()"><i>大家好</i></a>
182// 将被过滤为
183// <a href="#">大家好</a>
184```
185
186默认白名单参考 `xss.whiteList`
187
188### 自定义匹配到标签时的处理方法
189
190通过 `onTag` 来指定相应的处理函数。以下是详细说明:
191
192```javascript
193function onTag(tag, html, options) {
194 // tag是当前的标签名称,比如<a>标签,则tag的值是'a'
195 // html是该标签的HTML,比如<a>标签,则html的值是'<a>'
196 // options是一些附加的信息,具体如下:
197 // isWhite boolean类型,表示该标签是否在白名单上
198 // isClosing boolean类型,表示该标签是否为闭合标签,比如</a>时为true
199 // position integer类型,表示当前标签在输出的结果中的起始位置
200 // sourcePosition integer类型,表示当前标签在原HTML中的起始位置
201 // 如果返回一个字符串,则当前标签将被替换为该字符串
202 // 如果不返回任何值,则使用默认的处理方法:
203 // 在白名单上: 通过onTagAttr来过滤属性,详见下文
204 // 不在白名单上:通过onIgnoreTag指定,详见下文
205}
206```
207
208### 自定义匹配到标签的属性时的处理方法
209
210通过 `onTagAttr` 来指定相应的处理函数。以下是详细说明:
211
212```javascript
213function onTagAttr(tag, name, value, isWhiteAttr) {
214 // tag是当前的标签名称,比如<a>标签,则tag的值是'a'
215 // name是当前属性的名称,比如href="#",则name的值是'href'
216 // value是当前属性的值,比如href="#",则value的值是'#'
217 // isWhiteAttr是否为白名单上的属性
218 // 如果返回一个字符串,则当前属性值将被替换为该字符串
219 // 如果不返回任何值,则使用默认的处理方法
220 // 在白名单上: 调用safeAttrValue来过滤属性值,并输出该属性,详见下文
221 // 不在白名单上:通过onIgnoreTagAttr指定,详见下文
222}
223```
224
225### 自定义匹配到不在白名单上的标签时的处理方法
226
227通过 `onIgnoreTag` 来指定相应的处理函数。以下是详细说明:
228
229```javascript
230function onIgnoreTag(tag, html, options) {
231 // 参数说明与onTag相同
232 // 如果返回一个字符串,则当前标签将被替换为该字符串
233 // 如果不返回任何值,则使用默认的处理方法(通过escape指定,详见下文)
234}
235```
236
237### 自定义匹配到不在白名单上的属性时的处理方法
238
239通过 `onIgnoreTagAttr` 来指定相应的处理函数。以下是详细说明:
240
241```javascript
242function onIgnoreTagAttr(tag, name, value, isWhiteAttr) {
243 // 参数说明与onTagAttr相同
244 // 如果返回一个字符串,则当前属性值将被替换为该字符串
245 // 如果不返回任何值,则使用默认的处理方法(删除该属)
246}
247```
248
249### 自定义 HTML 转义函数
250
251通过 `escapeHtml` 来指定相应的处理函数。以下是默认代码 **(不建议修改)**
252
253```javascript
254function escapeHtml(html) {
255 return html.replace(/</g, "&lt;").replace(/>/g, "&gt;");
256}
257```
258
259### 自定义标签属性值的转义函数
260
261通过 `safeAttrValue` 来指定相应的处理函数。以下是详细说明:
262
263```javascript
264function safeAttrValue(tag, name, value) {
265 // 参数说明与onTagAttr相同(没有options参数)
266 // 返回一个字符串表示该属性值
267}
268```
269
270### 自定义 CSS 过滤器
271
272如果配置中允许了标签的 `style` 属性,则它的值会通过[cssfilter](https://github.com/leizongmin/js-css-filter) 模块处理。
273`cssfilter` 模块包含了一个默认的 CSS 白名单,你可以通过以下的方式配置:
274
275```javascript
276myxss = new xss.FilterXSS({
277 css: {
278 whiteList: {
279 position: /^fixed|relative$/,
280 top: true,
281 left: true
282 }
283 }
284});
285html = myxss.process('<script>alert("xss");</script>');
286```
287
288如果不想使用 CSS 过滤器来处理 `style` 属性的内容,可指定 `css` 选项的值为 `false`
289
290```javascript
291myxss = new xss.FilterXSS({
292 css: false
293});
294```
295
296要获取更多的帮助信息可看这里:https://github.com/leizongmin/js-css-filter
297
298### 快捷配置
299
300#### 去掉不在白名单上的标签
301
302通过 `stripIgnoreTag` 来设置:
303
304* `true`:去掉不在白名单上的标签
305* `false`:(默认),使用配置的`escape`函数对该标签进行转义
306
307示例:
308
309当设置 `stripIgnoreTag = true`时,以下代码
310
311```html
312code:<script>alert(/xss/);</script>
313```
314
315过滤后将输出
316
317```html
318code:alert(/xss/);
319```
320
321#### 去掉不在白名单上的标签及标签体
322
323通过 `stripIgnoreTagBody` 来设置:
324
325* `false|null|undefined`:(默认),不特殊处理
326* `'*'|true`:去掉所有不在白名单上的标签
327* `['tag1', 'tag2']`:仅去掉指定的不在白名单上的标签
328
329示例:
330
331当设置 `stripIgnoreTagBody = ['script']`时,以下代码
332
333```html
334code:<script>alert(/xss/);</script>
335```
336
337过滤后将输出
338
339```html
340code:
341```
342
343#### 去掉 HTML 备注
344
345通过 `allowCommentTag` 来设置:
346
347* `true`:不处理
348* `false`:(默认),自动去掉 HTML 中的备注
349
350示例:
351
352当设置 `allowCommentTag = false` 时,以下代码
353
354```html
355code:<!-- something --> END
356```
357
358过滤后将输出
359
360```html
361code: END
362```
363
364## 应用实例
365
366### 允许标签以 data-开头的属性
367
368```javascript
369var source = '<div a="1" b="2" data-a="3" data-b="4">hello</div>';
370var html = xss(source, {
371 onIgnoreTagAttr: function(tag, name, value, isWhiteAttr) {
372 if (name.substr(0, 5) === "data-") {
373 // 通过内置的escapeAttrValue函数来对属性值进行转义
374 return name + '="' + xss.escapeAttrValue(value) + '"';
375 }
376 }
377});
378
379console.log("%s\nconvert to:\n%s", source, html);
380```
381
382运行结果:
383
384```html
385<div a="1" b="2" data-a="3" data-b="4">hello</div>
386convert to:
387<div data-a="3" data-b="4">hello</div>
388```
389
390### 允许名称以 x-开头的标签
391
392```javascript
393var source = "<x><x-1>he<x-2 checked></x-2>wwww</x-1><a>";
394var html = xss(source, {
395 onIgnoreTag: function(tag, html, options) {
396 if (tag.substr(0, 2) === "x-") {
397 // 不对其属性列表进行过滤
398 return html;
399 }
400 }
401});
402
403console.log("%s\nconvert to:\n%s", source, html);
404```
405
406运行结果:
407
408```html
409<x><x-1>he<x-2 checked></x-2>wwww</x-1><a>
410convert to:
411&lt;x&gt;<x-1>he<x-2 checked></x-2>wwww</x-1><a>
412```
413
414### 分析 HTML 代码中的图片列表
415
416```javascript
417var source =
418 '<img src="img1">a<img src="img2">b<img src="img3">c<img src="img4">d';
419var list = [];
420var html = xss(source, {
421 onTagAttr: function(tag, name, value, isWhiteAttr) {
422 if (tag === "img" && name === "src") {
423 // 使用内置的friendlyAttrValue函数来对属性值进行转义,可将&lt;这类的实体标记转换成打印字符<
424 list.push(xss.friendlyAttrValue(value));
425 }
426 // 不返回任何值,表示还是按照默认的方法处理
427 }
428});
429
430console.log("image list:\n%s", list.join(", "));
431```
432
433运行结果:
434
435```html
436image list:
437img1, img2, img3, img4
438```
439
440### 去除 HTML 标签(只保留文本内容)
441
442```javascript
443var source = "<strong>hello</strong><script>alert(/xss/);</script>end";
444var html = xss(source, {
445 whiteList: [], // 白名单为空,表示过滤所有标签
446 stripIgnoreTag: true, // 过滤所有非白名单标签的HTML
447 stripIgnoreTagBody: ["script"] // script标签较特殊,需要过滤标签中间的内容
448});
449
450console.log("text: %s", html);
451```
452
453运行结果:
454
455```html
456text: helloend
457```
458
459## 授权协议
460
461```text
462Copyright (c) 2012-2018 Zongmin Lei(雷宗民) <leizongmin@gmail.com>
463http://ucdok.com
464
465The MIT License
466
467Permission is hereby granted, free of charge, to any person obtaining
468a copy of this software and associated documentation files (the
469"Software"), to deal in the Software without restriction, including
470without limitation the rights to use, copy, modify, merge, publish,
471distribute, sublicense, and/or sell copies of the Software, and to
472permit persons to whom the Software is furnished to do so, subject to
473the following conditions:
474
475The above copyright notice and this permission notice shall be
476included in all copies or substantial portions of the Software.
477
478THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
479EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
480MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
481NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
482LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
483OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
484WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
485```