Что такое код domdocumenttype >system_id


Содержание

DomDocumentType->system_ >get_attribute_node()» HREF=»/php/007/function.domelement-get-attribute-node.html»>
Руководство по PHP
Пред. След.

DomDocumentType->system_ >

(no version information, might be only in CVS)

DomDocumentType->system_id() — Returns the system id of document type

Описание

Returns the system id of the document type.

Возвращаемые значения

Returns the system >DomDocumentType , as a string.

Примеры

Пример 1. Retrieving the system id

if (! $dom = domxml_open_mem ( $xmlstr )) <
echo «Error while parsing the document\n» ;
exit;
>

$doctype = $dom -> doctype ();
echo $doctype -> system_id ();
?>

Результат выполнения данного примера:

Migrating to PHP 5

Use the systemId property of the DOMDocumentType object.

Свойства узлов: тип, тег и содержимое

Теперь давайте более внимательно взглянем на DOM-узлы.

В этой главе мы подробнее разберём, что они собой представляют и изучим их основные свойства.

Классы DOM-узлов

Каждый DOM-узел принадлежит соответствующему встроенному классу.

Корнем иерархии является EventTarget, от него наследует Node и остальные DOM-узлы.

На рисунке ниже изображены основные классы:

Существуют следующие классы:

  • EventTarget – это корневой «абстрактный» класс. Объекты этого класса никогда не создаются. Он служит основой, благодаря которой все DOM-узлы поддерживают так называемые «события», о которых мы поговорим позже.
  • Node – также является «абстрактным» классом, и служит основой для DOM-узлов. Он обеспечивает базовую функциональность: parentNode , nextSibling , childNodes и т.д. (это геттеры). Объекты класса Node никогда не создаются. Но есть определённые классы узлов, которые наследуют от него: Text – для текстовых узлов, Element – для узлов-элементов и более экзотический Comment – для узлов-комментариев.
  • Element – это базовый класс для DOM-элементов. Он обеспечивает навигацию на уровне элементов: nextElementSibling , children и методы поиска: getElementsByTagName , querySelector . Браузер поддерживает не только HTML, но также XML и SVG. Класс Element служит базой для следующих классов: SVGElement , XMLElement и HTMLElement .
  • HTMLElement – является базовым классом для всех остальных HTML-элементов. От него наследуют конкретные элементы:
    • HTMLInputElement – класс для тега ,
    • HTMLBodyElement – класс для тега ,
    • HTMLAnchorElement – класс для тега ,
    • …и т.д, каждому тегу соответствует свой класс, который предоставляет определённые свойства и методы.

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

Рассмотрим DOM-объект для тега . Он принадлежит классу HTMLInputElement.

Он получает свойства и методы из (в порядке наследования):

  • HTMLInputElement – этот класс предоставляет специфичные для элементов формы свойства,
  • HTMLElement – предоставляет общие для HTML-элементов методы (и геттеры/сеттеры),
  • Element – предоставляет типовые методы элемента,
  • Node – предоставляет общие свойства DOM-узлов,
  • EventTarget – обеспечивает поддержку событий (поговорим о них дальше),
  • …и, наконец, он наследует от Object , поэтому доступны также методы «обычного объекта», такие как hasOwnProperty .

Описание структуры XML документа средствами DTD – Document Type Definition

Шпаргалка по DTD.

DTD – Один из способов формализованного описания схемы документа XML, сделанного на языке, понятном программе-анализатору.

В настоящее время идет отказ от использования DTD в пользу XSD (XML Schema Definition), по ряду причин:

  • DTD использует отличный от XML синтаксис.
  • Отсутствует типизация узлов.
  • Отсутствует поддержка пространств имён.

Тем не менее этот способ ещё широко применяется поскольку является более простым и удобным для описания несложных схем документов.

КОНСТРУКЦИИ DTD

Описание схемы состоит из объявлений разметки (markup declaration), начинающихся с пары символов “ ”

ОБЪЯВЛЕНИЕ ТИПА ЭЛЕМЕНТА


(должен быть описан каждый элемент документа)

  • EMPTY – пустой (например
    )
  • ANY – любое содержимое (встречается редко)
  • (#PCDATA)– только символьные данные
  • (список имен вложенных элементов ч.з. запятую) – вложенные элементы должны следовать в документе в том порядке, в котором они перечислены в объявлении. Объявляется только один уровень вложенности. Элементы можно группировать скобками.
    Использование разделителя | между элементами указывает, что встречается один из разделенных элементов.
    После элементов или скобок:
  • ? – встречается 0 или 1 раз
  • * – 0 или несколько раз
  • + – 1 или несколько раз

ОБЪЯВЛЕНИЕ АТРИБУТОВ

Атрибуты объявляются после объявления самого элемента. Все атрибуты одного элемента объявляются сразу, одним списком.

Для каждого атрибута записывается его имя, тип и признак обязательности.

Типы атрибутов:
  • CDATA – (Character set of data) строка символов
  • Список значений атрибута в скобках, перечисл чз “|”
  • ID – уникальный идентификатор
  • IDREF – идентификатор, содержащий одно из значений атрибута ID, исп в качестве ссылки на др элементы
  • IDREFS – идентификатор, содержащий набор значений атрибута типа ID, перечисленных через пробел , так же исп в качестве ссылки сразу на несколько элементов.
  • ENTITY – имя не проверяемой анализатором сущности (объявленные в том же описанииDTD)
  • ENTITIES – имена не проверяемых анализатором сущностей.
  • NMTOKEN – слово, содержащее только символы, применяемые в именах (имена др элементов или атрибутов, например чтобы ссылаться на них)
  • NMTOKENS – слова, перечисленные через пробелы
  • NOTATION – обозначение (обозначения, расшифрованные в описанииDTD)
  • NOTATIONS – список нотаций
признак обязательности:
  • Значение атрибута по умолчанию – указывается в кавычках и обозначает что атрибут необязателен.
  • #REQUIRED – атрибут надо обязательно записывать в элементе.
  • #IMPLIED – атрибут необязателен, у него нет значения по умолчанию.
  • #FIXED – у атрибута есть только одно значение, кот записывается тут же через пробел.

При исп пространства имен надо всегда указывать уточненное (QName), а не локальное имя.

Атрибуты не входят в пространство имен по умолчанию.

Атрибуты “xml:lang” и “xml:space” так же дол быть объявлены в DTD в случае их применения

ОБЪЯВЛЕНИЕ СУЩНОСТЕЙ

Внутренние сущности – задаются при объявлении сущности.

— можно применять дальше в самом DTD ниже объявления.

Внешние сущности – содержатся в отдельном файле или встроены в программу-анализатор.

Параметризованные сущности – исп только внутри описания DTD

Ссылка на параметризированную сущность начинается не с “&”, а с “%” !

Сущности делятся на разбираемые(parsed) и не разбираемые (unparsed). Разбираемые предст собой фрагмент документа XML или целый документ и подлежат обработке программой-анализатором после подстановки. После подстановки разборки сущность становится частью XML документа.

Двоичный программный код, чертеж, изображение и др. не надо обрабатывать средствами XML, для этого сущность надо объявить не разбираемой . Для этого в конце объявления сущности делается пометка “NDATA” и указывается обозначение (notation) вставляемого объекта.

ПРЕДОПРЕДЕЛЕННЫЕ СУЩНОСТИ В XML

ОБЪЯВЛЕНИЕ ОБОЗНАЧЕНИЯ (NOTATION)

Объявляются подобно сущностям, также могут быть внутренними и внешними.

Внутренняя


Внешняя

SYSTEM | PUBLIC — в данном случае равнозначны т.к. в public не обязательно общеизвестная ссылка.

РАЗМЕЩЕНИЕ DTD

Либо в отдельном файле “*.dtd” указав его имя в кавычках во второй части пролога DOCTYPE, либо включить описание непосредственно во вторую часть пролога, заключив его в квадратные скобки.

62 LPX-00000 to LPX-00690

1s buffer overflow, maximum size is

2s [general entity

1S» does not match DTD root «

* attributes with default values — or —

* attributes with values subject to normalization — or —

* element types with element content»

* The declaration matches EMPTY and the element has no content

* The declaration matches children and the sequence of child elements belongs to the language generated by the regular expression in the content model, with optional white space (characters matching the nonterminal S) between each pair of child elements.

* The declaration matches Mixed and the content consists of character data and child elements whose types match names in the content model.

* The declaration matches ANY, and the types of any child elements have been declared.»

S» is not declared in the DTD

S» is not empty as required by the DTD

2S» is undefined

S» has multiple declarations

S» in mixed-content declaration

2S» (not a Nmtoken)

S» has multiple ID attributes

1S» ID attribute «

2S» must be #IMPLIED or #REQUIRED

2S» has invalid enumeration value «

1S» is missing required attribute «

2S» has invalid value «

2S» must be an unparsed entity

1S» NDATA (notation) «

2S» is undefined

c’ in character reference

s» found in an attribute value

1S» does not match start-element tag «

S» is not declared

S» is not a parsed entity

S» refers to itself

2x) found in a Name or Nmtoken

2c’) found in a Name or Nmtoken

