1. SQLインジェクションとは何か? いわゆるSQLインジェクションとは、ドメイン名やページリクエストのクエリ文字列をフォームフォームに挿入し、最終的にサーバーを騙して悪意のあるSQLコマンドを実行させることです。 巧妙なSQL文を作成するパラメータを提出することで、望ましいデータを確実に取得できます。
2. SQL注射の種類 具体的には、SQLインジェクションは数字インジェクション、文字インジェクション、検索インジェクション(like)、インインジェクション、センテンス接続インジェクションの5つのカテゴリーに分けられます。 応用の観点からは、IPにおけるSQLインジェクション、検索、バッチ削除、データベース間の転送に特に注意を払うべきです。
3. 注射方法
典型的な例を見てみましょう
SqlCommand cmd = new SqlCommand("SELECT * FROM PE_USERS WHERE UserName = '" 2+ UserName + "' AND UserPassword = '" + PassWord + "'", conn); UserNameとPassWordの検証がないため、もしUserName="admin' OR 1=1--"の場合 実行されたSQL文は次のようになります:
UserName='admin' または 1=1—' および UserPassword='' の PE_USERS から * を選択 これによりSQLインジェクションが行われ、条件は常に真なので、パスワードなしでも正常にログインできます。
4. SQLインジェクションの防止方法
1. 疑わしい文字列のフィルタリングまたは変換
SQLインジェクションは、危険な文字列をフィルタリングまたは変換する関数を書き、その後GLOBAL.ASAXを使うかコンテキストインスタンスを書き換えることで防げます
例を挙げます
public static bool SqlFilter2(string InText) 2 { 3 string word="and|exec|insert|select|delete|update|chr|mid|master|or|truncate|char|declare|join"; 4 の場合は(InText==null) 5は誤りを返します。 6 foreach(単語の文字列i。 スプリット('|')) 7 { 8 の場合は((InText.ToLower() IndexOf(i+" ")>-1)||(InText.ToLower() IndexOf(" "+i)>-1)) 9 { 10は真を返します。 11 } 12 } 13は偽を返します; 14 }
2. グローバル.asax
保護された空虚Application_BeginRequest(Object sender, EventArgs e) 2 { 3 // Postパラメータのトラバース(隠れたドメインを除く) 4 foreach(ここでの文字列i。 Request.Form) 5 { 6 もし(i=="__VIEWSTATE")が続くなら、 7 this.goErr(this. Request.Form.ToString()); 8 } 9 // Get パラメータをトラバースします。 10 foreach(ここでの文字列i。 Request.QueryString) 11 { 12 this.goErr(this. Request.QueryString.ToString()); 13 } 14 } private void goErr(string tm) 2 { 3 if(WLCW. Extend.CValidity.SqlFilter2(tm)) これ。 Response.end() 5 } 長所:この点は多くの初心者プログラマーがSQLインジェクションを防ぐために使っており、ほとんどの場合、インジェクションを防ぐのに効果的であるようです。
欠点:1. 元々注入に使われていなかった一部の文字をフィルタリングし、予期せぬ問題を引き起こす。 例えば、フォーラムメンバーの名前にフィルターされたキャラクターと同じ文字が含まれている場合、予期せぬ問題やトラブルが生じます。
2. 毎回フィルタリングや変換が必要となり、プログラムの効率が低下します
2. パラメータクエリにストアドプロシージャを使用する
SQLインジェクションの主な目的は、悪意のあるSQLコードを提出してデータベース内の悪意あるコマンドを実行することです。 したがって、SQLコマンドが実行前に処理されれば、SQLインジェクションは効果的に防ぐことができます。 パラメータ化されたクエリはSQLインジェクションを効果的に防げます。
例
const string strSql = "SELECT * FROM [PE_Users] WHERE UserName = @UserName"; パラメータparms = 新しいパラメータ("@UserName", DbType.String, userName); 上記のパラメータ@UserNameがあり、Prarmeterオブジェクトを使ってパラメータをCommandオブジェクトに追加します。 これによりパラメータ化されたクエリが得られます。 前述の通り、ADO.NET はSQL Serverに以下のSQL文を送信します:
Exec sp_executesql N 'select * from [pe_users] (username=@username ',N '@username nvarchar(20) ',@username=N 'name' SQL Serverはクエリを実行する前に@usernameを「name」という文字列に置き換えます。 以下の入力があると仮定します:
「ユニオン選択@@version、null、null— 生成されるSQL文は以下の通りです:
Exec sp_executesql N 'select * from [pe_users] (username=@username ',N '@username nvarchar(20) ',@username=N '' union select @@version, null, null--' 入力から ADO.NET 脱出しているのがわかります。
- public SqlParameter Add(string parameterName, SqlDbType sqlDbType, int size);
コードをコピーします
DbTyeやSqlDbTypeはさまざまなデータ型を持つことができます。 データタイプに基づいて選択できます。 場所によっては、パラメータの長さを指定するためにも使われます:intサイズ。 これにより、データベースのオーバーフローやSQLノートの発生も効果的に防げます 入場の可能性。 利点:SQLインジェクションを効果的に防げます。 欠点:一部の場所では適用できません。例えば、
3. ホワイトリスト
説明: 既知のパラメータ範囲の一部はホワイトリストの形で扱うことがあり、これによりSQLの注入やクエリを防げます 例えば、+列名による順序は、列名がパラメータの形で渡される場合、まずパラメータを判断するためにホワイトリストを作成することができます 番号がホワイトリストに入っているかどうか、そしてクエリを行ってください。そうでなければ誤った処理になります。 利点:安全で信頼できる 欠点:用途の範囲が狭い |