从查询中删除SQL Injection漏洞

时间:2018-01-05 10:00:03

标签: java sql prepared-statement sql-injection

我需要从一个表中获取数据,该表有多个过滤器并限制来自java脚本数据表请求的行

SELECT coalesce(parent_id,siteid) as siteid, address, state, status, plan,
remarks, FROM archive  LEFT OUTER JOIN site_mappings ON 
site_dn = mrbts AND siteid = child_site_id 

在我的代码中,我有一个实现在执行预准备语句之前在查询中附加过滤器。 此处的过滤条件为List<String[]> filters,其过滤器值为列表名称(UPPER(mrbts)类似于UPPER(&#39;%6105%&#39;)) ... 6105是filter string和mrbts是列名

private String createFilterWhereClause(List<String[]> filters) {
    StringBuilder sb = new StringBuilder();
        Iterator<String[]> filterParmItr = filters.iterator();
            while (filterParmItr.hasNext()) {
                String[] filterParm = filterParmItr.next();
               sb.append("(")
                        .append(filterParm[ScFilterCriteria.FILTER_PARM_VAL])
                        .append(")");
                if (filterParmItr.hasNext()) {
                    sb.append(" and ");
                }

            }
        return sb.toString();
}

在执行期间,它会形成如下的sql查询,并在预准备语句中执行。

SELECT coalesce(parent_id,siteid) as siteid, address, state, status, plan,
remarks, FROM archive  LEFT OUTER JOIN site_mappings ON site_dn = mrbts AND
siteid = child_site_id   where UPPER(mrbts) like UPPER('%4105%') and 
((UPPER(technology) like UPPER('%LTE%')))

它具有SQL注入漏洞。为了解决这个问题,我试图通过使用预备语句集字符串来保护它,如下所示

SELECT coalesce(parent_id,siteid) as siteid, address, state, status, plan,
remarks, FROM archive  LEFT OUTER JOIN site_mappings ON site_dn = mrbts AND
siteid = child_site_id  where ?

使用预备声明,

PreparedStatement ps = null;
Connection connection = null;
ps = connection.prepareStatement(sql);
String filters = createFilterWhereClause(filterClause);
ps.setString(1, filters );

在设置字符串

之后用单引号形成的sql查询中的问题
SELECT coalesce(parent_id,siteid) as siteid, address, state, status, plan,
remarks, FROM archive  LEFT OUTER JOIN site_mappings ON site_dn = mrbts AND 
siteid = child_site_id  where '((UPPER(mrbts) like UPPER(\'%6105%\')))';

如何在设置字符串和/或任何其他方法中删除单引号? 你能帮助我吗?

3 个答案:

答案 0 :(得分:2)

将您的查询更改为:

SELECT coalesce(parent_id,siteid) as siteid, address, state, status, plan,
    remarks, FROM archive  LEFT OUTER JOIN site_mappings ON site_dn = mrbts AND
    siteid = child_site_id  where ((UPPER(mrbts) like UPPER(?));

仅使用预准备的语句参数设置参数。

添加动态条件:     //你的基本sql语句     String sqlString =&#34;选择......&#34 ;;

//add condition only in few cases
if(mycondition){
    sqlString += "WHERE mycondition = ?"
}

ps = connection.prepareStatement(sql);

//bind the corresponding dynamic parameter you just added in the where clause. 
if(mycondition){
   ps.setString(1, myparameter );
}

如果没有任何用户输入与sqlString连接,那么这样做是安全的。

答案 1 :(得分:2)

静态SQL语句的代码如下所示:

String query = "SELECT coalesce(parent_id,siteid) AS siteid, address, state, status, "
    + "plan, remarks "
    + "FROM archive "
    + "LEFT OUTER JOIN site_mappings ON site_dn = mrbts "
    + "AND siteid = child_site_id "
    + "WHERE UPPER(mrbts) LIKE UPPER(?) "
    + "AND UPPER(technology) LIKE UPPER(?)";

// UPPER probably is not needed; there was one spurious comma after "remarks"

String mrbts = "4105";
String technology = "LTE";

try (PreparedStatement preparedStatement = connection.prepareStatement(query)) {
    preparedStatement.setString(1, "%" + mrbts + "%");
    preparedStatement.setString(2, "%" + technology + "%");
    try (resultSet = preparedStatement.executeQuery()) {
        while (resultSet.next()) {
            ...
        } 
        return list; // Or such
    }
}

对于动态数量的标准:

StringBuilder sb = new StringBuilder();
List<Object> params = new LinkedList<>();
...
sb.append(" AND mrbts LIKE ? ");
params.add(mrbts);
...
int column = 1;
for (Object param : params) {
    preparedStatement.setObject(column, param);
    ++column;
}

答案 2 :(得分:0)

正如Joop Eggen所说,使用准备好的陈述