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

问题描述 投票:0回答:2

我一直在努力让我的应用程序通过 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
进行比较,而不是使用正则表达式:

    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 注入吗?如果不是,为什么?我真的很难在这里找到一个可行的解决方案。

java spring spring-boot sql-injection checkmarx
2个回答
0
投票

那些推荐使用查询参数来防御SQL注入的人只对了一半。在大多数情况下,这是推荐的解决方案。

但是查询参数只能用来代替常量值。不是标识符(在您的情况下是模式标识符)、表达式或 SQL 关键字等

你在使用某种验证的正确轨道上,所以模式标识符被限制为一个已知的安全值。然后您可以将该字符串插入到您的 SQL 查询中。如果你已经做了充分的验证,那么它就可以免受 SQL 注入攻击。

您还应该分隔您的标识符,以防它包含空格、标点符号或与 SQL 保留关键字冲突。在 DB2 中,使用双引号作为标识符分隔符。

然而,即使您所做的验证可能已经足够,它可能不是一种可以被自动 SQL 注入检测工具(如 Checkmarx)识别的防御方法。它可能会看到您正在将变量一起放入一个 SQL 字符串中,并得出结论认为这是一个 SQL 注入风险。它不能说您的验证足以防止出现问题。

SQL 注入检测的自动化解决方案总是有限的。有时您确实必须使用人工分析。

我知道现在这么说已经不合时宜了,因为有一种说法是人工智能会让程序员失业。但是人工智能还不能像人类专家那样可靠地处理边缘情况。我不相信它会是。


-3
投票

我不会为你做你的工作......但是你的问题可以总结为“为什么我会得到 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();
© www.soinside.com 2019 - 2024. All rights reserved.