Reputation: 1194
I have a query with where conditions , order by and limit. I am using prepared statements to set the where conditions and limit. Currently i am using string append for order by which causing SQL injection vulnerability.
I cannot use set string to order by like this order by ? ?
SQL Order functionality not working if i do like this.
Example query:
SELECT siteid, technology, address, state, status FROM archive LEFT OUTER
JOIN mappings ON siteid = child_site_id order by siteid asc limit ? offset ?
SELECT siteid, technology, address, state, status FROM archive LEFT OUTER
JOIN mappings ON siteid = child_site_id order by siteid asc limit 10 offset 0
Any other way i can do this to avoid SQL injection.
Upvotes: 4
Views: 4249
Reputation: 10142
PreparedStatement SetMethods are applicable only for database table column values ( WHERE
clause values for SELECT
& DELETE
SQL statements and also includes to be updated or inserted column values for UPDATE
& INSERT
statements).
So this means that following usual SQL parts like - column names , table schema , table name , ORDER BY , GROUP BY , Pagination ( LIMIT , OFFSET , FETCH FIRST etc ) can't be parametrized via question mark symbol ( ?
) of java.sql.PreparedStatement
Directly appending values from user input to query will cause security flaw and only way out is to examine input values from your list of valid values for these sections of SQL.
e.g. what table name you are expecting ? , what schema should be for a particular table ? , what columns are present in a particular table ? , is page number an integer ?, is LIMIT value an integer ? values after column names for ORDER BY
clause should only be ASC
or DESC
& nothing else etc etc.
You can either dynamically populate these valid values or hard code in systems.
If invalid value is passed then either we don't execute query ( & log it as error ) or replace invalid value with useful defaults and execute query.
Upvotes: 3
Reputation: 2855
You should use a whitelist of possible columns:
String[] cols = {"siteid", "technology", "address", "state", "status"};
then use an index when referring to columns with the user:
int colFromUser = Integer.parseInt(request.getParameter("sortCol"));
and validate the index before appending the column name to the order by
list:
if(colFromUser < 0 || colFromUser >= cols.length) {
throw new IllegalArgumentException("Invalid column");
}
String col = cols[colFromUser];
query.append(col);
Although if it was me, I'd be using something like Hibernate criteria to do this job:
Criteria c2 = session.createCriteria(Supplier.class); c2.addOrder(Order.desc("name"));
Upvotes: 1
Reputation: 11287
Do something like this and concatenate it:
List<String> allowedSortableColumns = Arrays.asList(new String[]{"siteid", "technology", "address"})
if(! allowedSortableColumns.contains(sortByColumn)){
throw new RuntimeException("Cannot sort by: " + sortByColumn);
}
// Continue here and it's safe to concatenate sortByColumn...
You can do sanitization and other stuff, but this should work in your case
Upvotes: 1