清洁/消毒xpath属性 [英] Cleaning/sanitizing xpath attributes

查看:109
本文介绍了清洁/消毒xpath属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要为元素属性动态构建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实际上包含一种安全地执行此操作的方法,因为它允许提供了提供变量的接口,但是在您的示例中,没有被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 ,它是与SimpleXML相同的基础库的python包装器,具有类似的 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文档外部使用&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)));
}

I need to dynamically construct an XPath query for an element attribute, where the attribute value is provided by the user. I'm unsure how to go about cleaning or sanitizing this value to prevent the XPath equivalent of a SQL injection attack. For example (in 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']

The last one in particular is reminiscent to the SQL injection attacks of yore.

Now, I know for a fact there will be attributes containing single quotes and attributes containing double quotes. Since these are provided as an argument to a function, what would be the ideal way to sanitize the input for these?

解决方案

XPath does actually include a method of doing this safely, in that it permits variable references in the form $varname in expressions. The library on which PHP's SimpleXML is based provides an interface to supply variables, however this is not exposed by the xpath function in your example.

As a demonstration of really how simple this can be:

>>> 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

That's using lxml, a python wrapper for the same underlying library as SimpleXML, with a similar xpath function. Booleans, numbers, and node-sets can also be passed directly.

If switching to a more capable XPath interface is not an option, a workaround when given external string would be something (feel free to adapt to PHP) along the lines of:

def safe_xpath_string(strvar):
    if "'" in strvar:
        return "',\"'\",'".join(strvar.split("'")).join(("concat('","')"))
    return strvar.join("''")

The return value can be directly inserted in your expression string. As that's not actually very readable, here is how it behaves:

>>> print safe_xpath_string("basic")
'basic'
>>> print safe_xpath_string('He said "I\'m here"')
concat('He said "I',"'",'m here"')

Note, you can't use escaping in the form &apos; outside of an XML document, nor are generic XML serialisation routines applicable. However, the XPath concat function can be used to create a string with both types of quotes in any context.

PHP variant:

function safe_xpath_string($value)
{
    $quote = "'";
    if (FALSE === strpos($value, $quote))
        return $quote.$value.$quote;
    else
        return sprintf("concat('%s')", implode("', \"'\", '", explode($quote, $value)));
}

这篇关于清洁/消毒xpath属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