S» is not declared

2c’) found in public identifier

1d, must be 0 to

s-based but default input encoding is not


S» not expected for

S used but not declared

S not supported

S» is not a valid value for the lang attribute of xsl:sort

1S’, for attribute ‘

S’ doesn’t have a parent element.

S’ doesn’t have a parent element.

Книга «Безопасность в PHP» (часть 2). Атаки с внедрением кода

В списке десяти наиболее распространённых видов атак по версии OWASP первые два места занимают атаки с внедрением кода и XSS (межсайтовый скриптинг). Они идут рука об руку, потому что XSS, как и ряд других видов нападений, зависит от успешности атак с внедрением. Под этим названием скрывается целый класс атак, в ходе которых в веб-приложение внедряются данные, чтобы заставить его выполнить или интерпретировать вредоносный код так, как это нужно злоумышленнику. К таким атакам относятся, например, XSS, внедрение SQL, внедрение заголовка, внедрение кода и полное раскрытие путей (Full Path Disclosure). И это лишь малая часть.

Атаки с внедрением — страшилка для всех программистов. Они наиболее распространены и успешны за счёт разнообразия, масштабности и (иногда) сложности защиты от них. Всем приложениям нужно брать откуда-то данные. XSS и UI Redress встречаются особенно часто, поэтому я посвятил им отдельные главы и выделил их из общего класса.

OWASP предлагает следующее определение атак с внедрением:

Возможности внедрения — вроде SQL, OS и LDAP — возникают тогда, когда интерпретатор получает ненадёжные данные в виде части командного запроса. Зловредные данные могут обмануть интерпретатор и заставить его выполнить определённые команды или обратиться к неавторизованным данным.

Внедрение SQL

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

Итак, данные внедряются в веб-приложение, а затем используются в SQL-запросах. Обычно они попадают из ненадёжных источников ввода, например из веб-форм. Однако внедрение может выполняться и из других мест, скажем, из самой базы данных. Программисты часто верят в полную безопасность своей базы, не осознавая, что если она была безопасна в одном случае, то это совершенно не значит, что она будет безопасна и впредь. Данные из базы должны считаться ненадёжными до тех пор, пока не доказано обратное, т. е. пока они не прошли проверку.

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

Посмотрите на этот запрос:

Здесь целый ряд косяков. Во-первых, мы не проверяли содержимое POST-данных на предмет корректности user_id . Во-вторых, мы позволяем ненадёжному источнику сообщать нам, какой user_id использовать: атакующий может подсунуть любой корректный user_id . Возможно, он содержался в скрытом поле формы, которую мы считали безопасной, потому что её нельзя редактировать (при этом забыв, что атакующие могут вводить любые данные). В-третьих, мы не заэкранировали user_id и не передали его в запрос в виде параметра (bound parameter), что тоже позволяет атакующему внедрять произвольные строки, которые будут манипулировать SQL-запросом, учитывая, что мы не смогли проверить его в первую очередь.

Это три упущения очень часто встречаются в веб-приложениях.

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

Также уделяйте внимание другому фактору внедрения SQL: постоянное хранилище не всегда нужно держать на сервере. HTML 5 поддерживает использование БД на стороне клиента, куда можно отправлять запросы с помощью SQL и JavaScript. Для этого есть два API: WebSQL и IndexedDB. В 2010 году W3C не рекомендовал выбирать WebSQL; он поддерживается WebKit-браузерами, использующими SQLite в качестве бэкенда. Скорее всего, поддержка сохранится ради обратной совместимости, даже несмотря на рекомендацию W3C. Как следует из его названия, этот API принимает SQL-запросы, а значит, может быть мишенью атак с внедрением. IndexedDB — это более новая альтернатива, база данных NoSQL (не требует использования SQL-запросов).

Примеры внедрения SQL

Манипулирование SQL-запросами может преследовать такие цели:

  1. Утечки данных.
  2. Раскрытие хранимой информации.
  3. Манипулирование хранимой информацией.
  4. Обход авторизации.
  5. Внедрение SQL на стороне клиента.

Защита от внедрения SQL

Защита от внедрения SQL базируется на принципе эшелонирования. Перед использованием данных в запросе надо проверять, что их форма корректна. Также необходимо изолировать данные до включения в запрос либо включать в виде параметра перехода.

Проверка

Я не устаю повторять: все данные, которые не были явным образом созданы в исходном PHP-коде текущего запроса, ненадёжны. Строго проверяйте их и отклоняйте всё, что не прошло проверок. Не пытайтесь «исправить» данные, можно внести лишь лёгкие, косметические изменения в формат.

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

Экранирование

С помощью расширения mysqli вы можете изолировать все данные, включённые в SQL-запрос. Это делает функция mysqli_real_escape_string() . Расширение pgsql для PostgresSQL предлагает функции pg_escape_bytea() , pg_escape_identifier() , pg_escape_literal() и pg_escape_string() . В расширении mssql (Microsoft SQL Server) нет изолирующих функций, а подход с применением addslashes() неэффективен — вам понадобится кастомная функция.

