PL / SQL中的SQL注入-神话还是事实?

时间:2018-08-29 11:45:20

标签: sql plsql code-injection

我正在尝试破解我的PL / SQL代码。我们创建打开并获取游标的PL / SQL过程。按照我们的标准,我们确实创建了一个动态SQL语句,但是我们无法注入OR 1 = 1条件。

我确实准备了一个http://sqlfiddle.com/#!4/a62a3/5演示,您可以在其中尝试插入代码。

CREATE FUNCTION get_documents (p_document_id IN DOCUMENTS.DOCUMENT_ID%TYPE)
    RETURN SYS_REFCURSOR
AS
    p_rs SYS_REFCURSOR;
BEGIN
    DBMS_OUTPUT.PUT_LINE('------ INPUT VALUES ------');
    DBMS_OUTPUT.PUT_LINE('p_document_id: ' || p_document_id);

    OPEN p_rs FOR 
        SELECT DOCUMENT_ID, '(' || MY_FIELD || ')' FROM DOCUMENTS WHERE DOCUMENT_ID = '' ||  p_document_id  || '';
    RETURN p_rs;
END;

我们尝试将代码插入p_document_id参数中。我们将其设置为:

 document_refcur_local:=get_documents('10'' OR 1=1; -- ');

,但我们无法选择所有记录。您能告诉我我做错了什么吗?

3 个答案:

答案 0 :(得分:5)

这实际上不是动态语句,因此不容易受到注入攻击。

如果您是使用SQL查询之外的p_document_id的字符串串联从前端构建此字符串的,然后将其发送到SQL,则该字符串很容易受到攻击,但是您不能在SQL查询本身中进行注入(除非构建一个字符串然后运行它,即您不执行的动态查询)

容易注入的动态查询看起来更像

EXECUTE IMMEDIATE 'SELECT * FROM DOCUMENTS WHERE DOCUMENT_ID = ''' + someUserInput + ''''

您可以通过传递诸如someUserInput之类的东西来注入

' OR 1=1; --

答案 1 :(得分:4)

如果要成功进行SQL注入,则需要将SELECT语句指定为字符串,在该字符串中连接文档ID字符串,该字符串包含要添加的条件。这是您的代码,已重写:

CREATE OR REPLACE FUNCTION GET_DOCUMENTS (p_document_id IN VARCHAR2)
  RETURN SYS_REFCURSOR
IS
  p_rs SYS_REFCURSOR;
BEGIN
  DBMS_OUTPUT.PUT_LINE('------ INPUT VALUES ------');
  DBMS_OUTPUT.PUT_LINE('p_document_id: ' || p_document_id);

  OPEN p_rs FOR 
    'SELECT DOCUMENT_ID, ''('' || MY_FIELD || '')'' FROM DOCUMENTS WHERE DOCUMENT_ID = ''' ||  p_document_id  || '''';

  RETURN p_rs;
END GET_DOCUMENTS;

答案 2 :(得分:2)

一个例子:

create table documents (id, value) as 
(
    select 1, 'x' from dual union all
    select 2, 'x' from dual union all
    select 3, 'y' from dual
)

一个易受攻击的功能

create or replace function countDocs(pValue IN varchar2) return number is
    vRetVal number;
begin
    execute immediate 'select count(*) from documents where value = ''' || pValue || ''''
    into vRetVal;
    return vRetVal;
end;

您可以做什么:

SQL> select countDocs('y') from dual;

COUNTDOCS('Y')
--------------
             1

SQL> select countDocs('y'' or ''a''=''a') from dual;

COUNTDOCS('Y''OR''A''=''A')
---------------------------
                          3

安全的方法可能是使用绑定变量:

create or replace function countDocsSafe(pValue IN varchar2) return number is
    vRetVal number;
begin
    execute immediate 'select count(*) from documents where value = :bindVar'
    into vRetVal
    using pValue ;
    return vRetVal;
end;

哪个给:

SQL> select countDocsSafe('y') from dual;

COUNTDOCSSAFE('Y')
------------------
                 1

SQL> select countDocsSafe('y'' or ''a''=''a') from dual;

COUNTDOCSSAFE('Y''OR''A''=''A')
-------------------------------
                              0