PreparedStatement with table name

I have a vulnerability in my code, and I'm trying to fix it.

To do this, in the SQL query, I'm using PreparedStatements to inject the parameters safely as follows:

String runQuery(String value) {

   String myReturn;
   String query = "select VALUE from " + tableName + " where config = ?";

   try(PreparedStatement ps = con.prepareStatement(query)){
      ps.setString(1, value);
      try(ResultSet rs = ps.executeQuery()) {
         if (rs.next()) {
            myReturn = rs.getString(1);
         } else {
            throw new BusinessException("noSQLResultSet");
         }
      }
   } catch (Exception sqlException) {
      throw new BusinessException("SQLException");
   }
   return myReturn;
}

My question is about the name of the table tableName, I am currently retrieving it from the properties file located on the server, but from what I see with PreparedStatements I cannot inject the name of the table since it is not allowed. How could you specify the table name in a safe way without concatenating the value in the query?

Upvotes: 2

Views: 902

Answers (4)

lkatiforis
lkatiforis

Reputation: 6255

A table name cannot be used as a parameter in a PreparedStatement. It must be hard coded.

Upvotes: 1

Bill Naylor
Bill Naylor

Reputation: 490

I'm guessing that the reason that you want to get the tableName from your properties is that your schema is in a state of flux (?) ... not unusual in a development environment. If that is the case getting it from your properties does not introduce a vulnerability, and if you are using Spring, I believe you can use anotations like:
@ConfigurationProperties(prefix = "schema.properties")
On your class, then include a field like:
private String tableName;
In the class. If this is the case and you have a field in the applications.properties file (or environment specific equivalences) called:
schema.properties.tableName = myTableName
I think you should be good to go.

Upvotes: 0

rzwitserloot
rzwitserloot

Reputation: 103018

There is no particularly easy way; one solution is to whitelist the input: If it consists solely of letters and underscores, then it's okay.

Note that your exception handling is horrible, you're tossing away ALL useful info! Try throw new BusinessException("uncaught", e); - and if BusinessException is your code, make sure you add that constructor (you can just call super(msg, cause);).

Upvotes: 1

Dragos Ionut
Dragos Ionut

Reputation: 257

As i can see you already created your query containing the tableName. It's not ok to concatenate the query and the parameters on the fly as you are vulnerable to sql injection if you receive from frontend a parameter like "or 1=1", but it's not the case here since you are providing the parameters separately. Anyway, sounds a bit strange to have the table name configurable.

Upvotes: 0

Related Questions