SQL-инъекция в PL / SQL - миф или факт? - PullRequest
0 голосов
/ 29 августа 2018

Я пытаюсь взломать мой код 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 голосов
/ 29 августа 2018

Если вы хотите добиться успеха при внедрении SQL, ваш оператор SELECT должен быть указан в виде символьной строки, к которой вы объединяете строку идентификатора документа, которая содержит условие, которое нужно добавить. Вот ваш код, переписанный:

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;
0 голосов
/ 29 августа 2018

Пример:

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
0 голосов
/ 29 августа 2018

На самом деле это не динамическое утверждение, поэтому оно не уязвимо для инъекции.

Если вы построили эту строку из внешнего интерфейса с конкатенацией строк p_document_id вне SQL-запроса, а затем отправили его в SQL, он был бы уязвим, но вы не можете выполнить инъекцию в самом SQL-запросе затем запускается строка, то есть динамический запрос, который у вас не выполняется)

Динамический запрос, уязвимый для внедрения, выглядел бы больше как;

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

И вы можете ввести, передавая как someUserInput что-то вроде

' OR 1=1; --
...