将变量从 ejs 传递到 javascript(渲染时服务器到客户端),同时避免 XSS 问题 [英] Passing vars from ejs to javascript (server to client on render) while avoiding XSS issues

查看:29
本文介绍了将变量从 ejs 传递到 javascript(渲染时服务器到客户端),同时避免 XSS 问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 ejs 将变量传递给 JavaScript 的公认方式是这样的:

It seems like the accepted way to pass variables to JavaScript using ejs is like so:

<script>
  var foo = <%- JSON.stringify(foo) %>;
</script>

但是我在使用这种方法时遇到了 XSS 问题,想知道是否有更好/更安全的方法.

But I've ran into XSS issues using this method, and wanted to know if there was a better/safer way.

这个例子展示了这个漏洞.

这是有效的,因为 JSON.stringify("</script><script>alert('test')</script><script>") 返回 "</script><script>alert('test')</script><script>"<%- %> 操作符 逃避结果.

This works since JSON.stringify("</script><script>alert('test')</script><script>") returns "</script><script>alert('test')</script><script>" and the <%- %> operators do not escape the result.

它也适用于对象:此处的示例

<script>
var test = {
    "text": "</script><script>alert('test')</script><script>"
}
</script>

有没有更安全的方法来处理这个问题?

Is there a safer way to handle this?

推荐答案

您可以在 JSON.stringify 之后使用 Base64 编码.这将避免与引号或 HTML 标签相关的所有风险,因为 Base64 仅包含安全"字符以放入带引号的字符串中.

You can use Base64 encoding after JSON.stringify. This would avoid all risks related to quotes or HTML tags since Base64 only contains "safe" characters to put in a quoted string.

我在我的网站中使用的解决方案:

The solution I use in my website:

EJS 文件:

<script>
  var foo = <%- passValue(foo) %>
</script>

这将渲染成类似的东西(例如这里的 foo = null):

which will render into something like (for example here foo = null):

<script>
  var page = JSON.parse(Base64.decode("bnVsbA=="))
</script>

服务端NodeJS:

function passValue(value) {
  return 'JSON.parse(Base64.decode("' + new Buffer(JSON.stringify(value)).toString('base64') + '"))'
}

客户端 JS(这是一个适用于 Unicode 的 Base64 解码实现,如果您愿意,可以使用另一个,但如果它支持 Unicode,请小心):

Client-side JS (this is an implementation of Base64 decoding that works with Unicode, you can use another if you prefer but be careful if it supports Unicode):

var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f<e.length){n=e.charCodeAt(f++);r=e.charCodeAt(f++);i=e.charCodeAt(f++);s=n>>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9+/=]/g,"");while(f<e.length){s=this._keyStr.indexOf(e.charAt(f++));o=this._keyStr.indexOf(e.charAt(f++));u=this._keyStr.indexOf(e.charAt(f++));a=this._keyStr.indexOf(e.charAt(f++));n=s<<2|o>>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/
/g,"
");var t="";for(var n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r)}else if(r>127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n<e.length){r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r);n++}else if(r>191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}}

这篇关于将变量从 ejs 传递到 javascript(渲染时服务器到客户端),同时避免 XSS 问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