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

时间:2013-01-07 17:36:56

标签: java sql security sql-injection

我有人指出,使用私有方法处理单个类所做的所有查询的查询执行会增加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,因为我认为它符合特定的安全编程问题。

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

谢谢

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:1)

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

对我来说似乎很重要(以及通过编辑问题而改变的)是它应该尽可能地用它来执行手工构建的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工作正常。

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