Мне нужно динамически построить запрос XPath для атрибута элемента, где значение атрибута предоставляется пользователем. Я не уверен, как сделать очистку или дезинформировать это значение, чтобы предотвратить эквивалент XPath атаки SQL-инъекции. Например (в PHP):
<?php function xPathQuery($attr) { $xml = simplexml_load_file('example.xml'); return $xml->xpath("//myElement[@content='{$attr}']"); } xPathQuery('This should work fine'); # //myElement[@content='This should work fine'] xPathQuery('As should "this"'); # //myElement[@content='As should "this"'] xPathQuery('This\'ll cause problems'); # //myElement[@content='This'll cause problems'] xPathQuery('\']/../privateElement[@content=\'private data'); # //myElement[@content='']/../privateElement[@content='private data']
Последнее, в частности, напоминает атаки SQL-инъекций.
Теперь я знаю, что на самом деле будут атрибуты, содержащие одинарные кавычки и атрибуты, содержащие двойные кавычки. Поскольку они представлены в качестве аргумента функции, каков был бы идеальный способ дезинформировать вклад для этих целей?
XPath действительно включает в себя метод безопасного выполнения, поскольку он разрешает ссылки на переменные в форме $varname
в выражениях. Библиотека, на которой основан PHP SimpleXML, обеспечивает интерфейс для подачи переменных , однако это не отображается функцией xpath в вашем примере.
Как демонстрация действительно, насколько это просто:
>>> from lxml import etree >>> n = etree.fromstring('<na=\'He said "I'm here"\'/>') >>> n.xpath("@a=$maybeunsafe", maybeunsafe='He said "I\'m here"') True
Это использует lxml , оболочку python для той же базовой библиотеки, что и SimpleXML, с аналогичной функцией xpath . Булевы, числа и наборы узлов также могут передаваться напрямую.
Если переключение на более удобный интерфейс XPath не является вариантом, обходным путем при использовании внешней строки будет что-то (не стесняйтесь адаптироваться к PHP) в соответствии с:
def safe_xpath_string(strvar): if "'" in strvar: return "',\"'\",'".join(strvar.split("'")).join(("concat('","')")) return strvar.join("''")
Возвращаемое значение может быть непосредственно вставлено в строку выражения. Поскольку это на самом деле не очень читаемо, вот как он себя ведет:
>>> print safe_xpath_string("basic") 'basic' >>> print safe_xpath_string('He said "I\'m here"') concat('He said "I',"'",'m here"')
Обратите внимание: вы не можете использовать экранирование в форме '
вне XML-документа, а также не являются универсальными процедурами сериализации XML. Тем не менее, функция concath XPath может использоваться для создания строки с обоими типами котировок в любом контексте.
Вариант PHP:
function safe_xpath_string($value) { $quote = "'"; if (FALSE === strpos($value, $quote)) return $quote.$value.$quote; else return sprintf("concat('%s')", implode("', \"'\", '", explode($quote, $value))); }
function xPathQuery($attr) { $xml = simplexml_load_file('example.xml'); $to_encode = array('&', '"'); $to_replace = array('&','"'); $attr = replace($to_encode, $to_replace, $attr); return $xml->xpath("//myElement[@content=\"{$attr}\"]"); }
Хорошо, что он делает?
Он кодирует все вхождения & и «как & amp; и» в строке, что должно дать вам безопасный селектор для этого конкретного использования. Обратите внимание, что я также заменил внутренний «в xpath на». EDIT: С тех пор было указано, что «может быть экранировано как», поэтому вы можете использовать любой способ цитирования строк, который вы предпочитаете.
Я бы создал одноэлементный XML-документ, используя DOM, используя DOM, чтобы установить текст элемента в предоставленное значение, а затем извлечь текст из строкового представления XML в XML. Это гарантирует, что все экранирование персонажа будет выполнено правильно, а не только персонаж, с которым я сталкиваюсь, чтобы думать об этом.
Редактировать: причина, по которой я буду использовать DOM в таких ситуациях, это то, что люди, которые написали DOM, прочитали рекомендацию XML, и у меня нет (по крайней мере, не с уровнем ухода, который у них есть). Чтобы выбрать тривиальный пример, DOM сообщит об ошибке синтаксического анализа, если текст содержит символ, который не разрешает XML (например, # x8), поскольку авторы DOM внедрили раздел 2.2 рекомендации XML.
Теперь я могу сказать: «Хорошо, я просто получу список недопустимых символов из рекомендации XML и вычеркнул их из ввода». Конечно. Давайте просто посмотрим на рекомендацию XML и … гм, каковы черты суррогатных блоков Unicode? Какой код мне нужно написать, чтобы избавиться от них? Могут ли они даже попасть в мой текст в первую очередь?
Предположим, я это понял. Существуют ли другие аспекты того, как рекомендации XML указывают представления символов, о которых я не знаю? Вероятно. Будут ли они влиять на то, что я пытаюсь реализовать? Может быть.
Если я позволю DOM сделать кодировку символов для меня, мне не нужно беспокоиться об этом.