Чтобы ещё больше усложнить вам жизнь, скажу, что вы не имеете права на ошибку при изолировании вводимых в запрос данных. Один промах — и вы уязвимы для атаки.

Подведём итог. Экранирование — не лучший вариант защиты. К нему стоит прибегать в крайнем случае. Оно может понадобиться, если используемая вами для абстракции библиотека БД допускает настройку голых SQL-запросов или частей запроса без принудительной привязки параметров. В остальных случаях лучше вообще избегать изолирования. Этот подход сложен, провоцирует ошибки и различается в зависимости от расширения базы данных.

Параметризованные запросы (заранее подготовленные выражения)

Параметризация, или привязка параметров, — это рекомендованный способ создания SQL-запросов. Все хорошие библиотеки БД применяют его по умолчанию. Вот пример использования расширения PDO для PHP:

Метод bindParam() , доступный для выражений PDO, позволяет привязывать параметры к «местам для вставки» (placeholders), представленным в заранее подготовленном выражении. Этот метод принимает параметры основных типов данных, например, PDO::PARAM_INT , PDO::PARAM_BOOL , PDO::PARAM_LOB и PDO::PARAM_STR . Для PDO::PARAM_STR это делается по умолчанию, если не задано другое, так что запомните и для других значений!

В отличие от ручного изолирования, привязка параметров (или иной другой метод, используемый вашей библиотекой БД) позволит корректно изолировать автоматически привязываемые данные, так что вам не придётся вспоминать, какую функцию применять. Также согласованная привязка параметров гораздо надёжнее, чем попытка не забыть, что нужно изолировать всё вручную.

Реализация принципа наименьших привилегий

Прервать успешное внедрение SQL не менее важно, чем его полностью предотвратить. Когда атакующий получает возможность выполнять SQL-запросы, то он будет это делать как конкретный пользователь БД. Благодаря принципу наименьших привилегий можно удостовериться, что все пользователи имеют лишь те привилегии, которые абсолютно необходимы для выполнения их задач.

Если у пользователя широкие привилегии, то атакующий может удалять таблицы и менять привилегии других пользователей, выполняя от их имени новые внедрения SQL. Чтобы этого не произошло, никогда не обращайтесь к БД из веб-приложения от лица root’а, администратора или иного пользователя с высокими привилегиями.

Другое применение принципа — разделение ролей чтения и записи данных в базу. Выберите одного пользователя с правами только на запись, а другого — с правами только на чтение. Если атака будет направлена на «читающего» пользователя, то у злоумышленника не получится манипулировать данными в таблице или записывать их. Можно ограничивать доступ в ещё более узких рамках, тем самым уменьшая последствия успешных атак с внедрением SQL.

Многие веб-приложения, особенно с открытым кодом, разработаны так, что в них используется только один пользователь БД, уровень привилегий которого почти наверняка никогда не проверяется. Так что не забывайте об этом моменте и не пытайтесь запускать приложения под администраторским аккаунтом.


Внедрение кода (известно как удалённое включение файла, Remote File Inclusion)

Внедрение кода — это любые способы, которые позволяют атакующему добавлять в веб-приложение исходный код с возможностью его интерпретировать и исполнять. При этом речь не идёт о внедрении кода в клиентскую часть, например в JavaScript, здесь применяются уже XSS-атаки.

Можно внедрить исходный код напрямую из ненадёжного источника входных данных либо заставить веб-приложение загрузить его из локальной файловой системы или внешнего ресурса вроде URL. Когда код внедряется в результате включения внешнего источника, то это обычно называют удалённым включением файла (RFI), хотя само по себе RFI всегда предназначено для внедрения кода.

Основные причины внедрения кода:

  • обход проверки входных данных,
  • внедрение ненадёжных входных данных в любой контекст, где они будут расценены как PHP-код,
  • взлом безопасности репозиториев исходного кода,
  • отключение предупреждений о загрузке сторонних библиотек,
  • переконфигурация сервера, чтобы он передавал в PHP-интерпретатор файлы, не относящиеся к PHP.

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

Примеры внедрения кода

В PHP множество целей для внедрения кода, так что этот тип атак возглавляет список наблюдения у любого программиста.

Включение файла

Самые очевидные цели для внедрения кода — функции include() , include_once() , require() и require_once() . Если ненадёжные входные данные позволят определить передаваемый в эти функции параметр path , то можно будет удалённо управлять выбором файла для включения. Нужно отметить, что включённый файл не обязан быть настоящим PHP-файлом, допускается использование файла любого формата, способного хранить текстовые данные (т. е. почти без ограничений).

Параметр path также может быть уязвим для атак обхода каталога (Directory Traversal) или удалённого включения файла. Использование в path комбинаций символов ../ или… позволяет атакующему переходить почти к любому файлу, к которому имеет доступ PHP-процесс. Заодно в конфигурации PHP по умолчанию вышеприведённые функции принимают URL, если не отключён allow_url_include.

Проверка

Функция PHP eval() принимает к исполнению строку PHP-кода.

Внедрение регулярных выражений

Функция PCRE (регулярное выражение, совместимое с Perl) preg_replace() в PHP допускает использование модификатора e (PREG_REPLACE_EVAL). Это означает замещающую строку, которая после подстановки будет считаться PHP-кодом. И если в этой строке имеются ненадёжные входные данные, то они смогут внедрить исполняемый PHP-код.

Дефектная логика включения файла

Веб-приложения по определению включают в себя файлы, необходимые для обслуживания любых запросов. Если воспользоваться дефектами логики маршрутизации, управления зависимостями, автозагрузки и других процессов, то манипуляция с путём прохождения запроса или его параметрами заставит сервер включить конкретные локальные файлы. Поскольку веб-приложение не рассчитано на обработку таких манипуляций, последствия могут быть непредсказуемыми. Например, приложение невольно засветит маршруты, предназначенные только для использования в командной строке. Или раскроет другие классы, конструкторы которых выполняют задачи (лучше классы так не проектировать, но это всё же встречается). Любой из этих сценариев может помешать операциям бэкенда приложения, что позволит манипулировать данными или провести DOS-атаку на ресурсоёмкие операции, которые не подразумевают прямого доступа.

Задачи внедрения кода

Спектр задач чрезвычайно широк, поскольку этот тип атак позволяет выполнять любой PHP-код на выбор атакующего.

Defenses against Code Injection

Command Injection

Examples of Command Injection

Defenses against Command Injection

Внедрение лога (известно как внедрение лог-файла, Log File Injection)

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

Уязвимость логов зависит от механизмов контроля над записью логов, а также от обращения с данными логов как с ненадёжным источником при просмотре и анализе записей.

Простая система журналирования может записывать в файл текстовые строки с помощью file_put_contents() . Например, программист регистрирует ошибочные попытки авторизации в виде строк следующего формата:

А что, если атакующий использует в форме имя «AdminnSuccessful login by Adminn»?

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

Здесь вся суть в том, что атакующий способен добавлять в лог всевозможные записи. Также можно внедрить XSS-вектор и даже символы, затрудняющие чтение в консоли записей лога.

