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

use*_*495 1 sql security oracle stored-procedures sql-injection

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

什么是存储过程? /sf/answers/32167201/

"存储过程还具有安全性,因为您可以向存储过程授予执行权限,但用户不需要对基础表具有读/写权限.这是针对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;
Run Code Online (Sandbox Code Playgroud)

恶意用户输入.

A' AND 1=2 UNION SELECT password FROM members WHERE username='admin
Run Code Online (Sandbox Code Playgroud)

生成的查询.

SELECT description FROM products WHERE name='A' OR 1=2 UNION SELECT password FROM members WHERE username='admin'
Run Code Online (Sandbox Code Playgroud)

执行查询时,攻击者获取管理员密码.

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

Kri*_*ice 13

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

vsql := 'SELECT description FROM products WHERE name=''' || vname || '''';
Run Code Online (Sandbox Code Playgroud)

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

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

要么

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

在下面的完整示例中使用两种方法.第一个有绑定,第二个用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> 
Run Code Online (Sandbox Code Playgroud)