{"_id":"@58fe/hammer-security","_rev":"13-351e3c6c9ad6a313ffec1976ce6e58ad","name":"@58fe/hammer-security","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.1":{"name":"@58fe/hammer-security","version":"0.1.1","description":"security plugin in hammer frameworks","main":"index.js","scripts":{"lint":"eslint .","test":"npm run lint -- --fix && npm run test-local","test-local":"mocha \"test/**/*.test.js\" -exit","cov":"nyc -r lcov -r text-summary npm run test-local","cov-clid":"nyc --reporter=text npm run test-local","ci":"npm run lint && npm run cov","autod":"autod"},"keywords":["hammer","security","node"],"dependencies":{"csrf":"^3.0.6","escape-html":"^1.0.3","is":"^3.3.0","methods":"^1.1.2","statuses":"^1.5.0","type-is":"^1.6.16","xss":"^1.0.3","chalk":"^2.4.2"},"devDependencies":{"autod":"^3.0.1","eslint":"^5.15.1","eslint-config-egg":"^7.1.0","koa":"^2.7.0","mocha":"^6.0.2","nyc":"^13.3.0","should":"^13.2.3","supertest":"^4.0.0"},"ci":{"version":"8, 10, 11"},"author":{"name":"Artorias Chan"},"license":"MIT","gitHead":"3ac9e5aac09336b15efa27dd12af081b0be1be9b","_id":"@58fe/hammer-security@0.1.1","_npmVersion":"5.6.0","_nodeVersion":"8.11.4","_npmUser":{"name":"artoriaschan","email":"544396118@qq.com"},"dist":{"integrity":"sha512-propLWP7A7XjgWLma3j5OrL+CBnQ7MxKV+iGV9dT/iVrT/wGcpd9yKCVSWAKPxkIqcEoomcOqZirDyXuhNZAaw==","shasum":"88099f07607e97b35e29f593546f1c3b871de78d","tarball":"https://registry.npmjs.org/@58fe/hammer-security/-/hammer-security-0.1.1.tgz","fileCount":42,"unpackedSize":41737,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcttA8CRA9TVsSAnZWagAA8NwP/2TqoIDAHAALqnwjF8+n\nNDfA1/8BQBj/zYxrVLryc12Et1EX8py+JgTvztxjb/oiTOCV5ZC+dP5K0pch\nWdFXzGbqxO17pahvIXKhL+hl6CXnpc4NkrTCPP0qtV340/PA03BMOsMfuTJT\nPgmOgohMDqmDad9QqT9swI7IWWGgmB2LEliutvaocv1nzftPya3jRI2xkiam\n3YYGVqTfkd6zhf8aeFVrpf/RIvikzwzjN8mecza7de4fXqC21LcUU9MEMTgk\nXx5YfxhMAwf40z0wKm5+c6O07EcYbsK/doAaJP6F0xSCO/Y7ihMRXbHlxtU8\nGfEAoL35ti0fszUwqSuiFwb4J58LTkINaPip/BdduVz+BjvUvtwhekj3jDkl\n2O2J6DwPaknKhKc3MTRonWg/MZFqoVIFUplPzMWjYP1QlnUoq/EYvPEDVtAE\n2frX044X1LJBTwakGHT6eJNPV7stXyIFq8Td/xKE3xyQ68n7etZ6TjoM0uxQ\nKaarSkfSczrs+X8lq1Mp0bp7PoHcMT6JAsjgwCkTonbzSyHpf3E9eposY9Vj\nUptdZPzpclGeRdW0Y868hFyreGlEYL/TdSwfuY3F7gcn0Ts7XBOSA4haFnJE\nM5vgpx1j2N7U7dMYz5slZyDa0zvFRrbvVsJz9w5k+LNitDOkiI1WToiB8iW+\nIX4l\r\n=ZSPx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDs43SYu1KOCpUy3pfuFse1ISnr5hH0314I6DkI+PccTAiB81W/CSG5zvC6SL0AQe456d/O83MQNKp6lWX4KwiceKA=="}]},"maintainers":[{"name":"zhangyongming","email":"zishixiuwen@126.com"},{"name":"reking","email":"724255238@qq.com"},{"name":"rainbow_zh","email":"zhouhong07@58ganji.com"},{"name":"jackchou","email":"934803531@qq.com"},{"name":"shangpanpan","email":"crazycoding@foxmail.com"},{"name":"imlimiao","email":"lmjavajas@163.com"},{"name":"artoriaschan","email":"544396118@qq.com"},{"name":"alexjia","email":"875877496@qq.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hammer-security_0.1.1_1555484732180_0.9895445189117631"},"_hasShrinkwrap":false}},"time":{"created":"2019-04-17T07:05:31.985Z","0.1.1":"2019-04-17T07:05:32.338Z","modified":"2022-04-04T10:48:14.763Z"},"maintainers":[{"email":"skybjf@126.com","name":"skybjf"},{"email":"rockolin@163.com","name":"rockolin"},{"email":"724255238@qq.com","name":"reking"},{"email":"lmjavajas@163.com","name":"imlimiao"},{"email":"xiaoyuya13@163.com","name":"xiaoyuya"},{"email":"abc517722366@qq.com","name":"felix_xue"},{"email":"735841030@qq.com","name":"zhangboyu"},{"email":"772034368@qq.com","name":"marinamumu"},{"email":"2457929978@qq.com","name":"bestvist"},{"email":"937955281@qq.com","name":"liuhanbing"}],"description":"security plugin in hammer frameworks","keywords":["hammer","security","node"],"author":{"name":"Artorias Chan"},"license":"MIT","readme":"## hammer-security\n\n[![Build Status](https://travis-ci.com/artoriaschan/hammer-security.svg?token=yqEJiDNSRDZozHfUJWAx&branch=master)](https://travis-ci.com/artoriaschan/hammer-security)\n[![codecov](https://codecov.io/gh/artoriaschan/hammer-security/branch/master/graph/badge.svg?token=vPvP6ihSgN)](https://codecov.io/gh/artoriaschan/hammer-security)\n\n#### hammer的安全模块\n___\n## 目录结构\n```md\n├── config\n│   └── index.js\n├── lib\n│   ├── header\n│   │   ├── hsts.js\n│   │   ├── methodnoallow.js\n│   │   ├── noopen.js\n│   │   ├── nosniff.js\n│   │   ├── referrerPolicy.js\n│   │   ├── xframe.js\n│   │   └── xssProtection.js\n│   ├── helper\n│   │   ├── csrf.js\n│   │   ├── escape.js\n│   │   ├── index.js\n│   │   ├── scli.js\n│   │   ├── shtml.js\n│   │   ├── sjs.js\n│   │   ├── sjson.js\n│   │   ├── spath.js\n│   │   └── surl.js\n│   └── utils.js\n└── test\n    ├── lib\n    │   ├── header\n    │   │   ├── hsts.test.js\n    │   │   ├── methodnoallow.test.js\n    │   │   ├── noopen.test.js\n    │   │   ├── nosniff.test.js\n    │   │   ├── referrerPolicy.test.js\n    │   │   ├── xframe.test.js\n    │   │   └── xssProtection.test.js\n    │   ├── helper\n    │   │   ├── scli.test.js\n    │   │   ├── sjson.test.js\n    │   │   ├── shtml.test.js\n    │   │   ├── sjs.test.js\n    │   │   ├── spath.test.js\n    │   │   └── surl.test.js\n    │   └── utils.test.js\n    └── utils\n        └── app.js\n```\n\n## Helper\n\n### csrf\n\n接入[csrf](https://github.com/leizongmin/js-xss/) 模块, 具体使用方法请看[github](https://github.com/pillarjs/csrf)\n\n### .surl()\n\nurl 过滤。\n\n用于在html标签中中要解析 url 的地方（比如 `<a href=\"\"/><img src=\"\"/>`），其他地方不允许使用。\n\n对模板中要输出的变量，加 `helper.surl($value)`。\n\n**特别需要注意的是在需要解析url的地方，surl 外面一定要加上双引号，否则就会导致XSS漏洞。**\n\n不使用 surl\n\n```html\n<a href=\"$value\" />\n```\n\noutput:\n\n```html\n<a href=\"http://www.domain.com<script>\" />\n```\n\n使用 surl\n\n```html\n<a href=\"helper.surl($value)\" />\n```\n\noutput:\n\n```html\n<a href=\"http://www.domain.com&lt;script&gt;\" />\n```\n\n### .escape()\n\n对字符串进行 xss 过滤，安全性最高的过滤方式。\n\n```js\nconst str = '><script>alert(\"abc\") </script><';\nconsole.log(helper.escape(str));\n// => &gt;&lt;script&gt;alert(&quot;abc&quot;) &lt;/script&gt;&lt;\n```\n\n### .sjs()\n\n用于在 js（包括 onload 等 event）中输出变量，会对变量中字符进行 JAVASCRIPT ENCODE，\n将所有非白名单字符转义为 `\\x` spath形式，防止xss攻击，也确保在 js 中输出的正确性。\n\n```js\nconst foo = '\"hello\"';\n\n// 未使用 sjs\nconsole.log(`var foo = \"${foo}\";`);\n// => var foo = \"\"hello\"\";\n\n// 使用 sjs\nconsole.log(`var foo = \"${helper.sjs(foo)}\";`);\n// => var foo = \"\\\\x22hello\\\\x22\";\n```\n\n### .shtml()\n\n将富文本（包含 html 代码的文本）当成变量直接在模版里面输出时，需要用到 shtml 来处理。\n使用 shtml 可以输出 html 的 tag，同时执行 xss 的过滤动作，过滤掉非法的脚本。\n\n**由于是一个非常复杂的安全处理过程，对服务器处理性能一定影响，如果不是输出 HTML，请勿使用。**\n\n简单示例：\n\n```js\n// js\nconst value = `<a href=\"http://www.domain.com\">google</a><script>evilcode…</script>`;\n\n// 模板\n<html>\n<body>\n  ${helper.shtml(value)}\n</body>\n</html>\n\n// 输出\n'<a href=\"http://www.domain.com\">google</a>&lt;script&gt;evilcode…&lt;/script&gt;'\n```\n\nshtml 在 [xss](https://github.com/leizongmin/js-xss/) 模块基础上实现的。\n\n- [默认规则](https://github.com/leizongmin/js-xss/blob/master/lib/default.js)\n- 自定义过滤项 http://jsxss.com/zh/options.html\n\n例如只支持 a 标签，且除了 title 其他属性都过滤掉：\n\n```javascript\nconst html = '<a href=\"http://www.domain.com\" title=\"test\" onClick=\"hello()\"></a>';\nconst options = {\n  whiteList: {\n    a: [ 'href', 'title' ],\n  },\n};\n// html\n${helper.shtml(html, options)}\n\n// 输出\n'<a href=\"http://www.domain.com\" title=\"test\"></a>'\n```\n\n注意，shtml 使用了严格的白名单机制，除了过滤掉 xss 风险的字符串外，\n在 [默认规则](https://github.com/leizongmin/js-xss/blob/master/lib/default.js) 外的 tag 和 attr 都会被过滤掉。\n\n例如 html 标签就不在白名单中，\n\n```js\nconst html = '<html></html>';\nconst options = {\n  whiteList: {\n    a: [ 'href', 'title' ],\n  },\n};\n// html\n${helper.shtml(html, options)}\n\n// 输出\n'&lt;html&gt;&lt;/html&gt;'\n```\n\n常见的 `data-xx` 属性由于不在白名单中，所以都会被过滤。\n\n所以，一定要注意 shtml 的适用场景，一般是针对来自用户的富文本输入，切忌滥用，功能既受到限制，又会影响服务端性能。\n此类场景一般是论坛、评论系统等，即便是论坛等如果不支持 html 内容输入，也不要使用此 helper，直接使用 escape 即可。\n\n### .spath()\n\n如果把输入字符串用作 path 路径，需要使用 spath 进行安全检验。若路径不合法，返回 null。\n\n不合法的路径包括：\n\n- 使用 `..` 的相对路径\n- 使用 `/` 开头的绝对路径\n- 以及以上试图通过 url encode 试图绕过校验的结果字符串\n\n```js\nconst foo1 = '/usr/local/bin';\nconst foo2 = '../local/bin';\n\nconsole.log(helper.spath(foo1));\nconsole.log(helper.spath(foo2));\n\n// => null\n// => null\n```\n\n### .sjson()\n\njson转义\n\n在js中输出json，若未做转义，易被利用为xss漏洞。提供此宏做json encode，会遍历json中的key，将value的值中，所有非白名单字符转义为\\x形式，防止xss攻击。同时保持json结构不变。\n若你有模板中输出一个json字符串给js应用的场景，请使用 `${helper.sjson(变量名)}`进行转义。\n\n**处理过程较复杂，性能损耗较大，尽量避免使用**\n\n实例:\n\n```js\n  <script>\n    window.locals = ${helper.sjson(locals)};\n  </script>\n```\n\n### .scli()\n\n远程命令执行漏洞，用户通过浏览器提交执行命令，由于服务器端没有针对执行函数做过滤，导致可以执行命令，通常可导致入侵服务器。\n\n如果用户可控变量为命令中的参数。则直接使用安全包函数过滤。\n\n修复前：\n\n```js\n  cp.exec(\"bash /home/admin/xxx/run.sh \" + port);\n```\n\n修复后：\n\n```js\n  cp.exec(\"bash /home/admin/xxx/run.sh \" + helper.scli(port));\n```\n\n如果因为业务需要，需要在参数中天加白名单之外的字符。可以将用户输入按照该字符分割，并使用过滤函数过滤每一段数据。\n\n如果用户可控变量为命令中的命令，则和开发协商修改功能或功能下线。\n\n## Web 安全头\n\n### hsts(Strict-Transport-Security)\n\n默认开启，如果是 http 站点，需要关闭\n\n- maxAge 默认一年 `365 * 24 * 3600`\n- includeSubdomains 默认 false\n\n使用方法:\n```js\napp.use(hsts(options))\n```\n\n### X-Download-Options:noopen\n\n默认开启，禁用IE下下载框Open按钮，防止 ie 下下载文件默认被打开 xss\n\n使用方法:\n```js\napp.use(noopen())\n```\n\n### X-Content-Type-Options:nosniff\n\n禁用 IE8 自动嗅探 mime 功能。例如：`text/plain` 却当成 `text/html` 渲染，特别当本站点服务内容未必可信的时候。\n\n使用方法:\n```js\napp.use(nosniff())\n```\n\n### Referrer-Policy\n\n当用户在浏览器上点击一个链接时，会产生一个 HTTP 请求，用于获取新的页面内容，而在该请求的报头中，会包含一个 Referrer，用以指定该请求是从哪个页面跳转页来的，常被用于分析用户来源等信息。但是也有成为用户的一个不安全因素，比如有些网站直接将 sessionid 或是 token 放在地址栏里传递的，会原样不动地当作 Referrer 报头的内容传递给第三方网站。\n\n所以就有了 Referrer Policy，用于过滤 Referrer 报头内容，目前是一个候选标准，不过已经有部分浏览器支持该标准。\n\n**指令值** 目前包含了以下几种指令值：\n```js\nenum ReferrerPolicy {\n  \"\",\n  \"no-referrer\",\n  \"no-referrer-when-downgrade\",\n  \"same-origin\",\n  \"origin\",\n  \"strict-origin\",\n  \"origin-when-cross-origin\",\n  \"strict-origin-when-cross-origin\",\n  \"unsafe-url\"\n};\n```\n\n使用方法:\n```js\napp.use(nosniff(options))\n```\n### X-Frame-Options\n\n默认 SAMEORIGIN，只允许同域把本页面当作 iframe 嵌入。\n\n- value 默认值 `SAMEORIGIN`\n\n使用方法:\n```js\napp.use(xframe(options))\n```\n### X-XSS-Protection\n\n- close 默认值false，即设置为 `1; mode=block`\n\n使用方法:\n```js\napp.use(xssProtection(options))\n```\n## 其他\n\n* 禁止 trace track 两种类型请求\n\n  使用方法:\n  ```js\n  app.use(notAllow())\n  ```\n\n## License\n\n[**MIT**](./LICENSE)\n","readmeFilename":"README.md"}