4

当我在 PostgresSQL 中使用类似的东西时,我想知道我是否可以安全地防止 SQL 注入:

CREATE or REPLACE FUNCTION sp_list_name( VARCHAR )
RETURNS SETOF v_player AS '
   DECLARE
      v_start_name ALIAS FOR $1;
      r_player  v_player%ROWTYPE;
      v_temp VARCHAR;
   BEGIN
      v_temp := v_start_name || ''%'';
      FOR r_player IN
         SELECT first_name, last_name FROM v_player WHERE last_name like v_temp
      LOOP
         RETURN NEXT r_player;
      END LOOP;
      RETURN;
   END;
' LANGUAGE 'plpgsql' VOLATILE;

我想用这个函数列出以字母开头的玩家名字。

select * from sp_list_name( 'A' );

给我姓氏以 A 开头的玩家。

我试图注入sql

select * from sp_list_name( 'A; delete from t_player;--' );
select * from sp_list_name( '''; delete from t_player;--' );

我安全吗?

哪种情况可以注射?

问候

4

7 回答 7

7

就您的过程而言,您似乎很安全,因为 SP 中的变量不会扩展为代码,但如果您在应用程序代码SELECT * FROM sp_list_name(?);中不使用像 " "这样的参数化查询,您仍然可以暴露自己。像“ ”这样的东西可能会被用户传递“ ”的开始名称所破坏。因此,请使用参数化查询或健全性检查程序中的输入。SELECT * FROM sp_list_name('$start_name');');delete from t_player where last_name NOT IN ('

注意: 对于其他人,请注意存储过程中的变量即使包含 ' 或 ;,也不会扩展为代码(不包括将其传递给EXECUTE,您将使用它quote_literal,而不是手动replace函数)所以替换 ; or ' 是完全没有必要的(在存储过程中,使用它的应用程序当然是另一回事)并且会阻止您始终找到“ tl;dr”或“ O'Grady”团队。

Leo Moore,Karl,LFSR 咨询v_temp_name在存储过程中不会扩展为 SP 中的代码(没有EXECUTE),需要在应用程序中完成检查,而不是 SP(或者 OP 可以只使用参数化查询而是在他们的应用程序代码中)。其他人的建议类似于担心

my $bar = "foo; unlink('/etc/password');"; 
my $baz = $bar;

在没有评估的情况下实际运行取消链接。

于 2009-03-09T21:43:14.883 回答
6

防止 sql 注入的规则 #1:清理来自您无法信任/无法控制的某人/某事的所有输入。

问题本身不在于数据库代码,而在于执行这些语句的应用程序。

于 2009-03-09T20:40:57.983 回答
4

防止 SQL 注入的正确方法是通过白名单* - 设置您要接受的字符并将它们过滤掉。

错误的方法是黑名单- 黑名单不接受哪些字符会导致麻烦,因为你无法跟上攻击者的步伐。有一些方法可以通过 ASCII 表、转义字符等绕过黑名单。

此外,这里有一个不错的备忘单,可以在您的网站上试用。运行一些测试并尝试让事情失败。

*在应用程序中,而不是 DB(感谢 James)

于 2009-03-09T22:19:47.060 回答
1

您不是为自己生成 SQL,所以这看起来很安全(对我来说)。

我不知道您调用存储过程的数据来自哪里。所以你仍然必须防止缓冲区溢出等。

于 2009-03-09T20:39:46.800 回答
1

参考。白名单。如果遵循某些其他条件,这是可以的。将所有输入分解为最简单的形式是绝对必要的,因此不要只检查 SQL 查询名称、单引号等。它们可以使用其他字符集表示或编码,而这正是白名单的一部分而不是专门的SQL 关键字本身。

我正在为一个允许用户名/密码访问受保护资源的特定客户工作(这最终可以让您获得进入机场安全部分的访问通行证!)。您可以通过输入 ' 绕过登录字段,然后从那里构建 SQL 查询以检索用户帐户和密码。

问题是客户已经花了 20 万英镑与一家似乎从未做过 Web 开发的供应商建立网站。修复是另外 6 万英镑,这是一个 validate func(),它只检查 union、select、have et al 关键字。当被问及他们为 canicolisation /encoding 做了什么(我必须随后解释)时,这是风滚草时间。

开发室和(昂贵的)项目被封杀了。

于 2009-03-11T13:05:16.967 回答
-1

您可以考虑验证的内容

v_start_name
. 检查字符串中的分号、注释字符、等号等。记住要检查字符和十六进制值。请记住允许使用连字符的名称,例如“Smith-Brown”可能是可以接受的“Smith--Brown”可能是注入。

如果不熟悉 SQL 注入中的十六进制,以下是快速介绍

http://www.arejae.com/blog/sql-injection-attack-using-t-sql-and-hexadecimal.html

http://www.securityfocus.com/infocus/1768

宣布
      v_start_name 别名 1 美元;
      r_player v_player%ROWTYPE;
      v_temp VARCHAR;
   开始
      -- 新的伪代码在这里
      如果 v_start_name 有错误字符退出并显示错误消息
      -- 在此结束伪代码
      v_temp := v_start_name || ''%'';
      FOR r_player IN
         SELECT first_name, last_name FROM v_player WHERE last_name like v_temp
      环形
         返回下一个 r_player;
      结束循环;
      返回;
   结尾;

问候卡尔

于 2009-03-09T21:57:56.283 回答
-2

只需对您的 v_start_name 进行替换即可摆脱“;” 等,即

v_clean_name VARCHAR;
Select v_clean_name = Replace(v_start_name,';','');

这将取代 ; 用空格挫败 SQL 注入攻击

有关详细信息,请参阅PostgresSQL 中的字符串函数

正如 LFSR Consulting 所评论的那样。最好是白名单(即不要处理任何带有无效字符的输入,例如';')而不是黑名单(即尝试清理数据,因为用户也可能对您的替换进行 SQL 注入攻击)。

有关更多信息,请查看SQL 注入攻击

于 2009-03-09T22:01:50.080 回答