Prevent SQL injection with PostgreSQL COPY JDBC

Amit Goldstein :

I have the following code to download a table as file, using 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);
        }
    }

Obviously this code is prone to SQL injection (table parameter is passed from a Spring REST controller). Of course I can do some manual sanitation but if there is a "PreparedStatement" way to do this in CopyManager I would prefer it. Bonus points for using Spring's JdbcTemplate.

Tim Biegeleisen :

In addition to blanket SQL injection, where a malicious tries to do something like add a DELETE statement to your COPY command, there is another problem. Because your code allows for any valid table name to run, it still runs the risk of revealing the data contained in any table in your schema.

So, the safe thing to do here might be to maintain a whitelist of tables which you want to allow the user to access. Any input table name which did not match the list would be rejected. Assuming your list of tables resides in a List, we could make the following change to your code:

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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=77641&siteId=1