我正在阅读PostgreSql文档here,并遇到以下代码段:
EXECUTE 'SELECT count(*) FROM mytable WHERE inserted_by = $1 AND inserted <= $2'
INTO c
USING checked_user, checked_date;
文档指出“这种方法通常比将数据值作为文本插入命令字符串更好:它避免了将值转换为文本和返回的运行时开销,而 则更少容易受到SQL注入攻击 ,因为不需要引用或转发“。
你能告诉我这段代码是如何容易进行SQL注入的吗?
我使用过的所有其他RDBMS中的编辑将完全阻止SQL注入。在PostgreSql中以不同的方式实现了什么?
答案 0 :(得分:2)
快速回答是它本身并不容易出现SQL注入,因为我理解你的问题,你在问我们为什么不这么说。因此,既然您正在寻找可能导致SQL注入的场景,请考虑mytable
可能是一个视图,因此可能有其他功能。这些函数可能容易受到SQL注入的攻击。</ p>
因此,您无法查看查询并得出结论,它绝对不会受到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()
并不能始终解决问题。
问题是问题总是低于您正在执行的查询。
答案 1 :(得分:1)
绑定参数可以防止垃圾操纵语句执行除了预期之外的任何操作。
这保证了SQL注入攻击不会出现Postgres错误。 (有关可能出错的示例,请参阅H2C03's link。)
我认为“更不容易发生SQL注入攻击”相当于CYA的措辞,这样的事情就会出现。
答案 2 :(得分:0)
SQL注入通常与 pastebin.com 上的大型数据转储相关联,并且此类方案在此处不起作用,即使该示例使用的是contatenation而非变量。这是因为COUNT(*)
将聚合您试图窃取的所有数据。
但我可以想象任意记录的计数将是足够有价值的信息 - 例如竞争对手的客户数量,销售产品的数量等。实际上,回想起一些非常棘手的盲目SQL注入方法,有可能构建一个单独使用COUNT的查询,可以迭代地从数据库中恢复实际文本。
在数据库上利用足够旧和错误配置以允许;
分隔符也会容易得多,在这种情况下,攻击者可能只是附加一个完全独立的查询。