2017-01-09 80 views
1

我有以下枚举:的Java枚举值和SQL注入

public enum AccountStatus { 

    ENABLED, 
    CONFIRMATION_PENDING, 
    EXPIRED, 
    LOCKED, 
    DISABLED, 
    CREDENTIALS_EXPIRED, 
} 

那我结合复选框在JSP形式:

<li><form:checkbox path="accountStatus" value="ENABLED" label="Enabled" /></li> 
<li><form:checkbox path="accountStatus" value="CONFIRMATION_PENDING" label="Confirmation Pending" /></li> 
... 
<li><form:checkbox path="accountStatus" value="CREDENTIALS_EXPIRED" label="Credentials Expired" /></li> 

在我的控制器时,我得到的选择复选框值我将字符串转换为一个枚举如下:

AccountStatus accountStatus = AccountStatus.valueOf("selected string here"); 

然后在我的DAO(使用Spring JdbcTemplate)我查询我的数据基地使用选择的值:通过使用AccountStatus.valueOf(...)

String SQL = "SELECT * FROM TABLE_A WHERE column = \'" + accountStatus.name() + "\'"; 

jdbcTemplate.query(SQL, new MyMapper()); 

由于我选择了验证复选框每个用户,从SQL注入做安全的这种方式?

+2

为什么你不使用参数化查询? – cubrr

+0

我的SQL查询比较复杂,我只写了一个简单的例子。所以我必须根据用户输入的值动态生成SQL查询。 – karim

+1

所以你仍然可以参数化。 – OldProgrammer

回答

1

您不必为如何你展示这个枚举值越来越设置某人注入任意SQL的危险。攻击者可能会发送无效的枚举名称,但valueOf在无法将其与有效值相匹配时会抛出IllegalArgumentException。

如果出于某种原因不应输入有效的枚举值(例如,某个特定角色没有权限查找带有DISABLED值的条目),那么在缺少其他服务器端验证的情况下攻击者可以将条目更改为有效但未被允许的值。所以这可能是一种可能的攻击,您可以通过添加更多验证来补救(在我的示例中,检查是否允许为用户角色使用枚举值)。

它会改善此SQL的可读性,以重写它以使用参数(最好是named parameters)。此外,这将继续在每个代码审查,静态代码分析和代码审计中显示出来,我不得不不断回答关于它的问题。但我明白,要避免触摸复杂的工作。