Задачи внедрения лога

Одна из целей внедрения — интерпретаторы формата логов. Если инструмент анализа использует регулярные выражения для парсинга записей в логе, чтобы делить их на части и раскидывать по разным полям, то можно создать и внедрить такую строку, которая заставит регулярные выражения выбирать внедрённые поля вместо правильных. Например, эта запись может стать источником нескольких проблем:

Более изощрённые атаки с внедрением логов базируются на атаках с обходом каталога, чтобы отобразить лог в браузере. При подходящих условиях внедрение PHP-кода в сообщение лога и открытие в браузере файла с записями приведёт к успешному внедрению кода, аккуратно форматированного и выполняемого по желанию злоумышленника. А если дойдёт до исполнения на сервере зловредного PHP, то остаётся надеяться лишь на эффективность эшелонирования защиты, которое может уменьшить ущерб.

Защита от внедрения лога

Проще всего фильтровать все внешние сообщения логов с помощью белого списка. Допустим, ограничить набор символов только цифрами, буквами и пробелами. Сообщения, содержащие неразрешённые символы, считаются повреждёнными. Тогда в журнале появляется запись о потенциальной попытке внедрения лог-файла. Это простой способ защиты для простых текстовых логов, когда нельзя избежать включения в сообщения ненадёжных входных данных.

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

Обход пути (известен как обход каталога, Directory Traversal)

Атаки с обходом пути — это попытки повлиять на операции чтения или записи файлов в бэкенде веб-приложения. Делается это с помощью внедрения параметров, которые позволяют манипулировать путями файлов, вовлечённых в операции бэкенда. Так что атаки этого типа облегчают раскрытие информации (Information Disclosure) и локальное/удалённое внедрение файлов.

Такие атаки мы рассмотрим отдельно, но в основе их успешности лежит именно обход пути. Поскольку описанные ниже функции характерны именно для манипулирования путями файлов, имеет смысл упомянуть, что многие PHP-функции не принимают пути к файлам в привычном смысле слова. Вместо этого функции наподобие include() или file() принимают URI.

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

Дело в том, что относительный путь обрабатывается на стороне (настройка include_path в php.ini и доступных автозагрузчиках). В таких случаях PHP-функции особенно уязвимы для многих форм манипуляций с параметрами, включая подмену схемы URI файла (File URI Scheme Substitution), когда атакующий может внедрить HTTP или FTP URI, если в начало пути файла внедрены ненадёжные данные. Подробнее об этом мы поговорим в разделе, посвящённом атакам с удалённым включением файлов, а пока сосредоточимся на обходах путей файловых систем.


Эта уязвимость подразумевает изменение пути для обращения к другому файлу. Обычно это достигается с помощью внедрения серии последовательностей ../ в аргумент, который затем присоединяется к функциям или целиком вставляется в функции наподобие include() , require() , file_get_contents() и даже менее подозрительные (для кого-то) функции вроде DOMDocument::load() .

С помощью последовательности ../ атакующий заставляет систему вернуться в родительский каталог. Так что путь /var/www/public/../vendor на самом деле ведёт в /var/www/vendor . Последовательность ../ после / public возвращает нас в родительский каталог, т. е. в / var/www . Таким образом злоумышленник получает доступ к файлам, расположенным вне каталога / public , доступного с веб-сервера.

Конечно, обход пути не ограничивается одним лишь возвратом. Можно внедрить новые элементы пути, чтобы получить доступ к дочерним каталогам, которые недоступны из браузера в связи с настройками ограничений в .htaccess. Операции PHP с файловой системой не волнует конфигурация контроля доступа к непубличным файлам и каталогам на веб-сервере.

Examples of Path Traversal

Defenses against Path Traversal

Внедрение XML

Несмотря на внедрение JSON в качестве облегчённого средства передачи данных между сервером и клиентом, XML остаётся популярной альтернативой, API веб-сервисов зачастую поддерживает её параллельно с JSON. Также XML применяется для обмена данными, использующими XML-схемы: RSS, Atom, SOAP и RDF и т. д.

XML вездесущ: его можно найти в серверах веб-приложений, в браузерах (в качестве предпочтительного формата для запросов и откликов XMLHttpRequest) и браузерных расширениях. Учитывая его распространённость и обработку по умолчанию таким популярным парсером, как libxml2, используемым PHP в DOM и в расширениях SimpleXML и XMLReader, XML стал целью для атак с внедрением. Когда браузер активно участвует в XML-обмене, необходимо учитывать, что посредством XSS авторизованные пользователи могут передавать XML-запросы, созданные на самом деле злоумышленниками.

Внедрение внешней XML-сущности (XXE)

Такие атаки существуют из-за того, что библиотеки парсинга XML часто поддерживают использование ссылок на кастомные сущности. Вы познакомитесь со стандартным XML-дополнением сущностей, его применяют для представления специальных символов разметки наподобие > , &lt ; и &apos ;. XML позволяет расширять набор стандартных сущностей, определяя посредством самого XML-документа кастомные сущности. Их можно определять, напрямую включая в опциональный DOCTYPE. Представляемое ими расширенное значение может ссылаться на внешний ресурс, который должен быть включён. XXE-атаки стали популярны именно благодаря возможности ординарного XML хранить кастомные ссылки, которые могут увеличиваться за счёт содержимого внешних ресурсов. При обычных условиях ненадёжные входные данные никогда не должны непредвиденным образом взаимодействовать с нашей системой. А большинство программистов XXE почти однозначно не предвидят XXE-атаки, что вызывает особую озабоченность.

Давайте, к примеру, определим новую кастомную сущность harmless:

XML-документ с этим определением теперь может ссылаться на сущность &harmless; везде, где вообще разрешены сущности:

Когда XML-парсер вроде PHP DOM будет интерпретировать этот XML, он обработает эту кастомную сущность сразу же, как загрузится документ. Поэтому при запросе соответствующего текста вернёт следующее:

This result is completely harmless

Очевидно, что кастомные сущности имеют преимущество в представлении повторяющегося текста и XML с более короткими именами сущностей. Нередко бывает так, что XML должен следовать определённой грамматике, а кастомные сущности упрощают редактирование. Однако, учитывая наше недоверие к внешним входным данным, необходимо быть очень осторожными со всеми XML, потребляемыми нашим приложением. Например, это вовсе не безопасная разновидность:

В зависимости от содержимого запрошенного локального файла данные могут использоваться при расширении сущности &harmless; . А потом расширенный контент может быть извлечён из XML-парсера и включён в исходящие данные веб-приложения для анализа атакующим. Например, для раскрытия информации. Извлечённый файл будет интерпретирован как XML, хотя специальных символов, инициирующих такое интерпретирование, нет. Это ограничивает масштаб раскрытия содержимого локального файла. Если файл интерпретирован как XML, но не содержит корректного XML, то наверняка мы получим ошибку, что предотвратит раскрытие содержимого. Однако в PHP доступен аккуратный трюк, позволяющий обойти ограничение масштаба, поэтому удалённые HTTP-запросы влияют на веб-приложение, даже если возвращённый ответ нельзя передать обратно атакующему.

