0

ご協力いただきありがとうございます。スタック オーバーフローに関する同様の記事と、次の記事を確認しました。

ただし、私は MySQL を初めて使用し、別の開発者チームによって作成された Ruby on Rails Web サイトで作業しています。自分の状況に合わせてさまざまな記事をつなぎ合わせるのに苦労しています。

コードに SQL インジェクションの脆弱性があり、パラメーターを使用する必要があることを知っています。MYコードでそれを行う方法がわかりません。以下にその一部を含めました。

私の search.html.erb から、SELECT ステートメントは次のようになります。

@office_matches = Masterlocation.paginate_by_sql("select * from mylocations where #      {search_string} order by nickname asc",  :page => params[:page], :per_page => 20)

次に、search_controller.rb に次のように記述します。

def results
@search_string = ""

@first_term = 'y'
      params[:search_terms_new] = "something in here so loop works"
    if params[:search_terms_new] != ""

# debugger

if params[:city] != ""
  @search_string << "and city like '%#{params[:city]}%' "
  if @first_term == 'y'
    @search_string = @search_string.gsub('and ', " ")
    @first_term = 'n'
  end
end

if params[:search][:state] != ""
  @search_string << "and state = '#{params[:search][:state]}' "
  if @first_term == 'y'
    @search_string = @search_string.gsub('and ', " ")
    @first_term = 'n'
  end
end

SQL インジェクション攻撃を防ぐには、このコードをどのように変更すればよいですか?

4

1 に答える 1

2

モデル スコープを使用するには、アプローチをリファクタリングする必要があると思います。

モデルにスコープ ベースの関数またはスコープを配置することから始めます。これは私のモデルの 1 つです。この例に関係のないビットの一部を除外しました。以下に、2 つの関数があることがわかります。1 つは account_grouping で検索し、もう 1 つはアカウントで検索します。

account_grouping 関数は、ドロップダウンの最初の項目が「all」であるドロップダウン ボックスで使用されますが、アカウント検索はテキスト検索フィールドです。

class CostTypeAllocation < ActiveRecord::Base

  attr_accessible :fiscal_year_id, :fiscal_period_id, :cost_centre_id, :account_grouping, :account_code, :account, :fixed_percentage,
    :marginal_percentage, :incremental_percentage,  :non_applicable_percentage

  scope :in_sort_order, order("fiscal_year_id DESC, fiscal_period_id DESC, account_code")

  # Allow for searching by Account Grouping
  def self.search_account_grouping(account_grouping)
    if account_grouping
      case account_grouping
      when 'all'
        scoped
      else
        where("account_grouping = ?", account_grouping)
      end
    else
      scoped
    end

  end

  # Search the text of the account
  def self.search_account(account)
    if account
      where("account LIKE ?", "%#{account.downcase}%")
    else
      scoped
    end
  end
end

これで、検索を処理するコントローラーの関数ができました。

class Admin::CostTypeAllocationsController < ApplicationController
  before_filter :authenticate_user!
  def index
    @search_account_grouping = params[:search_account_grouping] || 'all'
    @search_account = params[:search_account]
    @cost_type_allocations = CostTypeAllocation.search_account_grouping(@search_account_grouping).search_account(@search_account).in_sort_order.paginate(:page => params[:page], :per_page => 10)

  end
end

したがって、コントローラーまたはパラメーターに SQL はありません。モデル内のカプセル化されたすべてのものがあるべき場所。ページネーションは will_paginate gem によって処理されます。


コメントへの返信 コードがどこにあるかは問題ではありませんが、すべてのデータ アクセスをモデル レイヤーに保持することをお勧めします。

あなたの主な問題は、文字列で #{params[:city]} を使用することです。ユーザーがパラメーターに入力したものはすべて SQL に入力されるため、SQL インジェクション攻撃が可能になります。where('city like ?', "%#{params[:city]}%") は、レールが where 句を構築する前に param 内の SQL を除外するため安全です。

where account で設定したのと同じように、where city と where state のスコープを設定します。それらを取得したら、model.cityscope(params[:city]).statescope(params[:state]) に移動するだけで、レールは必要に応じてそれらをチェーンします。

都市と州を持つモデルにスコープを配置する必要があると思います。

http://guides.rubyonrails.org/security.htmlのセキュリティ ガイドを参照してください。

あなたのコメントに続いて、これがあなたが探しているものだと思います。

あなたのモデルで

def self.search_city(city)
    if city
        where ("city LIKE ?", "%#{city}%")
    else
        scoped
    end
end

def self.search_state(state)
    if state
        where ("state LIKE ?", "%#{state}%")
    else
        scoped
    end
end

そしてあなたのコントローラーで

@collection_for_view = Model.search_city(params[:city]).search_state(params[:state])

いずれの場合も、検索関数は、パラメータが設定されている場合は where フィルタを返し、空白の場合はすべてのレコードを返します。

于 2013-01-17T23:41:02.167 に答える