spring 我可以使用if语句来防止SQL注入吗?

rdlzhqv9  于 2023-05-05  发布在  Spring
关注(0)|答案(2)|浏览(115)

我一直试图让我的应用程序通过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注入吗?若否,原因为何?我真的很难在这里找到一个有效的解决方案。

mrphzbgm

mrphzbgm1#

那些建议使用查询参数来防御SQL注入的人只说对了一半。这是大多数情况下推荐的解决方案。
但是查询参数只能用于代替常数值。不是标识符(在您的情况下是模式标识符)、表达式或SQL关键字等。
使用某种类型的验证是正确的,因此模式标识符被限制为一个已知的安全值。然后,您可以将该字符串插入到SQL查询中。如果您已经做了足够的验证,那么它就不会受到SQL注入的影响。
您还应该分隔标识符,以防它包含空格或标点符号,或与SQL保留关键字冲突。在DB2中,使用双引号作为标识符分隔符。
然而,即使您正在做的验证可能已经足够了,但它可能不是一种可以被像Checkmarx这样的自动化SQL注入检测工具识别的防御方法。它可能会看到您正在将变量放在一个SQL字符串中,并得出结论认为这是一个SQL注入风险。它无法判断您的验证是否足以防止问题。
SQL注入检测的自动化解决方案总是有限的。有时候,你必须使用人工分析。
我知道这是不时髦的说这些天,鉴于趋势说,人工智能将使程序员失业。但人工智能还不能像Maven人类那样可靠地处理边缘情况。我不相信它会永远如此。

yrwegjxp

yrwegjxp2#

我不会替你做你的工作但是你的问题可以总结为“为什么我会得到SQL注入?“
答案是“因为我正在动态创建SQL查询”,解决方案是:**停止动态创建SQL查询。**一旦你停止这样做,你所有的问题都会消失。你怎么停下来?将PreparedStatement()用于变量绑定(参数化查询)。
使用PreparedStatement(),你的sql访问看起来像这样:

string what_schema= //! Some value;
String query = SELECT_NEXTVAL_FOR + "?.CNTCT_ID FROM SYSIBM.SYSDUMMY1";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(1, what_schema);
ResultSet results = pstmt.executeQuery();

相关问题