Tengo el siguiente código para descargar una tabla como archivo, usando PG COPIA :
public void download(String table, Writer responseWriter) throws SQLException, IOException {
try (Connection conn = dataSource.getConnection()) {
CopyManager copyManager = new CopyManager(conn.unwrap(BaseConnection.class));
// SQL Injection can happen here!
String statement = "COPY " + table + " TO STDOUT WITH NULL ''";
copyManager.copyOut(statement, responseWriter);
}
}
Obviamente, este código es propenso a la inyección SQL (parámetro de tabla se hace pasar desde un controlador de primavera REST). Por supuesto que puedo hacer algo de saneamiento manual, pero si hay una manera "PreparedStatement" hacer esto en Administrador de Copias yo preferiría ella. Los puntos de bonificación para el uso de JdbcTemplate de primavera.
Además de la inyección de SQL manta, donde unos intentos maliciosos de hacer algo como agregar una DELETE
declaración a su COPY
mando, hay otro problema. Debido a que su código permite a cualquier nombre de tabla válido para correr, todavía corre el riesgo de revelar los datos contenidos en cualquier tabla en el esquema.
Por lo tanto, lo más seguro que hacer aquí podría ser la de mantener una lista blanca de tablas que desea permitir al usuario el acceso. Cualquier nombre de la tabla de entrada que no coincide con la lista sería rechazado. Asumiendo que su lista de tablas reside en una List
, podríamos hacer el siguiente cambio en su código:
public void download(String table, Writer responseWriter) throws SQLException, IOException {
// get list of all allowed tables
List<String> fileList = getAllowedTables();
if (!fileList.contains(table)) {
throw new IllegalAccessException("Someone tried to access a forbidden table.");
}
try (Connection conn = dataSource.getConnection()) {
CopyManager copyManager = new CopyManager(conn.unwrap(BaseConnection.class));
// SQL Injection can happen here!
String statement = "COPY " + table + " TO STDOUT WITH NULL ''";
copyManager.copyOut(statement, responseWriter);
}
}