我一直试图让我的应用程序通过Checkmarx,但我一直遇到二阶SQL注入漏洞。
现在我的代码看起来像这样:
public static final String SELECT_NEXTVAL_FOR = "SELECT NEXTVAL FOR ";
@Value("#{ systemProperties['sequence.schema']}")
String sequenceSchema;
public Integer getNextContactId() {
if (sequenceSchema.matches("[A-Z]{3}@[A-Z]{3}|[A-Z]\\d[A-Z]{5}")) {
Query getNextContactIdQuery = entityManager.createNativeQuery(
SELECT_NEXTVAL_FOR + sequenceSchema + ".CNTCT_ID FROM SYSIBM.SYSDUMMY1");
return (Integer) getNextContactIdQuery.getSingleResult();
} else {
return null;
}
Checkmarx在这里将sequenceSchema
标记为问题。我的想法是,if语句将确保sequenceSchema
中存在的任何内容都只匹配我们模式的特定正则表达式。显然这还不够好。我尝试过使用位置/命名参数,但它们在WHERE或HAVING子句之外不起作用。我已经尝试了条件查询,如here没有任何运气。
我有另一个想法沿着与这里类似,但是我可以创建一组有效的模式,并将其与sequenceSchema
进行比较,而不是使用regex:
public static final String SELECT_NEXTVAL_FOR = "SELECT NEXTVAL FOR ";
@Value("#{ systemProperties['sequence.schema']}")
String sequenceSchema;
Set<String> validSchemas = ... //create set of valid schemas
public Integer getNextContactId() {
if (validSchemas.contains(sequenceSchema)) {
Query getNextContactIdQuery = entityManager.createNativeQuery(
SELECT_NEXTVAL_FOR + sequenceSchema + ".CNTCT_ID FROM SYSIBM.SYSDUMMY1");
return (Integer) getNextContactIdQuery.getSingleResult();
} else {
return null;
}
这样可以防止SQL注入吗?若否,原因为何?我真的很难在这里找到一个有效的解决方案。
2条答案
按热度按时间mrphzbgm1#
那些建议使用查询参数来防御SQL注入的人只说对了一半。这是大多数情况下推荐的解决方案。
但是查询参数只能用于代替常数值。不是标识符(在您的情况下是模式标识符)、表达式或SQL关键字等。
使用某种类型的验证是正确的,因此模式标识符被限制为一个已知的安全值。然后,您可以将该字符串插入到SQL查询中。如果您已经做了足够的验证,那么它就不会受到SQL注入的影响。
您还应该分隔标识符,以防它包含空格或标点符号,或与SQL保留关键字冲突。在DB2中,使用双引号作为标识符分隔符。
然而,即使您正在做的验证可能已经足够了,但它可能不是一种可以被像Checkmarx这样的自动化SQL注入检测工具识别的防御方法。它可能会看到您正在将变量放在一个SQL字符串中,并得出结论认为这是一个SQL注入风险。它无法判断您的验证是否足以防止问题。
SQL注入检测的自动化解决方案总是有限的。有时候,你必须使用人工分析。
我知道这是不时髦的说这些天,鉴于趋势说,人工智能将使程序员失业。但人工智能还不能像Maven人类那样可靠地处理边缘情况。我不相信它会永远如此。
yrwegjxp2#
我不会替你做你的工作但是你的问题可以总结为“为什么我会得到SQL注入?“
答案是“因为我正在动态创建SQL查询”,解决方案是:**停止动态创建SQL查询。**一旦你停止这样做,你所有的问题都会消失。你怎么停下来?将
PreparedStatement()
用于变量绑定(参数化查询)。使用
PreparedStatement()
,你的sql访问看起来像这样: