XSS
zKing 2018-11-26 Web 安全
摘要
全名为:Cross Site Scripting,即跨站脚本攻击
# 攻击原理
程序+数据=结果
当“数据”由数据变成程序的时候,便受到了攻击
# 危害
- 偷取网站任意数据
- 被获取 cookie 来偷取用户资料,用户密码和登录态
- 劫持前端逻辑,或者更改发送请求,来欺骗用户
# 攻击分类
- 反射型-- url 参数直接注入
- 存储型 -- 存储到 DB 后读取时注入
- DOM 型 -- 通过浏览器端的 DOM 解析,完全作用于客户端,这也就是避免使用
eval
的原因
# 攻击注入点
# HTML 节点内容 和 HTML 属性
加入 script 语句进行攻击
# JavaScript 代码
可以利用代码以分号为结束的代码格式进行插入攻击
# 富文本
富文本本质就是一大段 HTML,而 HTML 就有 XSS 攻击风险
# 防御方案
# 浏览器自带防御
- 现在的浏览器有 X-XSS-Protection 属性,默认是开启这个属性的
- 只能防御参数出现在 HTML 内容或属性,只适用于反射型 XSS 攻击
- 防御有限,不能依赖
router.all("/*", async function(ctx, next) {
ctx.set("x-XSS-Protection", 1); //默认浏览器开启1,设为0时即可关闭
await next();
});
# 防御 HTML 中的 XSS
- 将
特殊符号
转义成HTML字符实体
- 常见的是转义内容是“大于号”,“小于号”,“单引号”,“双引号”,“空格”,“&”
let escapeHtml = str => {
if (!str) return "";
str = str.replace(/&/g, "&");
str = str.replace(/</g, "<");
str = str.replace(/>/g, ">");
str = str.replace(/"/g, "&quto;");
str = str.replace(/'/g, "'");
return str;
};
# 防御 Js 中的 XSS
使用 JSON.stringify 进行 encode
let escapeForJs = str => {
if (!str) return "";
//str = str.replace(/\\/g,'\\\\');
//str = str.replace(/"/g,'\\"');
//return str;
return JSON.stringify(str);
};
# 防御 富文本 的 XSS
- XSS 的变种很多,所以只能按
白名单
保留部分标签和属性 - npm 上有
cheerio
模块来解析 HTML,但是自己来进行操作太过麻烦,好在有已经做好的第三方白名单模块 - 常用的根据白名单过滤 HTML (防止 XSS 攻击),在 npm 上的模块名称就是
xss
,具体可以从 GitHub 上进行查找
cnpm install xss -D
const xss = require("xss");
let xssFilter = html => {
if (!html) return "";
let res = xss(html, {
whiteList: {
img: ["src"],
a: ["href"],
font: ["size", "color"]
},
onIgnoreTag: () => {
return "";
}
});
return res;
};
# CSP
- Content Security Policy 内容安全策略
- 这其实是 HTTP 协议的内容,用于指定哪些内容可执行,更多请点击这里
router.all("/*", async function(ctx, next) {
ctx.set("x-XSS-Protection", 0); //默认浏览器开启1
ctx.set(`Content-Security-Policy`, `default-src 'self'`); //CSP self同域下可以信任
await next();
});
# 总结防御方案
- 开启浏览器自带的防御机制
- 对浏览器发送的数据进行
转义
操作,必要时使用白名单
- 有需要时开启 CSP