Когда использовать document.implementation.createHTMLDocument?

#javascript

#javascript

Вопрос:

Каковы некоторые варианты использования и является ли он устаревшим? Как я узнал в http://groups.google.com/group/envjs/browse_thread/thread/6c22d0f959666009/c389fc11537f2a97 что он «нестандартный и не поддерживается ни одним современным браузером».

О document.implementation в http://javascript.gakaa.com/document-implementation.aspx:

Возвращает ссылку на объект W3C DOMImplementation, который представляет, в ограниченной степени, среду, которая составляет контейнер документа — браузер, для наших целей. Методы объекта позволяют увидеть, какие модули DOM поддерживает браузер. отчеты. Этот объект также является шлюзом для создания виртуальных объектов W3C Document и DocumentType вне текущего дерева документов. Таким образом, в Netscape 6 вы можете использовать свойство document.implementation в качестве начала для создания документа, не подлежащего передаче, для внешних XML-документов. Смотрите объект DOMImplementation для получения подробной информации о методах и их поддержке браузером.

Учитывая, что он предоставляет методы (такие как createHTMLDocument ) для создания неотрендеренного документа за пределами текущего дерева документов, было бы безопасно передавать ему ненадежный сторонний ввод HTML, который может содержать некоторые XSS? Я спрашиваю, потому что я хотел бы использовать createHTMLDocument для целей обхода стороннего ввода HTML. Может ли это быть одним из вариантов использования?

Комментарии:

1. Согласно QuirksMode , createHTMLDocument не был доступен в старых версиях IE или Firefox. IE9, по-видимому, поддерживает его, и мое собственное тестирование показывает, что FF7 поддерживает его.

2. И createHTMLDocument находится в спецификации DOM2

Ответ №1:

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

 function cleanHTML( html ) {
    var root = document.implementation.createHTMLDocument().body;

    root.innerHTML = html;

    //Manipulate the DOM here
    $(root).find("script, style, img").remove(); //jQuery is not relevant, I just didn't want to write exhausting boilerplate code just to make a point

    return root.innerHTML;
}


cleanHTML( '<div>hello</div><img src="google"><script>alert("hello");</script><style type="text/css">body {display: none !important;}</style>' );
//returns "<div>hello</div>" with the page unaffected
  

Комментарии:

1. Исчерпывающий шаблонный код = [].forEach.call(document.querySelectorAll("script, style, img"), function(el) { el.remove(); });

Ответ №2:

ДА. Вы можете использовать это для загрузки ненадежного стороннего контента и удаления из него опасных тегов и атрибутов, прежде чем включать его в свой собственный документ. Существует несколько отличных исследований, включающих этот трюк, описанный в http://blog.kotowicz.net/2011/10/sad-state-of-dom-security-or-how-we-all.html .

Однако описанного выше метода, описанного Esailija, недостаточно. Вам также необходимо удалить большинство атрибутов. Злоумышленник может установить элемент onerror или onmouseover для вредоносного JS. Атрибут style может использоваться для включения CSS, который запускает вредоносный JS. Также можно злоупотреблять Iframe и другими тегами для встраивания. Посмотреть источник на https://html5sec.org/xssme/xssme2 чтобы увидеть версию этой техники.

Комментарии:

1. Вторая ссылка не работает. Было бы интересно посмотреть

2. Я думаю, что это копия того же кода: html5sec.org/xssme/xssme2 . Обновление ответа, чтобы указать там. Исходный URL-адрес был xssme.html5sec.org/xssme2

Ответ №3:

Просто более чистый ответ, кроме ответов @Esailija и @Greg: эта функция создаст другой документ вне дерева текущего документа и очистит все сценарии, стили и изображения из нового документа:

 function insertDocument (myHTML) {
    var newHTMLDocument = document.implementation.createHTMLDocument().body;
    newHTMLDocument.innerHTML = myHTML;
    [].forEach.call(newHTMLDocument.querySelectorAll("script, style, img"), function(el) {el.remove(); });
    documentsList.push(newHTMLDocument);
    return $(newHTMLDocument.innerHTML);
}
  

Этот отлично подходит для выполнения ajax-запросов, и очистка содержимого будет быстрее 🙂