如何在Oracle中正确地将字符串参数传递给XPATH?

How to correctly pass a string argument to XPATH in Oracle?

提问人:TN. 提问时间:5/3/2021 最后编辑:TN. 更新时间:5/3/2021 访问量:203

问:

如何将字符串参数传递给?EXTRACTVALUE

例如:

EXTRACTVALUE(fooColumn, '/foo/bar[@baz = "arg"]/@value')

如何用真正的论据代替?"arg":arg

朴素的解决方案:

EXTRACTVALUE(fooColumn, '/foo/bar[@baz = "' || :arg || '"]/@value')

如何防止此处可能出现的“XPath”注入? 是否有 XPath 转义函数?

Oracle XPath SQL注入

评论

0赞 MT0 5/3/2021
EXTRACTVALUE已弃用。
0赞 TN. 5/3/2021
@MT0我知道这已被弃用。EXTRACTVALUE
0赞 Alex Poole 5/3/2021
那么你是在问如何专门用 来做到这一点,还是只是为了有什么方法可以做到这一点?extractvalue
0赞 TN. 5/3/2021
@AlexPoole我想知道如何使用.我知道我可以在 中使用 PASSING 子句。EXCTRACTVALUEXMLQUERY

答:

0赞 MT0 5/3/2021 #1

EXTRACTVALUE已弃用,您应该改用 OR。XMLQUERYXMLTABLE

您可以尝试使用该软件包:DBMS_ASSERT

CREATE FUNCTION enquote_name (
  name IN VARCHAR2
) RETURN VARCHAR2
IS
BEGIN
  -- Wrap it in a function call to use the PL/SQL FALSE literal.
  RETURN DBMS_ASSERT.ENQUOTE_NAME(name, FALSE);
END;
/

然后:

SELECT XMLQUERY(
         ('/foo/bar[@baz='||ENQUOTE_NAME(:arg)||']/@value')
         PASSING fooColumn
         RETURNING CONTENT
       ) AS value
FROM   table_name

SELECT EXTRACTVALUE( foocolumn, '/foo/bar[@baz='||ENQUOTE_NAME(:arg)||']/@value')
         AS value
FROM   table_name

对于表:

CREATE TABLE table_name ( foocolumn ) AS
SELECT XMLTYPE(
'<foo><bar baz="abc" value="123" /><bar baz="def" value="456" /></foo>'
)
FROM DUAL;

输出,当是 ::argdef

价值
456

如果尝试使用 as,则查询将返回零行(或引发异常);但是,如果您尝试传递相同的值而不将其包装在对的调用中(并包含将添加的双引号),那么它将执行您试图避免的 XPATH 注入。:arg'abc"][@value="123'EXTRACTVALUEENQUOTE_NAMEENQUOTE_NAME

db<>fiddle 在这里

评论

1赞 TN. 5/3/2021
你为什么用于 ? XMLQUERY 接受参数的子句。ENQUOTE_NAMEXMLQUERYPASSING
0赞 MT0 5/3/2021
@TN。这是解决您的问题的一种方式,如果您选择使用已弃用的方法,那么您可以使用完全相同的方法。EXTRACTVALUE
0赞 TN. 5/3/2021
是的,你是对的。只是你的答案现在有点误导(带有ENQUOTE_NAME的 XMLQUERY)。但谢谢你的ENQUOTE_NAME。