【发布时间】:2023-04-07 05:14:02
【问题描述】:
看起来有问题的函数
我正在探索 postgresql 数据库,我看到了一个反复出现的模式:
CREATE OR REPLACE FUNCTION paginated_class(_orderby text DEFAULT NULL, _limit int DEFAULT 10, _offset int DEFAULT 0)
RETURNS SETOF pg_class
LANGUAGE PLPGSQL
AS $$
BEGIN
return query execute'
select * from pg_class
order by '|| coalesce (_orderby, 'relname ASC') ||'
limit $1 offset $1
'
USING _limit, _offset;
END;
$$;
示例用法:
SELECT * FROM paginated_class(_orderby:='reltype DESC, relowner ASC ')
重复是:
-
_orderby作为text传递。它可以是返回的 SETOF 类型的字段的任意组合。例如。'relname ASC, reltype DESC' -
_orderby参数未以任何方式清理或检查 -
_limit和_offset是整数
为此提供数据库小提琴:https://www.db-fiddle.com/f/vF6bCN37yDrjBiTEsdEwX6/1
问题:这样的函数是否容易受到 SQL 注入的影响?
通过外部迹象可以怀疑此类函数容易受到 sql 注入。
但是我所有寻找参数组合的尝试都失败了。
例如
CREATE TABLE T(id int);
SELECT * FROM paginated_class(_orderby:='reltype; DROP TABLE T; SELECT * FROM pg_class');
将返回“查询错误:错误:无法将多查询计划作为游标打开”。
如果存在UPDATE/INSERT/DELETE,我没有找到利用漏洞的方法。
那么我们可以断定这样的函数实际上是安全的吗?
如果是这样:那为什么?
更新。可能的攻击计划
也许我不清楚:我问的不是一般准则,而是针对漏洞的实验性利用或证明这种利用是不可能的。
为此提供数据库小提琴:https://www.db-fiddle.com/f/vF6bCN37yDrjBiTEsdEwX6/4(或者您当然可以提供其他)
到目前为止我的结论
A.如果_orderby 有部分,那么这种攻击是可能的:
- 抑制第一个
SELECT输出的sql 代码 - 做一些有害的事情
-
select * from pg_class满足RETURNS SETOF pg_class
例如
SELECT * FROM paginated_class(_orderby:='relname; DELETE FROM my_table; SELECT * FROM pg_class')
对于 2 和 3 来说这很容易。我不知道如何做第 1 部分。
这将生成:“错误:无法打开多查询计划作为光标”
B.如果无法先压制SELECT
然后:
- 每个 postgresql 函数都在单独的事务中工作
- 由于错误,此事务将被回滚
- 没有像 Oracle 中那样的自治事务
- 对于非事务性操作:我只知道与序列相关的操作
- 其他一切都是 DML 或 DDL 是事务性的
所以?我们能否得出结论,这样的功能实际上是安全的?
或者我错过了什么?
更新 2. 使用准备好的函数进行攻击
来自答案https://stackoverflow.com/a/69189090/1168212
A.实施拒绝服务攻击是可能的,代价是昂贵的计算
B.副作用:
如果你在 ORDER BY 子句中加入一个有副作用的函数,你也可以修改数据。
让我们试试后者:
CREATE FUNCTION harmful_fn()
RETURNS bool
LANGUAGE SQL
AS '
DELETE FROM my_table;
SELECT true;
';
SELECT * FROM paginated_class(_orderby:='harmful_fn()', _limit:=1);
https://www.db-fiddle.com/f/vF6bCN37yDrjBiTEsdEwX6/8
是的。
所以如果攻击者有权创建函数:非DOS攻击也是可能的。
我接受 Laurenz Albe 的回答,但是:是否可以在没有功能的情况下进行非 DOS 攻击?
想法?
【问题讨论】:
-
一个经验法则是,如果用户可以传递被解释为代码的任意文本,那么您就有潜在的 SQL 注入,因此不安全。您总是需要清理用户输入数据。
-
@TedKleinBergman 问题不在于一般准则,而在于如何利用此类漏洞。能否举例说明如何利用此类漏洞?
-
我明白了。我的意思是回答您发布的问题是否安全。如果用户可以传递被解释为代码的任意文本,那么无论如何它都是不安全的。即使你找不到漏洞。即使你证明不存在这样的东西,它仍然不安全,因为它是一个可能迟早会打开的洞。