繁体   English   中英

私有查询方法会增加SQL注入攻击风险吗?

[英]Does a private query method increase SQL injection attack risk?

我曾经有人指出,使用私有方法处理由单个类完成的所有查询的查询执行会增加SQL注入攻击的风险。

此方法的示例可能如下所示(如下所示)。 我省略了一些细节,以免分散任何人的注意力。

如果您想谈谈实施,请随时在评论中。 安全审查没有评论该方法的内容,但主要是它不应该是自己的方法。

注意,queryText是从包含预准备语句的SQL文本的受保护静态最终字符串生成的。 准备好的语句文本中的?是使用PreparedStatement的setString(或set whatever)方法设置的。 在预准备语句中设置的变量尽可能强类型地进入调用方法。

然后将queryText传递给私有方法。

    private ResultSet executeQuery(PreparedStatement stmt) throws SQLException {

    // Declare result set variable
    try{
        try{
            // execute statement and store in variable
        }
        catch(SQLException se){
            // log, close connection, do any special processing, rethrow se
        }

    }
    finally{
                    // This finally block is here to ensure the connection closes if
                    // some special processing (not shown) in the other try generates a runtime exception
        // close connection and statement properly
    }
    // return result set
}

推荐的替代方法是在执行查询的每个方法中基本内联相同的代码。

我没有将此发布到security.stackexchange.com,因为我认为它有资格作为特定的安全编程问题。

我认为没有理由为什么将这个代码(从私有方法)复制到许多类中会增加任何保护。 是吗?

谢谢

如果此方法执行的查询具有SQL注入所需的成分,那么无论private/public方法如何,它都会产生影响。

这个私有方法将由一些公共方法调用,该方法从用户(或)数据库获取输入。 如果该输入是恶意的,则私有方法无法阻止它执行。

不要使用原始SQL字符串,总是更好地使用预准备语句。

拥有一个执行查询的中心(不重复)位置是个主意。 从代码可维护性和安全性角度来看都是如此。 为什么代码可能多次出现问题? 这只意味着你必须多次维护它!

对我来说似乎很重要(以及通过编辑问题而改变的)是,应该尽可能地用它来执行手工构建的SQL字符串。

例如,您可以使用自定义枚举替换任何String参数(您最初使用,但从那时PreparedStatement替换):

public enum SQLQuery {
  QUERY1("SELECT foo FROM BAR", 0),
  QUERY2("SELECT foo from BAR where baz = ?"; 1);

  private final String sql;
  private final int argumentCount;

  private SQLQuery(final String sql, final int argumentCount) {
    this.sql = sql;
    this.argumentCount = argumentCount;
  }

  public String getSQL() {
    return sql;
  }

  public int getArgumentCount() {
    return argumentCount;
  }
}

然后你可以像这样编写你的方法:

public ResultSet executeQuery(SQLQuery query, Object... arguments) {
  // implementation left as an exercise for the reader
}

通过这种方式,您可以非常确定您(或团队中的任何其他人)不会意外地将自构建String传递给您的方法。

如果有必要,可以扩展此方法以处理不同的参数类型,但对于许多情况,使用setObject()工作正常。

为了提高模块性,您可以从该枚举中提取接口,并允许多个枚举定义查询(例如,如果项目中有单独的模块)。 但这有一个缺点,即恶意(或无能)的开发人员可以使用SQLQuery动态非枚举实现来将他们手动构建的SQL字符串放入该方法中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM