2012-03-16 32 views
13

我有一個特殊情況要求我從用戶提供的輸入值生成部分SQL WHERE子句。我想防止任何種類的SQL注入漏洞。我想出了下面的代碼:如何在PostgreSQL中使用Java安全地轉義SQL中的任意字符串

private String encodeSafeSqlStrForPostgresSQL(String str) { 

    //Replace all apostrophes with double apostrophes 
    String safeStr = str.replace("'", "''"); 

    //Replace all backslashes with double backslashes 
    safeStr = safeStr.replace("\\", "\\\\"); 

    //Replace all non-alphanumeric and punctuation characters (per ASCII only) 
    safeStr = safeStr.replaceAll("[^\\p{Alnum}\\p{Punct}]", ""); 

    //Use PostgreSQL's special escape string modifier 
    safeStr = "E'" + safeStr + "'"; 

    return safeStr; 
} 

問題:

  • 你看到的任何問題?
  • 您能否提供更好的解決方案?
  • 是否有任何現有的庫來幫助這個?

注:

  • 這是SO和其他地方的一個共同的問題,但我見過的唯一的答案是經常使用的PreparedStatement。 Fwiw,我正在使用JasperReports。我想保留JasperReports中的查詢。查詢參數處理(包括X {}函數)的內置Jasper參數函數不足以滿足我需要的參數化。我可以嘗試創建一個自定義的Jasper QueryExecutor,它允許我注入自己的X {}函數,但這比使用Jasper的$ P!{}語法生成動態SQL where子句更復雜。我看了一下OWASP libraries。他們還沒有PostgresSQL編解碼器。儘管我看着OracleCodec,但它的逃逸看起來很簡單。我不確定這對防止SQL注入攻擊有多大幫助。

  • 在我的代碼中,我添加了E,以便不依賴於PostgreSQL的standard_conforming_strings設置。理想情況下,我不必添加它,然後該函數不必是PostgreSQL特定的。更多信息:http://www.postgresql.org/docs/9.0/static/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-ESCAPE

理想我會一直喜歡,我就知道會是安全的,支持所有可能的UTF-8字符串更通用的和可靠的解決方案。

+1

'BaseConnection.escapeString()'似乎涵蓋了這個http://jdbc.postgresql.org/development/privateapi/org/postgresql/core/BaseConnection.html#escapeString(java.lang.String) – 2012-03-16 17:05:54

+1

@FrankFarmer Great想看看JDBC驅動程序的來源。查看BaseConnection將我帶到Utils類:http://jdbc.postgresql.org/development/privateapi/org/postgresql/core/Utils.html。查看源代碼,他們打開符合標誌,然後轉義與我所做的相似的引號/撇號。他們只對\ 0角色進行特殊處理,並讓其他所有元素都通過。所以......我想這是安全的,我刪除\ 0以外的每個非標準字符都是矯枉過正的?隨時發表您的評論作爲我可以接受的答案。 – kaliatech 2012-03-16 18:00:34

回答

13

最最簡單的方法是使用PostgreSQL的Dollar Quoting在組合具有小隨機標籤:

  • 對於每個調用計算一個小的,隨機標籤(例如4個字符) (冗餘)
  • 查看quote標記是否是輸入字符串的一部分。
  • 如果是,重新計算一個新的隨機標籤。
  • 否則構建查詢這樣的:

    $tag$inputString$tag$ 
    

這樣你逃跑的不同嵌套引用技術整個麻煩和您也可以通過使用一個隨機標籤建立一個移動的目標。

根據您的安全要求,這可能會做或不做。 :-)

+0

有趣。我不知道美元引用的字符串語法。我剛纔試了一下,看起來確實有效。儘管有兩個注意事項:1)出於安全原因,您指出需要隨機化周圍的標籤是正確的。我認爲這是這種方法的主要負面影響。 2)通過測試,我確定美元語法仍然要求從字符串中刪除\ 0字符(否則從Postgres拋出異常,這比通過漏洞更好)。 – kaliatech 2012-03-16 19:15:14

+1

+1美元報價。儘管如此,你的邏輯還是有冗餘的。無論如何,如果您檢查用戶輸入的報價標籤,則最初不需要隨機化。如果報價標籤應該彈出,你只需要進行變異,這實際上只在攻擊者讀取你的代碼時纔會發生。只有這樣你才需要進行變異,這會掩蓋攻擊媒介。我冒昧地排除了冗餘步驟。 – 2012-03-17 06:25:13

+0

@ErwinBrandstetter:如果攻擊者可能以某種方式掩蓋了他對任務的使用,那麼從一開始就不要使用隨機標籤打開一些漏洞。這是一個相當不錯的現在,但我可以想象服務器編碼和客戶端編碼之間的一些編碼問題可能會訣竅。 ISO 2022(sic?)是我的第一個猜測。但我會考慮這一點,而在緩慢的線路上:-) – 2012-03-17 17:57:44

1

我在這裏問了一個similar question,但我認爲最好的辦法是使用org.postgresql.core.Utils.escapeLiteral。這是一個Postgres庫,所以使用它應該是安全的。如果/當Postgres添加新的字符串分隔符時,應更新此方法。

相關問題