2
4

2 に答える 2

1

ユーザー入力にJavaScriptを使用している場合、何をしても防弾にはなりません。

サーバー側のバックエンドを作成していると仮定すると、実証済みの真の bbcode を使用する必要があります。そのためのライブラリが必要です。

于 2012-08-22T23:12:43.900 に答える
1

単純なタグのホワイトリストがあり、エンコーディング レベル以下での攻撃を心配する必要がない場合 (ブラウザ側の JavaScript 内からの場合のように)、次のことができます。

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

  // 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');

次のように使用できます

sanitize({ p: true, b: true, i: true, br: true },
         "Hello, <b>World</b>!<script>alert(1337)<\/script>");

タグの属性を許可する機能など、より多くの構成機能が必要な場合は、Caja HTML サニタイザーを参照してください。

他の人が指摘しているように、サーバーはクライアントからの結果を信頼すべきではないため、サーバーが生成したマークアップに結果を埋め込む前に、サーバーで再サニタイズする必要があります。

于 2012-08-22T23:30:52.837 に答える