HTML: Эквивалентные символы избегают атаки xss [дублировать]

Ссылка NullReferenceException или Object, не установленная на экземпляр объекта, возникает, когда объект класса, который вы пытаетесь использовать, не создается. Например:

Предположим, что у вас есть класс с именем Student.

public class Student
{
    private string FirstName;
    private string LastName;
    public string GetFullName()
    {
        return FirstName + LastName;
    }
}

Теперь рассмотрим другой класс, в котором вы пытаетесь получить полное имя учащегося.

public class StudentInfo
{      
    public string GetStudentName()
    {
        Student s;
        string fullname = s.GetFullName();
        return fullname;
    }        
}

Как видно из вышеприведенного кода, оператор Student s - объявляет только переменную типа Student, обратите внимание, что класс Student не создается в этой точке. Следовательно, когда выполняется выполнение инструкции s.GetFullName (), она выкинет исключение NullReferenceException.

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

6 ответов

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

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

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

Однако, пока этого достаточно, чтобы разместить user_id в таких местах, как input value, этого недостаточно для 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, чтобы сократить длительность вызовов, созданных при создании-добавлении.

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 членов путают ее.)

34
ответ дан bobince 25 August 2018 в 01:06
поделиться
  • 1
    Я использую jQuery на данный момент в качестве рамки, поэтому любая идея, связанная с этим, может быть полезна. Проблема, с которой я столкнулся сейчас, заключается в том, что я использую JSONP для добавления элементов и событий на страницу, поэтому я не могу знать, существуют ли эти элементы или нет, прежде чем показывать сообщение. Это заставило меня думать, что я вынужден использовать дрянной метод, я должен найти, какие элементы выбрать или добавить их, если их еще нет. Из-за этого я не думаю, что ваше последнее предложение может работать, но я могу ошибаться. Ограниченный набор символов заставляет меня думать, что MD5 идентификатора может быть всем, что я могу сделать. – I GIVE TERRIBLE ADVICE 8 May 2010 в 15:26
  • 2
    Хотя я мог бы просто добавить предположение о принятых символах имени пользователя, использовать регулярные выражения и делать с ними. – I GIVE TERRIBLE ADVICE 8 May 2010 в 15:34

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

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

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

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

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

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

8
ответ дан aaaaaaaaaaaa 25 August 2018 в 01:06
поделиться

Поскольку текст, который вы экранируете, будет отображаться в атрибуте HTML, вы должны обязательно избегать не только HTML-объектов, но и атрибутов HTML:

var ESC_MAP = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#39;'
};

function escapeHTML(s, forAttribute) {
    return s.replace(forAttribute ? /[&<>'"]/g : /[&<>]/g, function(c) {
        return ESC_MAP[c];
    });
}

Затем ваш код экранирования станет var user_id = escapeHTML(id, true).

Для получения дополнительной информации см. Foolproof HTML escaping в Javascript .

1
ответ дан Brandon Mintern 25 August 2018 в 01:06
поделиться

Другим подходом, который мне нравится, является использование собственных возможностей DOM: http://shebang.brandonmintern.com/foolproof-html-escaping-in-javascript

15
ответ дан codecraig 25 August 2018 в 01:06
поделиться
  • 1
    @BrandonMintern gist не работает для меня. – cmcculloh 5 July 2016 в 18:10
  • 2
    Я написал это сообщение в блоге. К сожалению, метод TL; DR, указанный в верхней части, не подходит для использования в атрибутах HTML. Есть и другие подходы к концу сообщения, которые правильно выходят за атрибуты HTML, а именно: shebang.brandonmintern.com/… – Brandon Mintern 6 July 2016 в 23:06

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

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

OWASP имеет хорошее описание того, как уменьшить атрибут HTML XSS:

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
ответ дан kozmic 25 August 2018 в 01:06
поделиться

Вы также можете использовать это:

function sanitarize(string) {
  const map = {
      '&': '&amp;',
      '<': '&lt;',
      '>': '&gt;',
      '"': '&quot;',
      "'": '&#x27;',
      "/": '&#x2F;',
  };
  const reg = /[&<>"'/]/ig;
  return string.replace(reg, (match)=>(map[match]));
}

Документация OWASP предполагает сопоставление: https://www.owasp.org/index.php/XSS_ (Cross_Site_Scripting) _Prevention_Cheat_Sheet

5
ответ дан SilentImp 25 August 2018 в 01:06
поделиться
Другие вопросы по тегам:

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