В PHP часто встречаются три метода парсинга и использования XML: PHP DOM, SimpleXML и XMLReader. Все они применяют расширение libxml2, поддержка внешних сущностей включена по умолчанию. Как следствие, в PHP по умолчанию есть уязвимость к XXE-атакам, которую очень легко пропустить при рассмотрении безопасности веб-приложения или библиотеки, использующей XML.

Не забывайте также, что XHTML и HTML 5 могут быть сериализованы как корректный XML. А значит, некоторые XHTML-страницы или XML-сериализованный HTML 5 могут парситься как XML, с использованием DOMDocument::loadXML() вместо DOMDocument::loadHTML() . Такое применение XML-парсера тоже уязвимо к внедрению внешних XML-сущностей. Помните, что libxml2 пока даже не распознаёт HTML 5 DOCTYPE, поэтому не может проверить его как XHTML DOCTYPES.

Примеры внедрения внешних XML-сущностей

Содержимое файла и раскрытие информации

Выше мы рассмотрели пример раскрытия информации, отметив, что кастомная XML-сущность может ссылаться на внешний файл.

В данном случае кастомная сущность &harmless; будет расширена содержимым файлов. Поскольку все подобные запросы выполняются локально, это позволяет раскрыть содержимое всех файлов, которые может считать приложение. То есть когда расширенная сущность будет включена в исходящие данные приложения, атакующий сможет изучить файлы, находящиеся в закрытом доступе. Правда, в данном случае есть серьёзное ограничение: файлы должны быть либо XML-формата, либо формата, который не приведёт к возникновению ошибки XML-парсера. Но дело в том, что это ограничение можно полностью проигнорировать в PHP:

PHP даёт доступ к обёртке в виде URI, одного из протоколов, принимаемого стандартными функциями по работе с файловой системой: file_get_contents() , require() , require_once() , file() , copy() и многими другими. Обёртка PHP поддерживает ряд фильтров, которые можно применять к конкретному ресурсу, чтобы результаты возвращались вызовом функции. В приведённом выше примере мы применяем к целевому файлу, который хотим прочесть, фильтр convert.base-64-encode .

Это означает, что атакующий может прочитать любой доступный для PHP файл, независимо от текстового формата. Достаточно просто декодировать исходящие из приложения данные, а потом безнаказанно их препарировать. Хотя это не наносит прямого вреда конечным пользователям или бэкенду приложения, зато позволяет атакующим хорошо изучить структуру приложения в попытке найти иные уязвимости. Причём риск, что атакующих обнаружат, минимален.

Обход контроля доступа

Доступ контролируется разными способами. Поскольку XXE-атаки проводятся на бэкенде веб-приложения, использовать сессию текущего пользователя не получится. Но атакующий всё ещё может обойти контроль доступа к бэкенду с помощью запросов от локального сервера. Рассмотрим такой примитивный контроль доступа:

Этот кусок PHP, как и несметное количество ему подобных, ограничивает доступ к определённым PHP-файлам на локальном сервере, т. е. localhost. Однако XXE-атака на фронтенде приложения даёт атакующему точные учётные данные, необходимые для обхода этого контроля доступа, потому что все HTTP-запросы XML-парсера будут делаться из localhost.

Даже если бы просмотр логов был ограничен локальными запросами, атакующий всё равно смог бы получить логи. То же самое касается интерфейсов сопровождения или администрирования, доступ к которым ограничен подобным образом.

DOS-атаки

Для DOS-атак можно использовать почти всё, что диктует потребление серверных ресурсов. С помощью внедрения внешней XML-сущности атакующий получает возможность делать произвольные HTTP-запросы, которые при подходящих условиях истощают серверные ресурсы.

Позднее мы поговорим о других потенциальных DOS-применениях XXE-атак с точки зрения расширения XML-сущностей.

Защита от внедрения внешних XML-сущностей

Такие атаки очень популярны, так что вас удивит, как просто от них защититься. Поскольку DOM, SimpleXML и XMLReader опираются на libxml2, можно всего лишь применить функцию libxml_disable_entity_loader() , отключающую использование внешних сущностей. Правда, это не отключит кастомные сущности, заранее определённые в DOCTYPE, потому что они не используют внешние ресурсы, требующие выполнения HTTP-запроса или операции в файловой системе.

Это нужно сделать для всех операций, подразумевающих загрузку XML из строковых, файлов или удалённых URI.

Там, где приложению никогда не требуются внешние сущности, а также для большинства его запросов можно вообще отключить загрузку внешних ресурсов на более глобальном уровне. В большинстве случаев это куда предпочтительнее для определения всех «точек» загрузки XML, учитывая, что многие библиотеки имеют врождённые уязвимости к XXE-атакам:

Только не забывайте возвращать значение TRUE после каждого временного включения загрузки внешних ресурсов. Она может понадобиться для таких безобидных задач, как преобразование Docbook XML в HTML, когда применение XSL-стилей зависит от внешних сущностей.

Однако отключающая libxml2 функция — не панацея. Проанализируйте другие расширения и PHP-библиотеки, которые парсят или как-то ещё обрабатывают XML, чтобы найти их «выключатели» применения внешних сущностей.

Если это сделать невозможно, то дополнительно проверьте, объявляет ли XML-документ DOCTYPE. Если да и если при этом внешние сущности отключены, то просто выкиньте XML-документ, запретив ненадёжный XML-доступ к потенциально уязвимому парсеру и журналируя его как вероятную атаку. Это необходимый шаг, потому что других признаков не будет — ни ошибок, ни исключений. Встройте эту проверку в свою обычную валидацию входных данных. Но этот метод далеко не идеален, так что крайне рекомендуется в корне решить проблему внешних сущностей.

Также предпочтительно сразу удалять подозрительные данные, которые могут быть результатом атаки. Зачем продолжать работать с чем-то, что выглядит опасным? Так что комбинация из двух вышеописанных мер позволяет заранее игнорировать очевидно вредоносные данные, одновременно защищая себя на случай, если удалить данные не получится (например, если это сторонние библиотеки). Удалять данные приходится и потому, что libxml_disable_entity_loader() отключает не все кастомные сущности, а только те, что ссылаются на внешние ресурсы. Что оставляет возможность атаки с расширением XML-сущности (XML Entity Expansion).

Расширение XML-сущности

Эта атака во многом аналогична атаке с внедрением XML-сущности. Но в данном случае делается акцент на DOS-атаку с попыткой истощить ресурсы серверного окружения целевого приложения. В DOCTYPE XML создаётся определение кастомной сущности, которая, к примеру, может генерировать в памяти XML-структуры гораздо более крупного размера по сравнению с исходной. Это приводит к заполнению памяти и снижению эффективности работы сервера. Такая атака применяется и к XML-сериализации HTML 5 в том случае, если последний не распознан расширением libxml2 как HTML.

Примеры расширения XML-сущности

Есть несколько способов расширить кастомные XML-сущности ради желаемого истощения серверных ресурсов.


Общее расширение сущности

