【问题标题】:Execute query only if it is select statement. How?只有当它是 select 语句时才执行查询。如何?
【发布时间】:2014-11-11 08:35:03
【问题描述】:
string sqlQuery = "unknown";

我需要编写一个接收 sql 查询作为参数的函数,例如sqlQuery。我只想在它是 select 语句并返回数据时执行它。在其他情况下,如果参数sqlQuery 包含删除、更新或截断,函数应该返回null。

我想知道是否有办法在不解析参数sqlQuery 的内容的情况下实现这一点。 我想使用 c sharp 进行 oracle 查询来做到这一点。

任何提示。谢谢。

更新:

  1. 这应该适用于具有所有权限的所有类型的用户。

【问题讨论】:

  • SQL 注入在这里非常有用且准确...如果您不想关心它,请忽略讨论的那一部分,但请记住,我们是一个社区,不仅为您说话,但对于我们所有人。
  • 感谢大家花时间回答我的问题。

标签: c# oracle


【解决方案1】:

在仅具有选择权限的用户的上下文中运行查询。任何其他类型的查询都会出错。

【讨论】:

    【解决方案2】:

    SET TRANSACTION READ ONLY,然后执行字符串。如果它试图修改数据,它将产生 ORA-01456 错误。你可以捕获它并返回任何你想要的东西。

    【讨论】:

    • 您可以执行一个执行 COMMIT 或 ROLLBACK 作为其第一个操作的 PL/SQL 块,但它仍然比许多选项更安全
    • 嗯,如果他们在请求中运行另一个 SET TRANSACTION 语句呢?
    【解决方案3】:

    如果您确实必须使用将在数据库上操作的构造字符串,您应该使用 DBMS_ASSERT 数据库包来确保您有一个不受 SQL 注入影响的纯查询。 Oracle 网站上有一篇关于 here 的好论文。

    基础是:

    • 仅授予必要的最低权限,例如仅授予用户“选择”,如先前回复中所述。然后只在最少必要的一组表上。视图在限制访问方面非常有用。
    • 尽可能使用绑定变量。
    • 如果不能使用绑定变量,请使用 DBMS_ASSERT 检查语句的纯度

    【讨论】:

      【解决方案4】:

      您可能可以在字符串中搜索“update”、“delete”、“truncate”等关键字以及您可以在表上执行 ddl 或 dml 的所有其他方式,但它很容易出错。您必须消除查询中可能包含这些关键字的字符串,并且您必须考虑很多关键字。

      如果你的要求是返回null,为什么不给必要对象的select权限,遇到Insufficient Privileges错误返回null呢?

      http://download.oracle.com/docs/cd/E11882_01/server.112/e17069/strms_trapply.htm#STRMS1065

      【讨论】:

      • 只是为了强调“它非常容易出错”——任何聪明的黑客都可以通过 SQL 注入攻击轻易地破坏你的系统。这种方法(允许将原始 sql 传递到系统中,更不用说连接字符串或诸如此类的东西)可能非常危险。
      【解决方案5】:

      我不允许客户端指定 SQL 选择字符串。可能的攻击媒介太多。

      你考虑过使用 Linq 吗?调用者可以传递一个Func<T, bool>,它可以传递给一个Where 子句。由于 Linq 会为您生成 select 语句,因此不可能出现非 select 语句。

      【讨论】:

      • linq 是否与 Oracle 一起使用?并非每个功能都是为客户开发的。 :)
      • 很公平。不过,我看不出这会如何影响这种方法。这是我们在应用程序中实现用于搜索的 DSL 的方式。有一个子句生成器接受 UI 输入并将其转换为 Predicate<T>,还有另一个使用 Linq to EF 执行查询的类。
      【解决方案6】:

      请记住,SELECT column FROM table FOR UPDATE 仍然会对该表的每一行进行排他锁。而且它只需要 SELECT 权限(不需要 INSERT、UPDATE 或 DELETE)。

      【讨论】:

        【解决方案7】:

        您可以使用 ADO.NET SqlCommand http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.aspx。它具有用于选择类型查询的 ExecuteReader 方法和用于其他 sql 表达式的 ExecuteNonQuery 方法,您可以设置 CommandText 字符串属性。如果我是对的,如果查询不是 ExecuteReader 中的选择,则会引发异常,但您必须检查它。

        【讨论】:

        • 这是一个很好的答案,不过您必须使用该命令的 oracle 版本。
        【解决方案8】:
        string sqlQuery = "("+evil_sql+")";
        

        只有子查询可以以括号开头。这将停止 DML、DDL 和 Gary 提到的 FOR UPDATE 问题。您仍然必须执行所有操作,只需捕获所有错误。我在一个面向公众的网站上完成了这项工作,没有任何问题。

        即使您的用户没有直接获得任何授权,您也需要检查是否有不必要的 PUBLIC 授权。当然,还要为您的系统打补丁。可以在 SELECT 中调用的函数中存在漏洞。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-10-27
          • 2019-08-08
          • 1970-01-01
          • 1970-01-01
          • 2014-06-25
          • 2011-06-11
          • 1970-01-01
          相关资源
          最近更新 更多