2015-09-25 40 views
0

我有在我試圖創建一個基於IP user`s對API整個SQL的使用情況運行它。構建整個SQL和使用preparedStatement時

EG:用戶點擊API與格式/what/table/field/field_value?name=value1

public static Result getRows(String what, String table, String field, String field_value, String more_where_clause) throws SQLException { 
    //more_where_clause will have as many condition for where clause 

      String sql = String.format("select ? from ? where ?=?"); 

      if (!where.equals("")) { 
       sql += String.format(" and ?"); 
      } 
      ResultSet rs = targetDB.query(sql, what, table, field, field_value, more_where_clause); 



public <T extends Comparable<T>>ResultSet query(String sql, T... args) throws SQLException { 
    ResultSet rs = null; 
    try{ 
     preparedStatement = conn.prepareStatement(sql); 

     for(int i=0; i<args.length; i++){ 
      preparedStatement.setObject(i + 1, args[i]); 
     } 
     rs = preparedStatement.executeQuery(); 
    } 
    catch(SQLException e) 
    { 
     e.printStackTrace(); 
    } 
    return rs; 
} 

但是,當我查詢它用說:

/name/user_table/first_name/john?last_name=doe 

我得到一個SQL字符串像

select 'name' from 'user_table' where 'first_name'='john' and 'last_name=doe' 
as    preparedStatement.setObject(i + 1, args[i]); 

推斷它作爲字符串。

什麼是更好的方式來做到這一點,也避免SQL注入。 編輯: 除了參數化where子句部分之外,還可以進行其他額外的檢查嗎?如何處理more_where_clause,用戶可以在where條件中輸入更多內容。

+0

如果您基本上讓用戶注入_everything_,包括表名(您不能將其作爲綁定變量並需要連接到查詢字面值中),則無法避免SQL注入。通常情況下,您只需讓用戶輸入_values_列,然後您可以通過準備好的語句安全地進行清理。 –

+0

所以我無法將它與bcoz綁定爲相同的原因,即'user_table''額外'引號的'名稱'。對? – user2601010

+0

http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html –

回答

2

您不能綁定名稱(場,表格等),就值。

根據您可以定義一個「白名單」正則表達式來檢查名稱符合您的限制安全原則(即只允許[A-ZaZ0-9_-]+

較貧窮的解決方案是定義一個「黑名單」上你禁止使用雙引號(")和轉義序列(如果涉及多個RDBMS引擎,那可能很痛苦),然後將所有名稱放在雙引號之間。使用雙引號時請注意案例的真實性。

您還可以檢查OWASP librairies。我知道他們提供API來處理HTML,CSS,JavaScript & HTTP注入。可能他們也定義了API來處理生成的SQL。

最終你也可以建立/查詢數據庫,元數據和對提供者的匹配對象名稱。在這種情況下,你可以依靠價值綁定。在這種情況下,不要忘記使用從元數據返回的值,並將它們用生成的SQL中的雙引號引起來。

+0

這是一個很好的soln https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringEscapeUtils.html,雖然我聽說過其他方面。 – user2601010

+0

注意,'StringEscapeUtils.escapeSql'只處理值而不是名稱。 – LoganMzz

+0

statement.executeQuery(「SELECT * FROM MOVIES WHERE TITLE ='」+ StringEscapeUtils.escapeSql(「McHale's Navy」)+ 「'」);如果我做statement.executeQuery(「SELECT * FROM MOVIES WHERE StringEscapeUtils.escapeSql(」TITLE「)='」+ StringEscapeUtils.escapeSql(「McHale's Navy」)+ 「'」);那會失敗? – user2601010