Другое название — «атака квадратичного увеличения». Кастомная сущность определяется в виде очень длинной строки. Если многократно использовать её в документе, то она каждый раз увеличивается, в результате XML-структура потребляет гораздо больше оперативной памяти по сравнению с исходным XML.

Если найти баланс между размером строки кастомной сущности и количеством использования в теле документа, то можно создать такой XML-файл или строку, при расширении которых получится прогнозировать потребление серверной памяти. Если заполнить её такими повторяющимися вопросами, то выйдет настоящая DOS-атака. Недостаток подхода: изначальный XML тоже должен быть довольно большим, потому что потребление памяти зависит от простого эффекта умножения.

Рекурсивное расширение сущности

В то время как общее расширение требует использования изначально большого XML, рекурсивное обеспечивает гораздо более высокий коэффициент увеличения. Этот метод основан на экспоненциальном разложении (resolve) наборов маленьких сущностей таким образом, чтобы они существенно увеличивались в размерах. Вполне логично, что этот метод часто называют XML-бомбой и атакой миллиарда смешков (Billion Laughs Attack).

XML-бомба не требует большого XML, размер которого иногда может быть ограничен приложением. Атака приводит к тому, что память забивается текстом, чей размер в 2^100 раза превышает размер исходного значения сущности — &x0; . Настоящая БОМБА!

Удалённое расширение сущности

Обе вышеописанные атаки используют локально определённые сущности в XML DTD. Но атакующий способен определить сущность и удалённо, если XML-парсер может делать внешние HTTP-запросы. Как мы видели в описании XXE (внедрения внешней XML-сущности), эту возможность нужно заблокировать в качестве базовой меры защиты. Таким образом, защищаясь от XXE, мы защищаемся и от этого вида атаки.

В любом случае: для этой атаки XML-парсер должен делать внешние HTTP-запросы для извлечения расширенного значения соответствующих сущностей. В свою очередь, они самостоятельно определят новые внешние сущности, к которым парсеру придётся сделать дополнительные HTTP-запросы. Таким образом, парочка безобидно выглядящих запросов быстро выйдет из-под контроля, увеличивая нагрузку на доступные серверные ресурсы, что в результате может привести к рекурсивному расширению сущностей и усугубить ситуацию.

Вышеприведённый код также позволяет провести DOS-атаку более хитрым способом: внешние запросы должны быть адаптированы для локального приложения или любого другого приложения, совместно использующего серверные ресурсы. В результате система будет атаковать сама себя: попытки разложить (resolve) внешние сущности с помощью XML-парсера спровоцируют отправку множества запросов к локальным приложениям и потребление массы серверных ресурсов. Эта атака может использоваться для усиления эффекта XXE-атаки, ради дальнейшего выполнения DOS-атаки.

Защита от расширения XML-сущностей

Методы защиты те же, что и в случае с одиночными XXE-атаками. Нужно отключить разложение (resolution) кастомных XML-сущностей в локальные файлы, а также функции; отключить внешние HTTP-запросы с помощью следующей функции, которая глобально применяется ко всем XML-расширениям PHP, основанным на использовании libxml2.

Однако в PHP не реализовано очевидное средство полного отключения определения кастомных сущностей с помощью XML DTD посредством DOCTYPE. PHP определяет константу LIBXML_NOENT , также есть публичное свойство DOMDocument::$substituteEntities , но они не улучшают ситуацию. Похоже, придётся использовать собственные наборы обходных средств защиты.

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

Таким образом, первичная новая угроза — это грубые подходы с XML-бомбой или общим расширением сущности. Для этих атак не требуются локальные или удалённые системные вызовы, не нужна рекурсия сущностей. По сути, единственное средство защиты — удаление или очистка XML, если он содержит DOCTYPE. Удалять безопаснее, если нам не нужно использовать DOCTYPE и если мы не получили его из надёжного доверенного источника, т. е. через проверенное HTTPS-соединение. В противном случае требуется создавать самопальную логику, потому что PHP не даёт нам работающей опции для отключения DTD. Если предположить, что вы можете вызвать libxml_disable_entity_loader(TRUE) , то следующий код будет безопасен, потому что сущность не расширится, пока нет доступа к заражённому расширением значению узла (node value). А в ходе этой проверки такого не случится.

Конечно, нужно ещё подстраховаться и присвоить libxml_disable_entity_loader значение TRUE, чтобы ссылки на внешние сущности не были разложены (resolve) при первичной загрузке XML. Это может быть единственно возможной защитой там, где XML-парсер не зависит от libxml2, если только этот парсер не имеет исчерпывающего набора опций управления разложением сущностей.

Если вы намерены использовать SimpleXML, то имейте в виду, что с помощью функции simplexml_import_dom() вы можете импортировать проверенный объект DOMDocument.

Как узнать >

Вы решили переустановить Windows, либо установили дополнительное оборудование, но система не может найти драйвер на это устройство, не расстраивайтесь.

ШАГ 1. Нужно определить на какое устройство не установились драйвера. Для удобства существует система классификации оборудования и выглядит следующим образом:

VEN_**** , VID_*** — говорит о коде производителя оборудования (VENdor, Vendor Id)
DEV_**** , PID_*** — говорит о устройстве которое установлено (DEVice, Product Id)

ШАГ 2. Для того чтобы узнать код оборудования вам нужно попасть в «Диспетчер устройств«.

Вариант 1. Пуск — Панель управления — Диспетчер устройств

Вариант 2. На значке «Мой компьютер» при помощи нажатия правой кнопки мыши нажимаете на меню «Диспетчер устройств». Если отсутствует данный пункт меню, то нажимаете на «Управление»

В открывшемся меню выбираете пункт «Диспетчер устройств»

Если вы видите знак , то данное оборудование требует установки драйвера. При нажатии правой кнопки мыши на данном устройстве, выберите пункт меню «Свойства«

У Вас откроется окно со свойством оборудования, в моем случае «Свойства Android Phone«.

Переходите во вкладку «Сведения«

Где выбираете пункт меню «коды (ID) оборудования«

У Вас откроется окно:

ШАГ 3. Осталось скопировать код оборудования при помощи сочетания клавиш «CTR+C» и вставить в форму поиска поисковика, либо скопировать на форум поиска драйверов.

Класс DOMDocument

Введение

Представляет все содержимое HTML- или XML-документа; служит корнем дерева документа.

Обзор классов

Свойства

Устарело. Кодировка документа, является доступным только для чтения эквивалентом encoding .

Устарело. Конфигурация, используемая при вызове DOMDocument::normalizeDocument() .

Объявление типа документа, соответствующее этому документу.

Удобный атрибут, предоставляющий прямой доступ к дочернему узлу, как к элементу документа.

Расположение документа или NULL , если оно не определено.

Кодировка документа, как указано в объявлении XML. Этот атрибут отсутствует в последней спецификации DOM Level 3, но является единственным способом манипулирования кодировкой XML-документа в этой реализации.


Форматирует вывод, добавляя отступы и дополнительные пробелы.

Объект класса DOMImplementation, обрабатывающий этот документ.

