Очистка / дезинфекция атрибутов xpath - PullRequest
5 голосов
/ 09 октября 2008

Мне нужно динамически построить запрос 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-инъекций прошлого.

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

Ответы [ 3 ]

5 голосов
/ 11 октября 2008

XPath на самом деле включает в себя метод безопасного выполнения этих действий, который допускает ссылки на переменные в форме $varname в выражениях. Библиотека, на которой основан PHP * SimpleXML , предоставляет интерфейс для предоставления переменных , однако это не предоставляется функцией xpath в вашем примере.

Как демонстрация того, насколько просто это может быть:

>>> from lxml import etree
>>> n = etree.fromstring('<n a=\'He said "I&apos;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"')

Обратите внимание, вы не можете использовать экранирование в форме &apos; вне XML-документа, а также не применимы общие процедуры сериализации XML. Однако функцию concat 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)));
}
0 голосов
/ 10 октября 2008

Я бы создал одноэлементный XML-документ с использованием DOM, использовал DOM, чтобы установить для текста элемента указанное значение, а затем извлекал текст из строкового представления DOM XML. Это будет гарантировать, что все побеги персонажа сделаны правильно, а не только побег персонажа, о котором я думаю, придумывая.

Редактировать: Причина, по которой я бы использовал DOM в подобных ситуациях, заключается в том, что люди, которые написали DOM, прочитали рекомендации XML, а я - нет (по крайней мере, не из-за того уровня их заботы). Чтобы выбрать тривиальный пример, DOM сообщит об ошибке разбора, если текст содержит символ, который XML не допускает (например, # x8), потому что авторы DOM реализовали раздел 2.2 рекомендации XML.

Теперь я могу сказать: «Ну, я просто получу список недопустимых символов из рекомендации XML и уберу их из ввода». Конечно. Давайте просто посмотрим рекомендации XML и ... ну, что, черт возьми, суррогатные блоки Unicode? Какой код я должен написать, чтобы избавиться от них? Могут ли они вообще попасть в мой текст?

Предположим, я это выяснил. Существуют ли другие аспекты того, как в рекомендации XML определяются символьные представления, о которых я не знаю? Наверное. Повлияет ли это на то, что я пытаюсь реализовать? Может быть.

Если я позволю DOM сделать кодировку для меня, мне не придется беспокоиться ни о чем из этого.

0 голосов
/ 09 октября 2008
function xPathQuery($attr) {
    $xml = simplexml_load_file('example.xml');
    $to_encode = array('&', '"');
    $to_replace = array('&amp;','&quot;');
    $attr = replace($to_encode, $to_replace, $attr);
    return $xml->xpath("//myElement[@content=\"{$attr}\"]");
}

Хорошо, что это делает?

Он кодирует все вхождения & и "as & amp; и" в строке, что должно дать вам безопасный селектор для этого конкретного использования. Обратите внимание, что я также заменил внутренний 'в xpath на ". РЕДАКТИРОВАТЬ: С тех пор было указано, что «можно экранировать как & apos ;, так что вы можете использовать любой метод цитирования строк, который вы предпочитаете.

...