2

我在这里阅读 PostgreSql 文档,并遇到了以下代码片段:

EXECUTE 'SELECT count(*) FROM mytable WHERE inserted_by = $1 AND inserted <= $2'
   INTO c
   USING checked_user, checked_date;

文档指出“这种方法通常比将数据值作为文本插入命令字符串更可取:它避免了将值转换为文本并返回的运行时开销,而且它更不容易受到 SQL 注入攻击,因为存在无需引用或转义”。

你能告诉我这段代码是如何容易发生 SQL 注入的吗?

编辑:在我使用过的所有其他 RDBMS 中,这将完全防止 SQL 注入。PostgreSql 有什么不同的实现方式?

4

3 回答 3

2

快速回答是,它本身并不容易受到 SQL 注入的影响,据我了解,您的问题是您在问我们为什么不这么说。因此,由于您正在寻找可能导致 SQL 注入的场景,请考虑这mytable可能是一个视图,因此它背后可能有其他功能。这些函数可能容易受到 SQL 注入的攻击。

所以你不能看一个查询就断定它绝对不容易受到 SQL 注入的影响。您可以做的最好的事情是表明在提供的级别上,您的应用程序的这个特定级别不会在此处引发 sql 注入问题。

这是一个很可能发生 sql 注入的示例。

CREATE OR REPLACE FUNCTION ban_user() returns trigger
language plpgsql security definer as
$$
begin
    insert into banned_users (username) values (new.username);
    execute 'alter user ' || new.username || ' WITH VALID UNTIL ''YESTERDAY''';
    return new;
end;

请注意,效用函数不能按照您的指示进行参数化,而且我们忘记了quote_ident()环绕new.username,从而使该字段易受攻击。

CREATE OR REPLACE VIEW banned_users_today AS
SELECT username FROM banned_users where banned_date = 'today';

CREATE TRIGGER i_banned_users_today INSTEAD OF INSERT ON banned_users_today
FOR EACH ROW EXECUTE PROCEDURE ban_user();

EXECUTE 'insert into banned_users_today (username) values ($1)'
USING 'postgres with password ''boo''; drop function ban_user() cascade; --';

所以不,即使在任何可以使用的地方使用它也不能完全解决问题。而正确使用quote_literal()quote_ident()并不总能解决问题。

问题是问题总是比您正在执行的查询低。

于 2013-11-04T10:47:42.830 回答
1

绑定参数可以防止垃圾操纵语句做任何事情,而不是做它打算做的事情。

这保证了没有 Postgres 错误的 SQL 注入攻击的可能性。(有关可能出错的示例,请参阅H2C03 的链接。)

我想如果出现这样的事情,“不太容易受到 SQL 注入攻击”就相当于 CYA 的废话。

于 2013-11-01T13:47:18.843 回答
0

SQL 注入通常与pastebin.com上的大型数据转储相关联,即使示例使用了连接而不是变量,这种情况也不会在这里起作用。这是因为这COUNT(*)将汇总您试图窃取的所有数据。

但我可以想象任意记录的计数将是足够有价值的信息的场景——例如竞争对手的客户数量、销售产品的数量等。实际上回想一下一些非常棘手的盲 SQL 注入方法,它可能会构建一个查询,使用仅 COUNT 将允许从数据库中迭代地恢复实际文本。

在足够旧且配置错误以允许分隔符的数据库上利用它也会更容易;,在这种情况下,攻击者可能只是附加一个完全独立的查询。

于 2013-11-01T14:35:49.300 回答