Oracle 使用regexp\u replace防止SQL注入

Oracle 使用regexp\u replace防止SQL注入,oracle,sql-injection,dynamic-sql,Oracle,Sql Injection,Dynamic Sql,我们有数千个包含map_products过程的oracle软件包 我们有一个表,用于存储客户希望为其运行map_产品的oracle软件包列表 运行它们的进程使用动态SQL,如下所示: select sanitize(package_name) into v_package_name from custom_plugins where id = p_id; execute immediate ' begin '||v_package_name||

我们有数千个包含map_products过程的oracle软件包

我们有一个表,用于存储客户希望为其运行map_产品的oracle软件包列表

运行它们的进程使用动态SQL,如下所示:

select sanitize(package_name) 
  into v_package_name 
from   custom_plugins 
where  id = p_id;

execute immediate '
      begin 
          '||v_package_name||'.map_products; 
      end;
  ';
上面的清理功能旨在防止SQL注入

以下是函数定义:

function sanitize(p_string in varchar2) return varchar2
is
begin
    return regexp_replace(upper(p_string), 
              '(ALTER|MERGE|CREATE|SELECT|INSERT|UPDATE|DELETE|MODIFY|DROP|ENABLE|DISABLE|;)');
end;
现在我们意识到,从长远来看,这是一种危险的做法,并计划重做整个过程。然而,就目前而言,是否有任何简单的方法可以绕过这个regexp_替换来允许SQL注入

更具体地说,我们希望确保分号不能传入。上述内容是否确保?

使用字符串:

DRDROPOP your_package_name
“替换”只会在留给您以下内容时替换掉:

DROP your_package_name
使用字符串:

DRDROPOP your_package_name
“替换”只会在留给您以下内容时替换掉:

DROP your_package_name
我建议用白名单代替正则表达式

对照系统表检查输入

select object_name
from dba_objects
where owner = 'SYS'
and object_type = 'PACKAGE'
and object_name = :p_string;
如果找不到匹配项,则它不是已知的包,因此不要使用它。

我建议使用白名单而不是正则表达式

对照系统表检查输入

select object_name
from dba_objects
where owner = 'SYS'
and object_type = 'PACKAGE'
and object_name = :p_string;

如果您找不到匹配项,那么它不是已知的软件包,所以不要使用它。

我认为删除;将是避免sql注入的第一种方法。但请考虑这个可能的策略:

使用regexp从输入中提取一个有效的包名。例如,检查包名中是否有字母数字字符、或\或任何其他允许的字符,但不包括其他字符。 使用上一步的输出,检查包是否实际上是数据库中查询user_对象的对象。 此时,您将拥有一个有效的包名(如果有的话),并且可以在动态语句中使用它。
你已经说过你的方法很危险。我只是想确保您知道,如果一个包的名称包含您的regexp salaryUPDATEr中的任何单词,那么这个包就会出现问题,例如,我认为删除;将是避免sql注入的第一种方法。但请考虑这个可能的策略:

使用regexp从输入中提取一个有效的包名。例如,检查包名中是否有字母数字字符、或\或任何其他允许的字符,但不包括其他字符。 使用上一步的输出,检查包是否实际上是数据库中查询user_对象的对象。 此时,您将拥有一个有效的包名(如果有的话),并且可以在动态语句中使用它。
你已经说过你的方法很危险。我只是想确保您知道,如果一个包的名称包含您的regexp salaryUPDATEr中的任何单词,那么这个包可能会有问题,例如

,因为上面的其他海报评论说,黑名单很容易绕过

使用白名单验证总是理想的。如果这是不可行的,而且这是Oracle,那么最好的选择是使用内置的dbms_assert.enquote_名称-这可以安全地对值进行加引号,并检查嵌入的引号

有关DBMS_断言的更多信息,请参阅:

有关防止SQL注入的更多详细信息,请参阅:

正如上面的其他海报所评论的,黑名单将很容易被绕过

使用白名单验证总是理想的。如果这是不可行的,而且这是Oracle,那么最好的选择是使用内置的dbms_assert.enquote_名称-这可以安全地对值进行加引号,并检查嵌入的引号

有关DBMS_断言的更多信息,请参阅:

有关防止SQL注入的更多详细信息,请参阅: 您可以使用DBMS\u ASSERT包。 自10g版本以来,Oracle提供了DBMS_ASSERT包。它包含可用于验证用户输入的函数

SQL注入尝试示例

SELECT description FROM products WHERE name=DBMS_ASSERT.ENQUOTE_LITERAL('abc'' OR 1=1--');

ERROR RETURNED.

ORA-06502: PL/SQL: numeric or value error
您可以在上找到更多信息。

您可以使用DBMS\u ASSERT包。 自10g版本以来,Oracle提供了DBMS_ASSERT包。它包含可用于验证用户输入的函数

SQL注入尝试示例

SELECT description FROM products WHERE name=DBMS_ASSERT.ENQUOTE_LITERAL('abc'' OR 1=1--');

ERROR RETURNED.

ORA-06502: PL/SQL: numeric or value error

您可以在上找到更多信息。

这可能有助于OP或未来的读者理解您的意思。SQL注入之类的东西不一定意味着带有分号的东西。例如,…这很酷,但是,在这种情况下,这不会造成伤害,因为这将导致:删除无效声明中的package_name.map_products。这可能有助于OP或未来的读者理解您的意思。SQL注入之类的东西不一定意味着带有分号的东西。例如,…这很酷,但是,在这种情况下,这不会造成任何伤害,因为这将导致:删除无效语句中的package_name.map_products。