En nuestra aplicación, estamos aceptando la entrada del usuario (como el nombre del proyecto) y luego la usamos para crear una base de datos para el usuario (entre otras cosas). Me gustaría evitar la inyección de SQL, pero no puedo preparar la declaración de SQL para crear una base de datos y otorgar acceso. ¿Hay alguna forma segura de evitar que los usuarios nos inyecten SQL? Todo lo que podría pensar es limitar la entrada a las letras del alfabeto inglés y los espacios (y para el nombre de la base de datos reemplazarlos con guiones bajos), lo que a su vez podría proporcionar protección si incluimos nuestras declaraciones SQL entre comillas simples. ¿Es esta una solución plausible?

Estamos usando Java 8 / Spring Boot con una base de datos Postgres 10.6. He jugado con SQL y una declaración preparada, a mi entender, solo se puede usar para consultas como actualizar, eliminar y actualizar. Intenté manipular el código para tratar de eliminar algunas tablas de la entrada del usuario, pero, afortunadamente, no funcionó, pero me gustaría estar seguro de que la aplicación no queda vulnerable.

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();

Falla con org.postgresql.util.PSQLException: ERROR: syntax error at or near "$1" (lo cual tiene sentido si la declaración preparada no se puede usar para crear una base de datos`

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

Espera expresión de consulta y no funciona

3
Johnny 10 may. 2019 a las 23:53

3 respuestas

La mejor respuesta

Esto no es necesario y podría causar problemas más allá de las posibilidades de inyección de sql. Si está a cargo de proporcionar la base de datos, debe estar a cargo de los nombres.

Puede permitir que el usuario proporcione un nombre, en lo que a ellos respecta, ese es el nombre de la base de datos, pero su código para crear y usar la base de datos puede usar un nombre que usted genera y controla usted mismo. De esa manera, si por alguna razón necesita darle un nombre diferente, o crear una nueva copia de la base de datos, o cambiar a una plataforma de base de datos diferente donde el nombre proporcionado por el usuario sigue reglas diferentes (y tal vez su nombre elegido no sea válido) , no se te impide nada de eso.

2
Nathan Hughes 10 may. 2019 a las 21:26

O solo permite a-zA-Z0-9, o puede usar escapeLiteral

1
stena 10 may. 2019 a las 21:12

No tiene permiso para crear bases de datos en la sintaxis PREPARE:

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

(Postgresql 10 docs) (BTW: Son 10.8 hoy en día. O 11.3 )

Por lo tanto, tendrá que crear la base de datos en una declaración normal.

El título de su pregunta no está relacionado con la pregunta en sí, ya que ha codificado el nombre de la base de datos y ha evitado cualquier ataque. Lo más probable es que desee tratar con nombres de bases de datos proporcionados por el usuario. Si ese es el caso, esa parte de su pregunta es un duplicado.

0
Christian H. Kuhn 10 may. 2019 a las 21:36