清理/清理xpath属性

时间:2008-10-09 19:32:27

标签: php xml xpath code-injection

我需要为元素属性动态构造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 个答案:

答案 0 :(得分:5)

XPath确实包含一种安全执行此操作的方法,因为它允许表达式中$varname形式的variable references。 PHP的SimpleXML所基于的库provides an interface to supply variables,但在您的示例中为is not exposed by the xpath function

作为一个真实的示范,这可能是多么简单:

>>> 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,一个与SimpleXML相同的底层库的python包装器,具有类似的xpath function。布尔值,数字和节点集也可以直接传递。

如果不能选择切换到功能更强大的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文档之外的&apos;形式中使用转义,也不能使用通用XML序列化例程。但是,XPath concat函数可用于在任何上下文中创建具有两种类型引号的字符串。

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)));
}

答案 1 :(得分:-1)

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}\"]");
}

好的,它做了什么?

它编码所有出现的&amp;和字符串中的“as&amp; amp;和&amp; quot;”应该为您提供特定用途的安全选择器。请注意,我还用x替换了内部'。编辑:此后有人指出'可以作为&amp;'进行转义,因此您可以使用您喜欢的任何字符串引用方法。

答案 2 :(得分:-1)

我使用DOM创建单元素XML文档,使用DOM将元素的文本设置为提供的值,然后从DOM的XML字符串表示中获取文本。这将保证所有角色的逃避都能正确完成,而不仅仅是逃避我正在思考的角色。

编辑:我在这种情况下使用DOM的原因是编写DOM的人已经阅读了XML推荐而我没有(至少没有他们所拥有的关注程度)。为了选择一个简单的例子,如果文本包含XML不允许的字符(如#x8),DOM将报告解析错误,因为DOM的作者已经实现了XML推荐的第2.2节。

现在,我可能会说,“好吧,我只是从XML推荐中获取无效字符列表,并将它们从输入中删除。”当然。让我们看看XML推荐和......嗯,Unicode替代块是什么?我必须写什么样的代码才能摆脱它们?他们甚至可以在第一时间进入我的文本吗?

我想我想出来了。 XML建议如何指定我不知道的字符表示的其他方面?大概。这些会对我正在尝试实施的内容产生影响吗?也许

如果我让DOM为我做字符编码,我不必担心任何这些。