Указание не убирать лишние пробелы и отступы. По умолчанию TRUE .

Проприетарное свойство. Включает режим восстановления, то есть пытается разобрать некорректно составленные (non-well formed) документы. Этот атрибут не является частью спецификации DOM и специфичен для libxml.

Установите в TRUE для загрузки внешних элементов из объявления типа документа. Может быть полезным при включении элементов с символьными данными в XML-документ.

Устарело. Указание, что документ не зависит от других XML-документов. Это можно определить из XML-объявления. Свойство связано с xmlStandalone .

Выбрасывает исключение DOMException при ошибках. По умолчанию TRUE .

Патентованное свойство. Указывает, заменять или нет элементы документа. Этот атрибут не является частью спецификации DOM и специфичен для libxml.

Загружает DTD и проверяет документ на соответствие. По умолчанию FALSE .

Устарело. Версия XML, соответствует xmlVersion .

Атрибут, определяющий, как часть XML-объявления, кодировку эту документа. Имеет значение NULL в случаях, когда атрибут не задан, либо значение неизвестно, если, например, документ создан в памяти.

Атрибут, определяющий, как часть XML-объявления, что документ является автономным. Принимает значение FALSE , если не указан.

Атрибут, определяющий, как часть XML-объявления, номер версии этого документа. Если объявления в документе нет, но есть поддержка всех особенностей «XML», значение равно «1.0».

Примечания

Расширение DOM использует кодировку UTF-8. Используйте функции utf8_encode() и utf8_decode() для работы с текстами в кодировке ISO-8859-1 или Iconv для других кодировках.

Смотрите также

Содержание

  • DOMDocument::__construct — Создает новый объект DOMDocument
  • DOMDocument::createAttribute — Создать новый атрибут
  • DOMDocument::createAttributeNS — Создает новый атрибут узла с соответствующим пространством имен
  • DOMDocument::createCDATASection — Создает новый узел cdata
  • DOMDocument::createComment — Создать новый узел комментария
  • DOMDocument::createDocumentFragment — Создать новый фрагмент документа
  • DOMDocument::createElement — Создать новый узел элемента
  • DOMDocument::createElementNS — Создать новый узел элемента с соответствующим пространством имен
  • DOMDocument::createEntityReference — Создать новый узел ссылки на сущность
  • DOMDocument::createProcessingInstruction — Создать новый PI-узел
  • DOMDocument::createTextNode — Создать новый текстовый узел
  • DOMDocument::getElementById — Ищет элемент с определенным идентификатором
  • DOMDocument::getElementsByTagName — Ищет все элементы с заданным локальным именем
  • DOMDocument::getElementsByTagNameNS — Ищет все элементы с заданным именем в указанном пространстве имен
  • DOMDocument::importNode — Импортировать узел в текущий документ
  • DOMDocument::load — Загрузка XML из файла
  • DOMDocument::loadHTML — Загрузка HTML из строки
  • DOMDocument::loadHTMLFile — Загрузка HTML из файла
  • DOMDocument::loadXML — Загрузка XML из строки
  • DOMDocument::normalizeDocument — Нормализует документ
  • DOMDocument::registerNodeClass — Регистрация расширенного класса, используемого для создания типа базового узла
  • DOMDocument::relaxNGValidate — Производит проверку документа на правильность построения посредством relaxNG
  • DOMDocument::relaxNGValidateSource — Проверяет документ посредством relaxNG
  • DOMDocument::save — Сохраняет XML-дерево из внутреннего представления в файл
  • DOMDocument::saveHTML — Сохраняет документ из внутреннего представления в строку, используя форматирование HTML

  • DOMDocument::saveHTMLFile — Сохраняет документ из внутреннего представления в файл, используя форматирование HTML
  • DOMDocument::saveXML — Сохраняет XML-дерево из внутреннего представления в виде строки
  • DOMDocument::schemaValidate — Проверяет действительность документа, основываясь на заданной схеме
  • DOMDocument::schemaValidateSource — Проверяет действительность документа, основываясь на схеме
  • DOMDocument::validate — Проверяет документ на соответствие его DTD
  • DOMDocument::xinclude — Проводит вставку XInclude в объекте DOMDocument

User Contributed Notes 16 notes

Showing a quick example of how to use this class, just so that new users can get a quick start without having to figure it all out by themself. ( At the day of posting, this documentation just got added and is lacking examples. )

// Set the content type to be XML, so that the browser will recognise it as XML.
header ( «content-type: application/xml; charset=ISO-8859-15» );

// «Create» the document.
$xml = new DOMDocument ( «1.0» , «ISO-8859-15» );

// Create some elements.
$xml_album = $xml -> createElement ( «Album» );
$xml_track = $xml -> createElement ( «Track» , «The ninth symphony» );

// Set the attributes.
$xml_track -> setAttribute ( «length» , «0:01:15» );
$xml_track -> setAttribute ( «bitrate» , «64kb/s» );
$xml_track -> setAttribute ( «channels» , «2» );

// Create another element, just to show you can add any (realistic to computer) number of sublevels.
$xml_note = $xml -> createElement ( «Note» , «The last symphony composed by Ludwig van Beethoven.» );

// Append the whole bunch.
$xml_track -> appendChild ( $xml_note );
$xml_album -> appendChild ( $xml_track );

// Repeat the above with some different values..
$xml_track = $xml -> createElement ( «Track» , «Highway Blues» );

$xml_track -> setAttribute ( «length» , «0:01:33» );
$xml_track -> setAttribute ( «bitrate» , «64kb/s» );
$xml_track -> setAttribute ( «channels» , «2» );
$xml_album -> appendChild ( $xml_track );

$xml -> appendChild ( $xml_album );

// Parse the XML.
print $xml -> saveXML ();

?>

Output:


The ninth symphony

The last symphony composed by Ludwig van Beethoven.


Highway Blues

If you want your PHP->DOM code to run under the .xml extension, you should set your webserver up to run the .xml extension with PHP ( Refer to the installation/configuration configuration for PHP on how to do this ).

Note that this:
= new DOMDocument ( «1.0» , «ISO-8859-15» );
$xml_album = $xml -> createElement ( «Album» );
$xml_track = $xml -> createElement ( «Track» );
$xml_album -> appendChild ( $xml_track );
$xml -> appendChild ( $xml_album );
?>

is NOT the same as this:
// Will NOT work.
$xml = new DOMDocument ( «1.0» , «ISO-8859-15» );
$xml_album = new DOMElement ( «Album» );
$xml_track = new DOMElement ( «Track» );
$xml_album -> appendChild ( $xml_track );
$xml -> appendChild ( $xml_album );
?>

although this will work:
= new DOMDocument ( «1.0» , «ISO-8859-15» );
$xml_album = new DOMElement ( «Album» );
$xml -> appendChild ( $xml_album );
?>

For those landing here and checking for encoding issue with utf-8 characteres, it’s pretty easy to correct it, without adding any additional output tag to your html.

We’ll be utilizing: mb_convert_encoding

Thanks to the user who shared: SmartDOMDocument in previous comments, I got the idea of solving it. However I truly wish that he shared the method instead of giving a link.

