web-dev-qa-db-ja.com

SQLインジェクションを防ぐためのベストプラクティスは?

SQLインジェクションは、特にWebセキュリティに関しては常にホットなトピックです。この点で、どのWebアプリケーション内でもSQLインジェクションを防ぐために常に実行する必要がある手順に興味がありますか?また、これらの通常の手順に加えて、それを防ぐために他の人が通常を超えることをしていますか?

17
Mark Davidson

この質問についてはすでに非常に良い回答ですが、もう少し触れておきます。

  • 安全なコーディング(すでに多くの人がすでに言及しています)
    • ユーザー入力のエスケープ
    • パラメータ化クエリ(準備済みステートメント、変数のみをバインドする定義済みクエリ)
    • 防御的にコーディングする
  • 攻撃の監視
    • ネットワーク侵入検知システム(NIDS)
    • ホスト侵入検知システム(HIDS)
    • アプリケーション侵入検知システム(AppIDS)
  • 攻撃をブロック
    • アプリケーションファイアウォール
    • データベースファイアウォール
    • Webアプリケーションファイアウォール
      • Apache ModSecurity
      • Cisco Application Velocity System(AVS)
  • 脆弱性の調査
    • 自動ブラックボックス注入テスト
    • 静的ソースコード分析
    • 手動侵入テスト

これはpreventionの場合のみであり、私はsql server hardeningを考慮していません。ただし、多くの類似点があります。

注射に対してすでに脆弱である場合の追加の防御策は次のとおりです。

  • 必要最小限の許可でアプリケーションを実行する
    • 具体的には、必要なデータベースとテーブルへのアクセスのみを許可します
    • 必要な権限のみを付与してください(通常、選択、挿入、更新)
19
Chris Dale

準備されたステートメント、パラメーター化されたクエリ、すべてのユーザー入力のエスケープ。良い初心者には http://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet を参照してください。

16
Weber

重要な防御策は、データベースクエリを安全にエスケープするAPIのみを使用することです。これらは一般に、パラメータ化または準備されたステートメントと呼ばれます。これらはすべての場合に使用できるわけではありませんが(たとえば、実行時にテーブル名や列名などのSQL識別子が提供される場合)、可能な限り最善の方法です(ほとんどの場合)。

注-これにより、データベースに有害なデータが入れられる可能性があるため、このデータをアプリケーションの他の場所で使用する場合は注意してください

2番目の防御策は、エスケープアプローチを取ることです。これは、「単一引用符を2つの引用符で置き換える」アプローチです。このようにする必要がある場合は、潜在的に有害なすべての文字をエスケープするにする必要があります。可能であれば、OWASP ESAPIなどの上位レベルのライブラリを使用するか、OWASP SQLインジェクションチートシート(上記参照)をよく読んでください。

10
Justin Clarke

SQLインジェクションからWebアプリケーションを保護するための主な手順は、ユーザー入力(特にSQLクエリで使用される入力)を適切にサニタイズすることです。一部の言語/フレームワークでは、これらの値を処理する標準的な方法があります。たとえば、文字列値を結合してクエリを作成する代わりに、 パラメータ化クエリ を使用します。

9
bretik

私はポリテクニクスのITセキュリティを教えています。多くの場合、学生にとっては、SQLインジェクションに使用される用語についていくつかの混乱があるので、明確にしてみましょう。

FacebookのようなWebアプリケーションのコンテキストでは、

SQLインジェクションは、通常のWebユーザーがSQLコードをデータフィールドに入力するときです。

 ' OR '1'='1 into the textboxes of a login form.

SQLインジェクションを防ぐのに最適な人物は、Webアプリケーションがデータベースにデータを読み書きするためのコードを作成するWeb開発者です。

Web開発者によるSQLインジェクションを防ぐ最も簡単な方法は、パラメーター化されたクエリを使用することです。

準備されたステートメントとパラメーター化されたクエリは同じ意味です

これ以降は、パラメーター化されたクエリを使用します。

パラメータ化されたクエリは、SQLコードが最初に定義され、次にデータが適切なパラメータ内に配置される方法を参照します。

例:.Net

Update `users` set `name` = @name where `id` = @id

パラメータ@nameと@idはデータです。残りはSQLコードです。

パラメータ化されたクエリは通常ですが、常にではないWebアプリケーションコードで実行されることに注意してください。

パラメータ化されたクエリを書き出す一般的な方法は2つあります。

  1. 使用する言語に応じたWebアプリケーションコード
  2. ストアドプロシージャを使用したデータベース内

したがって、ある意味では、ストアドプロシージャはパラメーター化されたクエリの一種です。

単一引用符などの特殊文字をエスケープすることにより、SQLインジェクションを防ぐ他の方法があります。たとえば、PHPでは、基本的に単一引用符の前にスラッシュを置くmysql_real_escape_stringを使用できます。

MySQLのような特定のデータベースでは、LIKE演算子の%およびアンダースコアに問題があるため、これは理想的ではありません。詳細は this pdf を参照してください。

要するに、提案されているすべてのオプションは、SQLコードを削除するためにユーザー入力をサニタイズ(クリーンアップ)する必要があります。

最善の方法は、使用するプログラミング言語に応じてパラメーター化クエリを使用することです。

物語の終わり。

4
Kim Stacks

Web開発者の側からは、Weberがすでに言及したことに注意を向けるべきです。

さらに、GreenSQLのようにデータベースファイアウォールを設定できます: http://www.greensql.net/ 。これは、アプリケーションとユーザー入力の間のプロキシのように機能し、パススルーされるものを監視します。ただし、これには応答時間の増加という犠牲が伴います。

4
anonymous

適切なデータアクセスAPIを使用して、正しいことを安全に簡単に実行できます。

ActiveRecord v3は次のとおりです。

# basic usage
@user = User.where(:username => '[email protected]').first

# with a SQL-string fragment, but using parameters
@projects = @user.projects.where('status = ?', params[:status])
3
yfeldblum