使用为by by编写的预处理语句来防止SQL注入java

时间:2018-01-29 15:08:03

标签: java prepared-statement sql-injection

我有一个查询条件,排序和限制。我正在使用预准备语句来设置where条件和限制。目前我正在使用字符串追加来导致SQL注入漏洞。

我不能像这样使用set string来排序order by ? ?如果我这样做,SQL Order功能就不起作用了。

示例查询:

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

我可以采用其他任何方式来避免SQL注入。

3 个答案:

答案 0 :(得分:1)

执行类似的操作并将其连接起来:

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...

你可以做消毒和其他事情,但这应该适合你的情况

答案 1 :(得分:1)

您应该使用可能列的白名单:

const getInnerResult = (x, y, input) => {
  switch (input) { 
    case 1: 
    case 3:  return x;
    case 2:  return y;
    default: return null; 
  }
}

const getResult = function(input) {
  const result = getInnerResult("a", "b", input);
  
  // Other logic using the `result` variable
  return result ? result.toUpperCase() : "-";
};


console.log(getResult(2));
console.log(getResult(5));

然后在向用户引用列时使用索引:

String[] cols = {"siteid", "technology", "address", "state", "status"};

并在将列名附加到int colFromUser = Integer.parseInt(request.getParameter("sortCol")); 列表之前验证索引:

order by

虽然如果是我,我会使用Hibernate criteria之类的东西来完成这项工作:

if(colFromUser < 0 || colFromUser >= cols.length) {
    throw new IllegalArgumentException("Invalid column");
}
String col = cols[colFromUser];
query.append(col);

答案 2 :(得分:0)

PreparedStatement SetMethods仅适用于数据库表列值(WHERESELECT SQL语句的DELETE子句值,还包括{ {1}}和UPDATE语句)。

因此,这意味着不能通过问号符号({{}来参数化以下常用的SQL部分,例如列名,表模式,表名,ORDER BY,GROUP BY,分页(LIMIT,OFFSET,FETCH FIRST等) 1}})的INSERT

将用户输入中的值直接附加到查询中将导致安全漏洞,唯一的出路是从有效值列表中检查这些SQL部分的输入值。

例如您期望使用什么表名? ,特定表应采用哪种模式? ,特定表中存在哪些列? ,页码是整数吗?LIMIT值是整数吗? ?子句的列名之后的值只能是java.sql.PreparedStatementORDER BY,而不能是其他等等。

您可以动态填充这些有效值或系统中的硬代码。

如果传递了无效值,那么我们要么不执行查询(并将其记录为error),要么将无效值替换为有用的默认值并执行查询。