SQL 在 PL/SQL 中注入 - 神话还是事实?
SQL Injection in PL/SQL - myth or fact?
我正在尝试破解我的 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; -- ');
但是我们无法select所有记录。你能告诉我我做错了什么吗?
这实际上不是动态语句,因此不容易受到注入攻击。
如果您从 SQL 查询之外的 p_document_id 的字符串连接的前端构建此字符串 - 然后将其发送到 SQL,它将很容易受到攻击,但是你不能在 SQL 查询本身中进行注入(除非构建一个字符串然后 运行 它,即一个动态查询,而你的查询没有这样做)
易受注入攻击的动态查询看起来更像;
EXECUTE IMMEDIATE 'SELECT * FROM DOCUMENTS WHERE DOCUMENT_ID = ''' + someUserInput + ''''
你可以通过传递 someUserInput 来注入
' OR 1=1; --
如果你想在 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;
一个例子:
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
我正在尝试破解我的 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; -- ');
但是我们无法select所有记录。你能告诉我我做错了什么吗?
这实际上不是动态语句,因此不容易受到注入攻击。
如果您从 SQL 查询之外的 p_document_id 的字符串连接的前端构建此字符串 - 然后将其发送到 SQL,它将很容易受到攻击,但是你不能在 SQL 查询本身中进行注入(除非构建一个字符串然后 运行 它,即一个动态查询,而你的查询没有这样做)
易受注入攻击的动态查询看起来更像;
EXECUTE IMMEDIATE 'SELECT * FROM DOCUMENTS WHERE DOCUMENT_ID = ''' + someUserInput + ''''
你可以通过传递 someUserInput 来注入
' OR 1=1; --
如果你想在 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;
一个例子:
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