我们有数千个包含map_products过程的oracle包。
我们有一个表,用于存储客户希望map_products运行的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_replace来允许SQL注入?
更具体地说,我们希望确保不能传入分号。上述内容是否确保?
答案 0 :(得分:3)
使用字符串:
DRDROPOP your_package_name
替换只会在您离开时替换DROP
:
DROP your_package_name
答案 1 :(得分:2)
我建议使用白名单而不是正则表达式。
根据系统表检查输入。
select object_name
from dba_objects
where owner = 'SYS'
and object_type = 'PACKAGE'
and object_name = :p_string;
如果找不到匹配项,那么它不是已知的包,所以不要使用它。
答案 2 :(得分:0)
我认为删除;将是避免sql注入的第一种方法。但请考虑这种可能的策略:
你已经说过你的做法很危险。我只是想确保你知道一个名字包含你的正则表达式中的任何单词的包(例如,salaryUPDATEr)会有问题
答案 3 :(得分:0)
正如上面的其他海报所评论,黑名单将很容易绕过。
使用白名单验证始终是理想选择。如果这不可行,并且由于这是Oracle,最好的选择是使用内置的dbms_assert.enquote_name - 这可以安全地引用该值(并检查嵌入的引号)。
有关DBMS_ASSERT的更多信息,请参阅: https://oracle-base.com/articles/10g/dbms_assert_10gR2#ENQUOTE_NAME
或者有关防止SQL注入的更深入的内容,请参阅: http://www.oracle.com/technetwork/database/features/plsql/overview/how-to-write-injection-proof-plsql-1-129572.pdf
答案 4 :(得分:0)
您可以使用DBMS_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
您可以在link上找到更多信息。