php - 清理/清理 xpath 属性

标签 php xml xpath code-injection

我需要为元素属性动态构建 XPath 查询,其中属性值由用户提供。我不确定如何清理或清理此值以防止 XPath 等同于 SQL 注入(inject)攻击。例如(在 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 注入(inject)攻击。

现在,我确实知道会有包含单引号的属性和包含双引号的属性。由于这些是作为函数的参数提供的,因此清理这些输入的理想方法是什么?

最佳答案

XPath 实际上包含一种安全执行此操作的方法,因为它允许 variable references在表达式中以 $varname 的形式。 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 . bool 值、数字和节点集也可以直接传递。

如果切换到功能更强大的 XPath 接口(interface)不是一个选项,则在给定外部字符串时的解决方法是(随意适应 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 序列化例程也不适用。但是,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)));
}

关于php - 清理/清理 xpath 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/188834/

相关文章:

objective-c - iOS:访问 XML 数据记录的简便方法?

javascript - 如何在 PHP 中转换长度秒的值

php - 添加/更改 1 GET 值同时保留其他值的最佳方法?

java - 如何创建多列 CardView

java - 为什么XPATH无法访问该标签的值? ( java 语)

xml - XPath中contains()谓词测试之间的区别?

xml - XPATH:查找所有具有相同值的元素,直到值发生变化

php - laravel 5.5 中的 payhere 支付网关集成

php - Yii如何美化 Assets URL?

xml - 忽略流式 xml 管道中的子树