有问题的函数
我正在探索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
为整数
DB Fiddle for the: 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');
将返回"查询错误:Error: cannot open multi-query plan as cursor">.
如果UPDATE
/INSERT
/DELETE
存在漏洞,我没有找到利用的方法。
那么我们可以得出这样的结论:这个函数实际上是安全的吗?
如果是,那么为什么?
更新。可能的攻击计划
也许我没说清楚:我不是在问一般的指导方针,而是在问实验性的漏洞利用,或者证明这种漏洞不可能被利用。
DB Fiddle for this: https://www.db-fiddle.com/f/vF6bCN37yDrjBiTEsdEwX6/4(或者你可以提供其他当然)
我的结论到目前为止
。如果_orderby
有部件,这种攻击是可能的:
- sql代码抑制第一个
SELECT
的输出 - 做一些有害的事情
select * from pg_class
使其满足RETURNS SETOF pg_class
。
SELECT * FROM paginated_class(_orderby:='relname; DELETE FROM my_table; SELECT * FROM pg_class')
2和3很容易。我不知道怎么做第一部分。
这会生成:"error: cannot open multi-query plan as cursor">
B。如果不能抑制第一个SELECT
:
- 每个postgresql函数都在单独的事务中工作
- 由于错误,此事务将被回滚 Oracle中没有自治事务。非事务性操作
- :我只知道与序列相关的操作
- DML或DDL是事务性的
?我们能得出这样的结论吗?
还是我错过了什么?
更新2。使用准备函数进行攻击
从答案https://stackoverflow.com/a/69189090/1168212
。通过昂贵的计算实现拒绝服务攻击是可能的
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攻击?
想法?
不,那不安全。攻击者可以通过_orderby
参数将任何代码放入ORDER BY
子句中。
例如,您可以传递任意子查询,只要它只返回单行:(SELECT max(i) FROM generate_series(1, 100000000000000) AS i)
。如果查询的开销足够大,那么很容易将其用于拒绝服务攻击。或者,像这个例子一样,您可以在临时文件中造成(短暂的)空间不足的情况。
如果你把一个有副作用的函数放进ORDER BY
子句,你也可以修改数据。