BTalic207022 (Community Member) asked a question.

Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') (CWE
ID 89)

I'm not sure what's wrong here

 

For executing queries in my app I'm using PreparedStatement . I have custom class QueryModel where I collect query and all parameters.

Then based on QueryModel instance I create PreparedStatement and set all needed parameters.

Scanner showing issue on executeQuery()

 

Description

This database query contains a SQL injection flaw. The function call constructs a dynamic SQL query using a variable

derived from untrusted input. An attacker could exploit this flaw to execute arbitrary SQL queries against the database.

  

Example of my custom QueryModel which I used to generate PreparedStatement

  

sqlQuery = "SELECT * FROM table WHERE username = ? and password = ?"

params = {ArrayList@12810} size = 2

 0 = {QueryParam@12812} 

 type = "String"

 value = "USERNAMETEST"

 1 = {QueryParam@12813} 

 type = "String"

 value = "PASSWORDTEST"

------------------------------------------------------------------------------------

  

public class QueryModel {

  String sqlQuery;

  List<QueryParam> params;

 

  public QueryModel() {

    params = new ArrayList();

  }

 

  public void addToParams(String type, Object value) {

    if(params == null)

      params = new ArrayList();

    params.add(new QueryParam(type, value));

  }

}

-----------------------------------------------------------------------------------------

Method where I generate PreparedStatement base on my dynamic instance QueryModel

  public PreparedStatement makeQueryDbCall(QueryModel queryModel) throws SQLException {

 

    if (connection == null || !connection.isValid(0))

      connection = configuration.dataSource().getConnection();

 

    PreparedStatement prepareStatement = connection.prepareStatement(queryModel.sqlQuery);

    if (queryModel.getParams() != null && queryModel.getParams().size() > 0) {

      int index = 1;

      for (QueryParam param: queryModel.getParams()) {

        if (param.type.equals(Integer.class.getSimpleName())) {

          prepareStatement.setInt(index, (int) param.value);

        } else if(param.type.equals(String.class.getSimpleName())) {

          prepareStatement.setString(index, (String) param.value);

        }

        index ++;

      }

    }

    return prepareStatement;

  }

---------------------------------------------------------------------------------------------

  public PrepareResponse callRetryableServiceQuery(QueryModel queryModel) {

    try {

      return retryableServiceCall(() -> genericDao.makeQueryDbCall(queryModel), queryModel);

    }catch (Exception e){

      oracleErrorLogService.saveQueryOracleErrorLog(queryModel, e);

      throw e;

    }

  }

-----------------------------------------------------------------------------------------------------------

  public static <T> T getObject(BaseRepository baseRepository, QueryModel queryModel, Class clazz) {

    PrepareResponse response = baseRepository.callRetryableServiceQuery(queryModel);

 

    if (!response.isStatus()) {

      baseRepository.closeResultSet(response.getSpReturnData());

      return null;

    }

 

    ResultSet rs = null;

    try {

      rs = ((PreparedStatement) response.getSpReturnData()).executeQuery(); //place where scanner showing issue 

    } catch (SQLException e) {

      logger.error("Failed execute query: {}", e.getMessage());

      e.printStackTrace();

    }

 

...

  }


  • Robert (Community Member)

    I suspect, but this would be better confirmed by a Veracode Security Consultant, that what you are seeing is the static analyzer flagging the whole "QueryModel" object as tainted. When one field of an object is "tainted", like the parameters, the static analyzer typically considers the whole object "tainted", and thus would probably assume that the query is tainted. I'm not sure your "QueryModel" approach will work well with the static analyzer as it currently works.

     

    As a test, if you remove your query from the QueryModel object, and then pass constant string directly to prepareStatement, I suspect the flaw will "disappear".

    Expand Post
  • BTalic207022 (Community Member)

    @Robert (Community Member)​ 

     

    Yes, you're right, If I pass constant string instead of value from query model flaw disappear

     

    // PreparedStatement prepareStatement = connection.prepareStatement(queryModel.sqlQuery);

    PreparedStatement prepareStatement = connection.prepareStatement("query");

     

    In the end whether this is really an issue?

     

     

     

     

     

    Expand Post
    • Robert (Community Member)

      If you are always using constant strings with query parameters for your queries, then, I don't believe there is a risk of an SQL Injection attack. However, if you use the Veracode static scanner, you will need to mark every "flaw" it generates related to your query use cases as "mitigated by design" or "false positive" (although I don't think Veracode would consider this a false positive, but it is a limitation of the static scanner, and the way it treats objects as tainted if any part of the data is tainted, as opposed to tracking the tainted data through the object in more detail). This maybe be frustrating or annoying if you have a lot of cases, or they may "re-appear" in different versions of the scan as your code changes. Up to you to judge how that works for you.

      Expand Post

Topics (3)

No articles found
Loading

Ask the Community

Get answers, share a use case, discuss your favorite features, or get input from the community.