UNPKG

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