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 '<';
case '>': return '>';
case '"': return '"';
case '\'': return ''';
case '@': return '@';
}
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 に答える