简体   繁体   English

带表名的 PreparedStatement

[英]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:为此,在 SQL 查询中,我使用 PreparedStatements 安全地注入参数,如下所示:

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.我的问题是关于表tableName的名称,我目前正在从位于服务器上的属性文件中检索它,但是从我看到的 PreparedStatements 中我无法注入表的名称,因为它是不允许的。 How could you specify the table name in a safe way without concatenating the value in the query?如何在不连接查询中的值的情况下以安全的方式指定表名?

A table name cannot be used as a parameter in a PreparedStatement .表名不能用作PreparedStatement中的参数。 It must be hard coded .它必须是硬编码的。

As i can see you already created your query containing the tableName.如我所见,您已经创建了包含 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.如果您从前端收到“或 1=1”之类的参数,则无法动态连接查询和参数,因为您很容易受到 sql 注入的影响,但这里情况并非如此,因为您是单独提供参数的。 Anyway, sounds a bit strange to have the table name configurable.无论如何,让表名可配置听起来有点奇怪。

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);尝试throw new BusinessException("uncaught", e); - and if BusinessException is your code, make sure you add that constructor (you can just call super(msg, cause); ). - 如果 BusinessException 是您的代码,请确保添加该构造函数(您可以调用super(msg, cause); )。

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.我猜你想从你的属性中获取tableName的原因是你的模式是在一个 state 的通量(?)......在开发环境中并不罕见。 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:如果是这种情况,从您的属性中获取它不会引入漏洞,并且如果您使用的是Spring ,我相信您可以使用如下注释:
@ConfigurationProperties(prefix = "schema.properties")
On your class, then include a field like:在您的 class 上,包括如下字段:
private String tableName;
In the class.在 class 中。 If this is the case and you have a field in the applications.properties file (or environment specific equivalences) called:如果是这种情况,并且您在applications.properties文件(或特定于环境的等效项)中有一个字段,称为:
schema.properties.tableName = myTableName
I think you should be good to go.我认为你应该对 go 好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM