首页 > 解决方案 > 使用准备好的语句从用户输入创建数据库以防止 SQL 注入

问题描述

在我们的应用程序中,我们接受用户输入(如项目名称),然后使用它为用户创建一个数据库(除其他外)。我想防止 SQL 注入,但无法准备用于创建数据库和授予访问权限的 SQL 语句。有没有一种安全的方法可以防止用户 SQL 注入我们?我所能想到的只是将输入限制为英文字母和空格(对于 DB 名称,用下划线替换它们),如果我们将 SQL 语句括在单引号内,这反过来可以提供保护。这是一个合理的解决方案吗?

我们正在使用带有 Postgres 10.6 数据库的 java 8/spring boot。我玩过 SQL 和准备好的语句,据我了解,它只能用于更新、删除和更新等查询。我曾尝试摆弄代码以尝试从用户输入中删除一些表,但幸运的是,它不起作用,但我想确保应用程序不会受到攻击。

String createDbSQL = "create database ?";
Connection connection = DriverManager.getConnection(env.getDbUrl(), env.getDbUsername(), env.getDbPassword());
connection.setAutoCommit(false);
PreparedStatement preparedStatement = connection.prepareStatement(createDbSQL);
preparedStatement.setString(1, "test_db_name");
preparedStatement.execute();

失败org.postgresql.util.PSQLException: ERROR: syntax error at or near "$1"(如果准备好的语句不能用于创建数据库,这很有意义)

PREPARE foo (text) AS create alter database $1;

需要查询表达式并且不起作用

标签: javaprepared-statementsql-injection

解决方案


这不是必需的,并且可能导致超出 sql 注入可能性的问题。如果您负责提供数据库,则需要负责命名。

您可以让用户提供一个名称,就他们而言,这是数据库的名称,但是您创建和使用数据库的代码可以使用您自己生成和控制的名称。这样,如果由于某种原因您需要给它一个不同的名称,或者创建数据库的新副本,或者切换到用户提供的名称遵循不同规则的不同数据库平台(并且他们选择的名称可能无效) ,您不会受到任何阻碍。


推荐阅读