#java #postgresql #jdbc
#java #postgresql #jdbc
Вопрос:
У меня есть следующий код для загрузки таблицы в виде файла, используя PG COPY:
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);
}
}
Очевидно, что этот код подвержен SQL-инъекции (параметр таблицы передается из контроллера Spring REST). Конечно, я могу выполнить некоторую ручную очистку, но если есть способ «PreparedStatement» сделать это в CopyManager, я бы предпочел это. Бонусные баллы за использование JdbcTemplate от Spring.
Ответ №1:
В дополнение к общей SQL-инъекции, когда злоумышленник пытается сделать что-то вроде добавления DELETE
инструкции к вашей COPY
команде, существует еще одна проблема. Поскольку ваш код допускает выполнение любого допустимого имени таблицы, он по-прежнему рискует раскрыть данные, содержащиеся в любой таблице вашей схемы.
Итак, безопасным решением здесь может быть ведение белого списка таблиц, доступ к которым вы хотите разрешить пользователю. Любое имя таблицы ввода, которое не соответствует списку, будет отклонено. Предполагая, что ваш список таблиц находится в List
, мы могли бы внести следующие изменения в ваш код:
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);
}
}