2017-06-01 57 views
0

我有一個rails API來處理來自我的前端的請求。這些請求包括url中的查詢參數,用於對數據庫中的結果進行優化和排序。一個例子網址查詢看起來是這樣的:使用column_names.include?防止SQL注入?

http://localhost:8000/clients?_sort=name&_order=DESC&_start=0&_end=10

在我的控制我的索引方法抓住這些PARAMS並將它們用於過濾和排序:

def index 
    @all_clients = Client.all 
    response.headers['X-Total-Count'] = @all_clients.count 

    if (Client.column_names.include?(params[:_sort])) 
    if (params[:_order] == 'ASC') 
     @clients = Client.filtered(params[:_start].to_i, params[:_end].to_i).order("#{params[:_sort]} asc") 
    else 
     @clients = Client.filtered(params[:_start].to_i, params[:_end].to_i).order("#{params[:_sort]} desc") 
    end 
    end 

    json_response(@clients || @all_clients) 
end 

filtered方法是一個範圍,它看起來像這個: scope :filtered, -> (_start, _end) { limit(_end-_start).offset(_start) }

我的問題是這樣的:通過使用Client.column_names.include?檢查是否params[:_sort]是一個有效的屬性排序,我有效白名單反對SQL注入?如果沒有,我怎麼能改變這個代碼來防止SQL注入?

回答

3

這裏要考慮的最重要的事情不是「則params的白名單」(因爲你已經挑肥揀瘦哪些參數無論如何使用,而不是一味地使用整個params哈希的東西),而是如何正在構建SQL

有在代碼中兩個潛在注入方面:

limit(_end-_start) 

這是脆弱? 如果_end_start是除了整數話,那麼代碼只會失敗,錯誤信息 - 如:

NoMethodError: undefined method `-' for "DROP_TABLE":String

or

ArgumentError: invalid value for Integer(): 3.14159

order("#{params[:_sort]} desc") 

這是脆弱? 是的。(但不容易)This page給出了一個具體的例子:

params[:_sort] = "(CASE SUBSTR(password, 1, 1) WHEN 's' THEN 0 else 1 END)" 

你應該從來沒有使用直接串插在SQL,除非你是絕對100%確保該字符串是「安全」。在這種情況下,您可以將它寫爲:

order(params[:_sort] => :asc) 
+1

另外值得注意的是,可能有一些列不是您希望用戶能夠排序。 (例如恢復問題,電話號碼,銀行餘額還是...?) - 在這種情況下,您還應該實施明確的白名單。 –

+0

這非常好,感謝Tom的回答。您提出的代碼更改正是我關心的地方,如果不使用字符串插值,我無法獲得正確的語法。 – quicklikerabbit

+1

您也可以使用綁定參數 - '.order(「?ASC」,params [:_ sort])'。 – max