Anyway coming back to the solution, you can simply use:

// checks if the content we’re receiving isn’t empty, to avoid the warning
if ( empty( $content ) ) <
return false ;
>

// converts all special characters to utf-8
$content = mb_convert_encoding ( $content , ‘HTML-ENTITIES’ , ‘UTF-8’ );

// creating new document
$doc = new DOMDocument ( ‘1.0’ , ‘utf-8’ );

//turning off some errors
libxml_use_internal_errors ( true );

// it loads the content without adding enclosing html/body tags and also the doctype declaration
$doc -> LoadHTML ( $content , LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );

// do whatever you want to do with this code now

?>

I hope it solves the issue for someone! If you need my help or service to fix your code, you can reach me on nabtron.com or contact me at the email mentioned with this comment.

Here’s a small function I wrote to get all page links using the DOMDocument which will hopefully be of use to others

/**
* get_links()
*
* @param string $url
* @return array
*/
function get_links ( $url ) <

// Create a new DOM Document to hold our webpage structure
$xml = new DOMDocument ();

// Load the url’s contents into the DOM
$xml -> loadHTMLFile ( $url );

// Empty array to hold all links to return
$links = array();

//Return the links
return $links ;
>
?>

For anyone else who has been having issues with formatOuput not working, here is a work-around:

rather than just doing something like:

= $xml -> saveXML ();
?>

force it to reload the XML from scratch, then it will format correctly:

= $xml -> saveXML ();
$xml = new DOMDocument ();
$xml -> preserveWhiteSpace = false ;
$xml -> formatOutput = true ;
$xml -> loadXML ( $outXML );
$outXML = $xml -> saveXML ();
?>

A nice and simple node 2 array I wrote, worth a try ;)

function getArray ( $node )
<
$array = false ;

if ( $node -> hasAttributes ())
<
foreach ( $node -> attributes as $attr )
<
$array [ $attr -> nodeName ] = $attr -> nodeValue ;
>
>

if ( $node -> hasChildNodes ())
<
if ( $node -> childNodes -> length == 1 )
<
$array [ $node -> firstChild -> nodeName ] = $node -> firstChild -> nodeValue ;
>
else
<
foreach ( $node -> childNodes as $childNode )
<
if ( $childNode -> nodeType != XML_TEXT_NODE )
<
$array [ $childNode -> nodeName ][] = $this -> getArray ( $childNode );
>
>
>
>

You may need to save all or part of a DOMDocument as an XHTML-friendly string, something compliant with both XML and HTML 4. Here’s the DOMDocument class extended with a saveXHTML method:

/**
* XHTML Document
*
* Represents an entire XHTML DOM document; serves as the root of the document tree.
*/
class XHTMLDocument extends DOMDocument <

/**
* These tags must always self-terminate. Anything else must never self-terminate.
*
* @var array
*/
public $selfTerminate = array(
‘area’ , ‘base’ , ‘basefont’ , ‘br’ , ‘col’ , ‘frame’ , ‘hr’ , ‘img’ , ‘input’ , ‘link’ , ‘meta’ , ‘param’
);

/**
* saveXHTML
*
* Dumps the internal XML tree back into an XHTML-friendly string.
*
* @param DOMNode $node
* Use this parameter to output only a specific node rather than the entire document.
*/
public function saveXHTML ( DOMNode $node = null ) <

if (! $node ) $node = $this -> firstChild ;

$doc = new DOMDocument ( ‘1.0’ );
$clone = $doc -> importNode ( $node -> cloneNode ( false ), true );
$term = in_array ( strtolower ( $clone -> nodeName ), $this -> selfTerminate );
$inner = » ;

if (! $term ) <
$clone -> appendChild (new DOMText ( » ));
if ( $node -> childNodes ) foreach ( $node -> childNodes as $child ) <
$inner .= $this -> saveXHTML ( $child );
>
>

$doc -> appendChild ( $clone );
$out = $doc -> saveXML ( $clone );

return $term ? substr ( $out , 0 , — 2 ) . ‘ />’ : str_replace ( ‘> , «> $inner , $out );

?>

This hasn’t been benchmarked, but is probably significantly slower than saveXML or saveHTML and should be used sparingly.

DOMDocument php, как получить содержимое блока, с html тегами?

Вообщем необходимо получить со страницы примерно такого содержания:

а именно необходимо получить содержимое блока с идентификатором «firstElement», вместе с HTML тегами. Я использую DOMDocument, но получается вывести только текст.

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

P.S. вложенных блоков может быть сколько угодно много! и у всех может быть разное содержание!

  • Вопрос задан более трёх лет назад
  • 7466 просмотров

Вот чудо методы для работы с дом-моделью в PHP.
Я не сильно понял вопрос, но благодаря всякой фигне, которая тут написана, мне удалось управлять DOM моделью в PHP.

Вам надо обратить внимание на всякие такие штуки как DOMElement. Потому, что получив DOMDocument веселье не кончается. Теперь вам надо наладить работу с его «Документа» элементами. А значит не помешает так же распочковать структуру всех искомых элементов.
Это можно делать с помощью методов работы с ДОМЕлементами. Такими методами как

public DOMNodeList getElementsByTagName ( string $name )

Но я советую более детально ознакомиться с возможностями работы с ДОМЕлементами, чтоб не вышло путаницы. Найти там то, что вам надо и решить свою задачу.

После публикации вопроса, прошло время и вот что я добился!
Перекурил документацию по php, и сделал вот так:

Тут я добился, что переменная $html — представляет собой ‘string’ со всем содержимым тут все понятно.

Но дальше необходимо вставить $html в другой документ в блок с известным идентификатором, рабочее решение будет с использованием регулярки (написана прям тут) таким:

А вот используя DOMDocument и все такое, я не могу вставить узел, не могу понять (или еще не дочитал) как! Причем пытаюсь использовать DOMNode::appendChild и передаю ей $id из кода выше, но не работает!

DomDocumentType->system_ >(PHP 4 >= 4.1.0)

DomDocumentType->system_id — Returns the system id of document type

Описание

Returns the system id of the document type.

Возвращаемые значения

Returns the system id of the DomDocumentType, as a string.

Примеры

Пример #1 Retrieving the system id

if (! $dom = domxml_open_mem ( $xmlstr )) <
echo «Error while parsing the document\n» ;
exit;
>

$doctype = $dom -> doctype ();
echo $doctype -> system_id ();
?>

Результат выполнения данного примера:

Migrating to PHP 5

Use the systemId property of the DOMDocumentType object.

Что такое код domdocumenttype &#62;system_id

DomDocumentType->system_id — возвращает системный id типа документа.

Описание

string DomDocumentType->system_id (void)

Возвращает системный id типа документа.

Следующий пример выводит ‘/share/sgml/Norman_Walsh/db3xml10/db3xml10.dtd’.

Пример 1. Запрашивание системного >

Назад Оглавление Вперёд
DomDocumentType->public_id Вверх DomElement->get_attribute_node

Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:

Илон Маск рекомендует:  getcwd - Получить имя текущего рабочего каталога
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL