Очистка ввода данных пользователем прежде, чем добавить его к DOM в JavaScript

Я пишу JS для приложения чата, я продолжаю работать в свое свободное время, и у меня должны быть идентификаторы HTML, которые изменяются согласно отправленным данным пользователя. Это обычно - что-то концептуально достаточно шаткое, что я даже не делал бы попытку его, но я не вижу, что я имею большую часть выбора на этот раз. Что я должен сделать, затем должен выйти из идентификатора HTML, чтобы удостовериться, что он не будет допускать XSS или повреждающийся HTML.

Вот код:

var user_id = escape(id)
var txt = '<div class="chut">'+
            '<div class="log" id="chut_'+user_id+'"></div>'+
            '<textarea id="chut_'+user_id+'_msg"></textarea>'+
            '<label for="chut_'+user_id+'_to">To:</label>'+
            '<input type="text" id="chut_'+user_id+'_to" value='+user_id+' readonly="readonly" />'+
            '<input type="submit" id="chut_'+user_id+'_send" value="Message"/>'+
          '</div>';

Каков был бы лучший способ выйти id избегать какого-либо вида упомянутой выше проблемы? Как Вы видите, прямо сейчас я использую встроенное escape() функция, но я не уверен в том, как хороший это, как предполагается, сравнивается с другими альтернативами. Я главным образом привык к очистке входа, прежде чем это войдет в текстовый узел, не сам идентификатор.

35
задан sth 8 May 2010 в 13:24
поделиться

3 ответа

Никогда не используйте escape () . Это не имеет отношения к кодировке HTML. Это больше похоже на URL-кодирование, но это даже не совсем так. Это странная нестандартная кодировка, доступная только в JavaScript.

Если вам нужен кодировщик HTML, вам придется написать его самостоятельно, поскольку в JavaScript его нет. Например:

function encodeHTML(s) {
    return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;');
}

Однако, хотя этого достаточно, чтобы поместить ваш user_id в такие места, как входное значение , этого недостаточно для id , потому что идентификаторы могут использовать только ограниченный выбор персонажей. (И % среди них нет, поэтому escape () или даже encodeURIComponent () не годятся.)

Вы можете изобрести свою собственную кодировку. схема для вставки любых символов в идентификатор, например:

function encodeID(s) {
    if (s==='') return '_';
    return s.replace(/[^a-zA-Z0-9.-]/g, function(match) {
        return '_'+match[0].charCodeAt(0).toString(16)+'_';
    });
}

Но у вас все еще есть проблема, если один и тот же user_id встречается дважды. И, честно говоря, вся эта идея с разбрасыванием HTML-строк - обычно плохая идея. Вместо этого используйте методы DOM и сохраните ссылки JavaScript для каждого элемента, поэтому вам не нужно постоянно вызывать getElementById или беспокоиться о том, как произвольные строки вставляются в идентификаторы.

например:

function addChut(user_id) {
    var log= document.createElement('div');
    log.className= 'log';
    var textarea= document.createElement('textarea');
    var input= document.createElement('input');
    input.value= user_id;
    input.readonly= True;
    var button= document.createElement('input');
    button.type= 'button';
    button.value= 'Message';

    var chut= document.createElement('div');
    chut.className= 'chut';
    chut.appendChild(log);
    chut.appendChild(textarea);
    chut.appendChild(input);
    chut.appendChild(button);
    document.getElementById('chuts').appendChild(chut);

    button.onclick= function() {
        alert('Send '+textarea.value+' to '+user_id);
    };

    return chut;
}

Вы также можете использовать вспомогательную функцию или JS-фреймворк, чтобы сократить там длину вызовов create-set-appends.

ETA:

В настоящее время я использую jQuery в качестве фреймворка.

Хорошо, тогда рассмотрим ярлыки создания jQuery 1.4, например :

var log= $('<div>', {className: 'log'});
var input= $('<input>', {readOnly: true, val: user_id});
...

Проблема, с которой я столкнулся прямо сейчас, заключается в том, что я использую JSONP для добавлять элементы и события на страницу, поэтому я не могу знать, существуют ли элементы уже или нет, до отображения сообщения.

Вы можете сохранить поиск user_id узлов элементов (или объектов оболочки) в JavaScript, чтобы сохранить эту информацию в самой DOM, где символы, которые могут входить в id ограничены.

var chut_lookup= {};
...

function getChut(user_id) {
    var key= '_map_'+user_id;
    if (key in chut_lookup)
        return chut_lookup[key];
    return chut_lookup[key]= addChut(user_id);
}

(Префикс _map_ вызван тем, что объекты JavaScript не вполне работают как отображение произвольных строк. Пустая строка и, в IE, некоторые Object ] имена участников, запутайте.)

42
ответ дан 27 November 2019 в 07:03
поделиться

Вы можете использовать простое регулярное выражение, чтобы утверждать, что идентификатор содержит только разрешенные символы, например:

if(id.match(/^[0-9a-zA-Z]{1,16}$/)){
    //The id is fine
}
else{
    //The id is illegal
}

В моем примере разрешены только буквенно-цифровые символы и строки длиной от 1 до 16, вы должны изменить его, чтобы он соответствовал типу идентификаторы, которые вы используете.

Между прочим, в строке 6 в свойстве value отсутствует пара кавычек, что легко сделать, когда вы цитируете на двух уровнях.

Я не могу увидеть ваш реальный поток данных, в зависимости от контекста эта проверка может вообще не понадобиться или ее может быть недостаточно. Чтобы провести надлежащую проверку безопасности, нам потребуется дополнительная информация.

В общем, что касается встроенных функций escape или очистки, не доверяйте им слепо. Вам нужно точно знать, что они делают, и вы должны убедиться, что это именно то, что вам нужно. Если это не то, что вам нужно, код ваш собственный, в большинстве случаев простое регулярное выражение с белым списком, подобное тому, которое я вам дал, отлично работает.

9
ответ дан 27 November 2019 в 07:03
поделиться

Необходимо принимать дополнительные меры предосторожности при использовании пользовательских данных в атрибутах HTML. Потому что атрибуты имеют гораздо больше векторов атак, чем вывод внутри HTML-тегов.

Единственный способ избежать XSS-атак - кодировать все, кроме буквенно-цифровых символов. Все символы со значениями ASCII менее 256 экранируйте форматом &#xHH;. Что, к сожалению, может вызвать проблемы в вашем сценарии, если вы используете классы CSS и javascript для получения этих элементов.

У OWASP есть хорошее описание того, как смягчить последствия XSS атрибутов HTML:

http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.233_-_JavaScript_Escape_Before_Inserting_Untrusted_Data_into_HTML_JavaScript_Data_Values

1
ответ дан 27 November 2019 в 07:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: