使用javascript:在不使用块html标记(<;b>;、<;p>;)的情况下阻止脚本的最佳方法是什么?

使用javascript:在不使用块html标记(<;b>;、<;p>;)的情况下阻止脚本的最佳方法是什么?,javascript,escaping,xss,Javascript,Escaping,Xss,我希望安全地显示来自用户的文本(通过阻止脚本标记),但我需要接受html标记(b、p、li、ul等) 它需要防弹,以防跨站点脚本攻击 谢谢大家! 如果您使用javascript进行用户输入,无论您做什么,它都不会防弹 假设您正在编写服务器端后端,您应该使用经过验证的bbcode,它必须有一个库。如果您有一个简单的标记白名单,并且不需要担心编码级别或以下的攻击(如浏览器端JavaScript中的情况),您可以执行以下操作: function sanitize(tagWhitelist, html)

我希望安全地显示来自用户的文本(通过阻止脚本标记),但我需要接受html标记(b、p、li、ul等)

它需要防弹,以防跨站点脚本攻击


谢谢大家!

如果您使用javascript进行用户输入,无论您做什么,它都不会防弹


假设您正在编写服务器端后端,您应该使用经过验证的bbcode,它必须有一个库。

如果您有一个简单的标记白名单,并且不需要担心编码级别或以下的攻击(如浏览器端JavaScript中的情况),您可以执行以下操作:

function sanitize(tagWhitelist, html) {
  // Get rid of all uses of '['.
  html = String(html).replace(/\[/g, '&#91;');

  // Consider all uses of '<' and replace whitelisted tags with markers like
  // [1] which are indices into a list of approved tag names.
  // Replace all other uses of < and > with entities.
  var tags = [];
  html = html.replace(
    /<!--[\s\S]*?-->|<(\/?)([a-z]\w*)(?:[^"'>]|"[^"]*"|'[^']*')*>/g,
    function (_, close, tagName) {
      if (tagName) {
        tagName = tagName.toLowerCase();
        if (tagWhitelist.hasOwnProperty(tagName) && tagWhitelist[tagName]) {
          var index = tags.length;
          tags.push('<' + (close || '') + tagName + '>');
          return '[' + index + ']';
        }
      }
      return '';
    });

  // Escape HTML special characters.  Leave entities alone.
  html = html.replace(/[<>"'@\`\u0000]/g,
    function (c) {
      switch (c) {
        case '<': return '&lt;';
        case '>': return '&gt;';
        case '"': return '&quot;';
        case '\'': return '&#39;';
        case '@': return '&#64;';
      }
      return '&#' + c.charCodeAt(0) + ';';
    });
  if (html.indexOf('<') >= 0) { throw new Error(); }  // Sanity check.

  // Throw out any close tags that don't correspond to start tags.
  // If <table> is used for formatting, embedded HTML shouldn't be able
  // to use a mismatched </table> to break page layout.
  var open = [];
  for (var i = 0, n = tags.length; i < n; ++i) {
    var tag = tags[i];
    if (tag.charAt(1) === '/') {
      var idx = open.lastIndexOf(tag);
      if (idx < 0) { tags[i] = ""; }  // Drop close tag.
      else {
        tags[i] = open.slice(idx).reverse().join('');
        open.length = idx;
      }
    } else if (!HTML5_VOID_ELEMENTS.test(tag)) {
      open.push('</' + tag.substring(1));
    }
  }
  // Now html contains no tags or less-than characters that could become
  // part of a tag via a replacement operation and tags only contains
  // approved tags.
  // Reinsert the white-listed tags.
  html = html.replace(
       /\[(\d+)\]/g, function (_, index) { return tags[index]; });

  // Close any still open tags.
  // This prevents unclosed formatting elements like <ol> and <table> from
  // breaking the layout of containing HTML.
  return html + open.reverse().join('');
}

var HTML5_VOID_ELEMENTS = new RegExp(
     '^<(?:area|base|br|col|command|embed|hr|img|input'
     + '|keygen|link|meta|param|source|track|wbr)\\b');
函数清理(标记白名单,html){
//去掉“[”的所有用法。
html=String(html)。替换(/\[/g',[;');

考虑到其他人已经指出的所有用途,消毒不能做客户端,它应该做服务器端。你会感到失望,因为你不能得到不同的答案比“这是不能用JS”:(那么你是说backbone.JS escape方法不安全?我只想防止从不安全的字符串执行javascript。我不在乎用户是否可以修改DOM并删除验证,因为字符串只显示,而不是修改。@ajax333221,在使用前对客户端进行消毒是保护输入的一种非常安全的方法它们是客户端的,例如,作为富文本编辑器预览窗格的一部分分配给
innerHTML
。您不想做的事情是让服务器信任这些输入,因为验证客户端是否确实执行了清理比只重做清理更难。您的第一句话是什么意思?为什么这永远都不安全。你是说只在客户端执行发送到服务器的数据的输入验证/清理吗?如果是这样,我同意任何客户端代码都可以由客户端更改-当它到达服务器时,客户端必须重新验证。是的。但是,如果数据立即预览,javascript输入验证仍然有意义将客户端发送到服务器之前,必须先将其保存在服务器上。但是,介意我问一下为什么不允许使用
“@”
“\”
?@adlwalrus,
“@”
似乎出现在条件代码方案中。IE在其JavaScript引擎中使用它进行条件执行,但尽管我非常确定IE不会将其用于HTML中的条件注释,但我很难相信没有文档记录不良的浏览器功能使用
“@/code>来表示代码f下面是。
'““
是HTML属性中的一个特殊字符。我不想提出一个属性不安全的HTML转义方法,因为一旦你宣传一个函数将HTML转换为纯文本,人们就会认为它可以广泛使用。是的,但是
=
也是如此。正如你所说,这些都是,“HTML控制字符。”为什么不转义这些字符呢?这是我尝试的一种markdowney格式语言。你对我的代码有什么反馈吗?我希望有实际的评论,而不仅仅是编辑jsbin,因为jsbin很快就会变得非常混乱。谢谢。顺便说一句,
实际上在HTML中起着与
相同的作用
。另外,我想我忘了链接。这里是:@adlwalrus,我们是在讨论同一个代码吗?我根本没说“HTML控制字符”,单引号被转义。转义等号可能是个好主意,但分号似乎没有什么价值,必须在某处画一条线。
sanitize({ p: true, b: true, i: true, br: true },
         "Hello, <b>World</b>!<script>alert(1337)<\/script>");