2016-11-25 4 views
0

Ich versuche, mich von SQL-Injection zu verteidigen, ich bin mit Variable als Spaltenname in #where:Rspec nicht Fehler StatementInvalid fangen

class BuildSegment::FindUsers 

    def initialize(params) 
    @key = User.connection.quote_column_name(params[:key]) 
    @negative = params[:negative] 
    @pattern = params[:pattern] 
    end 

    def call 
    if @negative 
     users = User.where.not("#{@key} LIKE ?", @pattern) 
    else 
     users = User.where("#{@key} LIKE ?", @pattern) 
    end 

    users.uniq 
    end 
end 

Variable @key wird von Hash genommen wird, welche manipuliert werden können Benutzer. So zum Beispiel, wenn @key = "email LIKE '%' OR email" und ich vorbei @key direkt an Active Record-Abfrage, die ich erhalten:

SELECT "users".* FROM "users" WHERE (email LIKE '%' OR email LIKE '') 

, die alle Benutzer zurückgibt. Ich fand quote_column_name(params[:key]) als Lösung, die ActiveRecord::StatementInvalid Fehler zurückgibt:

ActiveRecord::StatementInvalid: 
     PG::UndefinedColumn: ERROR: column "email LIKE '%com%' OR email" does not exist 
     LINE 1: SELECT DISTINCT "users".* FROM "users" WHERE ("email LIKE '%... 
                  ^
     : SELECT DISTINCT "users".* FROM "users" WHERE ("email LIKE '%com%' OR email" LIKE '') 

Dieser Test jedoch versagt:

expect(segment_builder.call).to raise_error(ActiveRecord::StatementError) 

Und voll Backtrace:

Failures: 

    1) BuildSegment is protected from SQL injection 
    Failure/Error: users_to_add = users.flatten 

    ActiveRecord::StatementInvalid: 
     PG::UndefinedColumn: ERROR: column "email LIKE '%com%' OR email" does not exist 
     LINE 1: SELECT DISTINCT "users".* FROM "users" WHERE ("email LIKE '%... 
                  ^
     : SELECT DISTINCT "users".* FROM "users" WHERE ("email LIKE '%com%' OR email" LIKE '') 
    # ./app/services/build_segment.rb:51:in `flatten' 
    # ./app/services/build_segment.rb:51:in `users_passing_all_rules' 
    # ./app/services/build_segment.rb:46:in `users_passing_filter' 
    # ./app/services/build_segment.rb:32:in `block in users_meeting_requirements_for' 
    # ./app/services/build_segment.rb:31:in `each' 
    # ./app/services/build_segment.rb:31:in `users_meeting_requirements_for' 
    # ./app/services/build_segment.rb:8:in `call' 
    # ./spec/services/build_segment_spec.rb:107:in `block (2 levels) in <top (required)>' 
    # ------------------ 
    # --- Caused by: --- 
    # PG::UndefinedColumn: 
    # ERROR: column "email LIKE '%com%' OR email" does not exist 
    # LINE 1: SELECT DISTINCT "users".* FROM "users" WHERE ("email LIKE '%... 
    #              ^
    # ./app/services/build_segment.rb:51:in `flatten' 

Wo könnte mein Fehler sein?

Antwort

0

Es sieht für mich aus, als ob Sie Ihre SQL nicht korrekt entkommen.

sehen, ob dies für Sie arbeitet:

User.where.not("#{@key} LIKE ?, '#{@pattern}'") 

User.where("#{@key} LIKE ?, '#{@pattern}'") 
Verwandte Themen