使用准备好的语句从用户输入创建数据库以防止 SQL 注入

Create database from user input with prepared statement to prevent SQL injection

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

我们正在使用 java 8/spring 引导和 Postgres 10.6 数据库。我玩过 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 "" 而失败(如果准备好的语句不能用于创建数据库,这就有意义`

PREPARE foo (text) AS create alter database ;

需要查询表达式但不起作用

要么你只允许 a-zA-Z0-9,要么你可以使用 escapeLiteral

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

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

您不能在 PREPARE 语法中创建数据库:

statement
Any SELECT, INSERT, UPDATE, DELETE, or VALUES statement.

(Postgresql 10 docs)(顺便说一句:现在是 10.8。或 11.3)

因此您必须在正常语句中创建数据库。

你的问题标题与问题本身无关,因为你硬编码了数据库名称,因此避免了任何攻击。很可能您想处理用户提供的数据库名称。如果是这样的话,that part of your question is a duplicate.