带有 DBMS_ASSERT 的 Oracle SQL 注入块

Posted

技术标签:

【中文标题】带有 DBMS_ASSERT 的 Oracle SQL 注入块【英文标题】:Oracle SQL Injection Block with DBMS_ASSERT 【发布时间】:2014-02-19 18:04:09 【问题描述】:

此代码触发错误

query_string := 'SELECT '||dbms_assert.sql_object_name(trim(both ' ' from return_field))|| ' FROM '||dbms_assert.schema_name(trim(两个 ' ' 来自 from_schema))|| '.'||dbms_assert.sql_object_name(trim(来自 from_table) 的两个'')|| ' WHERE '||dbms_assert.sql_object_name(key_field) || ' = '||key_value; 立即执行 query_string 到 return_result;

无效的 sql 对象。

从文档中我觉得表中的任何对象都是 sql 对象?? 这里有什么问题?

考虑 oracle 10g 中的以下函数

考虑10g上下文中的以下函数

创建或替换函数 scott.tab_lookup (key_field CHAR, 键值字符, from_schema CHAR, from_table CHAR, return_field CHAR, return_type CHAR) 返回 VARCHAR2 是 结果_a varchar2(1000); 查询字符串 VARCHAR2(4000); /*版本 0.5*/ 开始 query_string := 'SELECT '||dbms_assert.qualified_sql_name(trim(from_table||'.'||return_field))|| ' FROM '||dbms_assert.schema_name(trim(from_schema))|| '.'||dbms_assert.sql_object_name(trim(from_table))|| ' WHERE '||dbms_assert.qualified_sql_name(from_table||'.'||key_field) || ' = '||key_value; IF(return_type = 'SQL') 那么 result_a := 查询字符串; 别的 立即执行查询字符串 --使用键值 进入结果_a; 万一; 返回(结果_a); 例外 什么时候 NO_DATA_FOUND 那么 返回(空); 什么时候 TOO_MANY_ROWS THEN RETURN('**ERR_DUPLICATE**'); 当其他人 然后 /* ORA-44001 INVALID_SCHEMA_NAME ORA-44002 INVALID_OBJECT_NAME ORA-44003 INVALID_SQL_NAME ORA-44004 INVALID_QUALIFIED_SQL_NAME */ 如果 SQLCODE = -44001 那么 RETURN('*ERR_INVALID_SCHEMA*'); ELSIF SQLCODE = -44002 那么 RETURN('*ERR_INVALID_OBJECT*'); ELSIF SQLCODE = -44003 那么 RETURN('*ERR_INVALID_SQL_NAME*'); ELSIF SQLCODE = -44004 那么 RETURN('*ERR_INVALID_QALIFIED_SQLNAME*'); 万一; return ('*ERR_'||sqlcode); 结尾; /

我收到 ERR_INVALID_OBJECT

--获取生成的 SQL 作为值 从对偶中选择 scott.tab_lookup('ID',1,'TEST','TEST_TABLE','TEST_DESC','SQL'); - -要么- -- 获取从数据库字段返回的值 从对偶中选择 scott.tab_lookup('ID',1,'TEST','TEST_TABLE','TEST_DESC','');

我的桌子是这样的

测试表 ===================== 身份证号, TEST_DESC ===================== “11”,“测试 1” “12”,“测试 5000” '13' , '测试输入值' '14' , '垃圾值' '50' , '测试值 50'

此表在“TEST”模式中,我与 SCOTT 连接 并且 SCOTT 有 'GRANT SELECT on TEST.TEST_TABLE to scott'

我还是会出错

ERR_INVALID_OBJECT

【问题讨论】:

一般提示:Oracle 提供了非常清晰和具体的错误消息,这些错误消息以 ORA-##### 代码开头。请不要将其视为不相关的内容。 表示您作为参数提供给函数的任何内容都是无效的。我猜无法以这种方式检查列名 【参考方案1】:
query_string := 'SELECT '||dbms_assert.qualified_sql_name(trim(from_schema||'.'||from_table||'.'||return_field))|| 
                   ' FROM '||dbms_assert.schema_name(trim(from_schema))||
                        '.'||dbms_assert.sql_object_name(trim(from_table))||  
                  ' WHERE '||dbms_assert.qualified_sql_name(from_schema||'.'||from_table||'.'||key_field) || ' = '||key_value;



 EXECUTE IMMEDIATE query_string into return_result;

来自Docs..

ENQUOTE_LITERAL - 引用字符串文字 ENQUOTE_NAME - 用双引号将名称括起来 NOOP - 返回值而不进行任何检查 QUALIFIED_SQL_NAME - 验证输入字符串是合格的 SQL 名称 SCHEMA_NAME - 函数验证输入字符串是否为现有架构名称 SIMPLE_SQL_NAME - 验证输入字符串是简单的 SQL 名称 SQL_OBJECT_NAME - 验证输入参数字符串是现有 SQL 对象的限定 SQL 标识符

【讨论】:

所以列名中也需要模式名。 感谢您的支持。解决此问题后,我的下一步是将模式和列名的最大输入限制为 30 个字节,并且我还在考虑将返回类型添加为本地数据类型,如日期数字 varchar。 @shinobi92 那么您在问题中发布的错误是什么解决了?只是想确认一下。你提到的那个和它有什么不同? 不,它没有什么不同,我只是添加了异常处理,但我仍然得到与原始异常相同的异常,我可以说该函数不是抛出错误,而是返回错误+原因值。我的问题是正确和干净的输入,函数应该返回值而不是抛出异常 err_invalid_object 当你说“无法以这种方式检查列名”时,我觉得你是对的,任何解决方案? 是的,我不明白,因此我强调这是不可能的。当它在 SQL 引擎中运行时,它必须经过资格预审才能返回一些东西。不能是动态的.. 一个建议是始终使用 Varchar 并使用调用者模块中的一些逻辑对其进行解析

以上是关于带有 DBMS_ASSERT 的 Oracle SQL 注入块的主要内容,如果未能解决你的问题,请参考以下文章

带有查询的链接表在列名中包含“/”

带有数值的 SSIS 查找不起作用

映射数据类型 Oracle 和 C# 时出错

Oracle 存储过程 OUT 参数

如何确定 Oracle NUMBER 列的最大值和最小值?

Oracle APEX 中的卡片报告