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



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

这个方法的一个例子可能如下所示。我省略了一些具体细节,以免分散大家对执行的注意力。

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

注意,queryText是从包含准备语句的SQL文本的受保护的静态final字符串生成的。预处理语句文本中的?使用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字符串。

例如,您可以用自定义枚举替换任何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的动态非enum实现来将他们手工构建的SQL字符串放入该方法。

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

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

不要使用原始的SQL字符串,最好使用准备好的语句

最新更新