2014-06-09 60 views
0

我試圖在PHP中創建聯繫表單搜索。多列無格式postgres搜索

示例項:

名稱:粉色

電話:555-888-1234

我要搜索的姓名和電話輸入框和返回像匹配的結果不區分大小寫。

例子:

在名稱搜索「p」和沒有電話號碼,並取回結果。

在電話號碼字段中搜索'5'並且沒有名字,得到結果。

在名稱字段中搜索「x」,得不到結果,目前我得到結果。

$query = "SELECT * FROM contacts WHERE name ~* '.*$name.*' OR phone ~* '.*$phone.*'"; 

回答

2

想象(但不實際運行它!),如果你把這個名稱字段會發生什麼:

');DROP TABLE contacts;-- 

Welcome to SQL injection。再見聯繫人表,除非你明智地與不是桌主的用戶一起運行 - 但即使如此,DELETE FROM contacts;也許可以工作。


在猜測,發生的事情是,你替換空字符串phonename,如果它是空白。因此給出.*$phone.*這產生了一個正則表達式.*.*這當然是匹配任何東西。由於有一個OR條款,與空白電話和姓名測試= x測試

name ~* '.*x.*' OR phone ~* '.*.*' 

這當然是真的在name任何價值。

您應該已經能夠通過查看實際運行的查詢來說明這一點。在postgresql.conf中打開log_statement=all並使用PostgreSQL查詢日誌。


你需要做的,而不是什麼是:

  • 建設上飛查詢。如果在phone的過濾器中沒有條目,請完全關閉OR phone ~* ...子句。

  • 使用查詢參數將您的值正確注入查詢。你可以做到這一點,即使你做拼接客戶端或類似串聯值:

    WHERE name ~* '.*'||$1||'.*' 
    

    其中$1是查詢參數佔位符。我不記得PHP是使用它還是?或其他;請參閱文檔。

  • 在將值作爲參數發送之前,請在您的值中轉義正則表達式元字符。否則,由於無效的正則表達式,搜索phone(將產生語法錯誤。

+0

我使用pg_query_params和傳遞和用戶輸入作爲參數在我們的真實代碼,這是一個簡化的例子,但是謝謝你指出SQL注入漏洞。我確實在postgres上登錄過,但沒有想到會在那裏看到,這會派上用場。它看起來像在飛行中建立查詢將起作用,但我也必須考慮是否包括或如果有人沒有輸入第一個值。我將不得不測試我是否仍然需要轉義正則表達式,如果它們作爲參數傳遞,希望不是。 – apuschak

+1

@apuschak您仍然必須轉義作爲參數傳遞的正則表達式,因爲它們的正則表達式元字符仍然很重要。不幸的是,我不認爲PostgreSQL有一個內置的'regexp_escape_string'或任何可以幫助你的東西。 –