Oracle - 为什么在存储过程中允许执行EXECUTE IMMEDIATE?

时间:2018-04-24 19:02:40

标签: sql oracle security stored-procedures sql-injection

如果存储过程旨在缓解SQL注入攻击,为什么存储过程中允许EXECUTE IMMEDIATE?接受以下问题的答案是将它们作为对抗此类攻击的一步:

  

什么是存储过程? https://stackoverflow.com/a/459531/3163495

     

“存储过程也具有安全优势,您可以授予   执行存储过程的权限,但用户不需要   对基础表具有读/写权限。这很好   反对SQL注入的第一步。“

...除非存储过程使用EXECUTE IMMEDIATE。

此PL / SQL代码返回产品说明(第二个参数)。

CREATE OR REPLACE PROCEDURE prodDescr(vname IN VARCHAR2, vresult OUT VARCHAR2) AS
vsql VARCHAR2(4000);
BEGIN
vsql := 'SELECT description FROM products WHERE name=''' || vname || '''';
EXECUTE IMMEDIATE vsql INTO vresult;
END;

恶意用户输入。

A' AND 1=2 UNION SELECT password FROM members WHERE username='admin

生成的查询。

SELECT description FROM products WHERE name='A' OR 1=2 UNION SELECT password FROM members WHERE username='admin'

执行查询后,攻击者会获取管理员密码。

正如您所看到的,虽然我们使用了存储过程,但攻击者仍然可以像使用PHP中的一些业务开发人员在没有清理输入的情况下连接某些SELECT语句一样轻松地利用漏洞。对我来说,向开发人员说存储过程有助于保护数据库安全,这似乎是非常误导。

2 个答案:

答案 0 :(得分:13)

执行立即仍然可以安全使用。这一切都归结为存储过程的逻辑。 concat使代码不安全而不是执行立即。

vsql := 'SELECT description FROM products WHERE name=''' || vname || '''';

应该使用绑定变量或dbms_assert调用。

  vsql := 'select count(1) from all_objects where owner = :1'
  EXECUTE IMMEDIATE vsql into vresult using vname ;

OR

 vsql := 'select count(1) from all_objects where owner ='||DBMS_ASSERT.ENQUOTE_LITERAL(vname);
  EXECUTE IMMEDIATE vsql into vresult  ;

在下面的完整示例中使用两种方法。第一个包含绑定,第二个包含DBMS_ASSERT。

SQL>declare
      v_in varchar2(2000);
      ret  varchar2(2000);
    begin
      v_in := 'KLRICE';
     EXECUTE IMMEDIATE 'select count(1) from all_objects where owner = :1' into ret using v_in ;
     dbms_output.put_line('First Object Count  : ' || ret);

     EXECUTE IMMEDIATE 'select count(1) from all_objects where owner ='||DBMS_ASSERT.ENQUOTE_LITERAL(v_in)  into ret ;

    dbms_output.put_line('Second Object Count  : ' || ret);
  end
SQL> /
First Object Count  : 74
Second Object Count  : 74


PL/SQL procedure successfully completed.

SQL> 

答案 1 :(得分:2)

存储过程不会保证数据库的安全。这从来都不是真的。

没有任何语言,框架或API可以确保您的数据库安全。

开发人员有责任编写安全的代码。

如果您以不安全的方式使用EXECUTE IMMEDIATE,那么您就有漏洞。

当您不使用存储过程时也是如此 - 如果使用任何应用程序语言编写动态SQL,则存在创建SQL注入漏洞的相同风险。