概要
SQL インジェクションの対策は、簡単に言えば SQL で静的プレースホルダを使用することです。
静的プレースホルダの詳細については、以下の記事を参照してください。
では、ASP.NET(C#, VB.NET) で SQL インジェクション対策を実際にどのように行うのか簡単なログイン処理で具体的に見てみましょう。
ログイン処理の概要は以下の通りです。動作環境は、.NET Framework 4.5 + SQL Server 2012 になります。
接続先のデータベース名は Test、テーブル名は LOGIN で、列名は ID, PASSWORD です。
.NET でデータベースにアクセスする方法は、LINQ を使用する方法と、DataReader を使用する方法があります。LINQ は使用するだけで SQL インジェクションの脆弱性を回避できるので、今後は LINQ を使用することを推奨します(参考1(Entitiy Framework),参考2(LINQ to SQL))。
なお、これは簡単なログイン処理のため、ログインにまつわるセキュリティ対策は省いています。ログインのセキュリティ対策は、以下の記事を参照してください。
LINQ を使用したログイン処理
LINQ は Entitity Framework で LINQ to Entities を使用します。事前に、エンティティの定義を作成しておく必要があります。
・Login.aspx(C#)
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Data.SqlClient; namespace TestCS { public partial class Login : System.Web.UI.Page { protected void ButtonLogin_Click(object sender, EventArgs e) { //パラメーター取得 string id = this.TextBoxID.Text; string passwword = this.TextBoxPassword.Text; //インスタンス作成 var entities = new LoginEntities(); //クエリ作成 var query = from t in entities.LOGIN where t.ID == id && t.PASSWORD == passwword select t; //ログイン処理&ログイン成功 if (query.Count() == 1) { //セッションに値格納 Session["id"] = id; //リダイレクト Response.Redirect("Welcome.aspx"); } } } }
・Login.aspx(VB.NET)
Public Class Login1 Inherits System.Web.UI.Page Protected Sub ButtonLogin_Click(sender As Object, e As EventArgs) Handles ButtonLogin.Click 'パラメーター取得' Dim id As String = Me.TextBoxID.Text Dim password As String = Me.TextBoxPassword.Text 'インスタンス作成' Dim entities = New LoginEntities() 'クエリ作成' Dim query = From t In entities.LOGIN _ Where t.ID = id And t.PASSWORD = password _ Select t If query.Count = 1 Then 'セッションに値格納' Session("id") = id 'リダイレクト' Response.Redirect("Welcome.aspx") End If End Sub End Class
DataReader を使用したログイン処理
・Login.aspx(C#)
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Data.SqlClient; namespace TestCS { public partial class Login : System.Web.UI.Page { protected void ButtonLogin_Click(object sender, EventArgs e) { int count = 0; //接続文字列 string connectionString = @"Server=(local)\SQLEXPRESS;Initial Catalog=Test;User ID=user01;Password=pass"; //接続作成 SqlConnection con = new SqlConnection(connectionString); //プレースホルダで SQL 作成 string sql = "SELECT COUNT(*) AS CNT FROM LOGIN WHERE ID = @ID AND PASSWORD = @PASSWORD;"; //パラメーター取得 string id = this.TextBoxID.Text; string passwword = this.TextBoxPassword.Text; //プレースホルダにパラメーター設定 SqlCommand command = new SqlCommand(sql, con); SqlParameter pID = new SqlParameter("@ID", id); command.Parameters.Add(pID); SqlParameter pPassword = new SqlParameter("@PASSWORD", passwword); command.Parameters.Add(pPassword); //接続オープン con.Open(); //SQL 実行 SqlDataReader reader = command.ExecuteReader(); if (reader.HasRows) { while (reader.Read()) { count = (int)reader["CNT"]; } } reader.Close(); con.Close(); if (count == 1) { //ログイン成功 Session["id"] = id; Server.Transfer("Welcome.aspx"); } } } }
・Login.aspx(VB.NET)
Imports System.Data.SqlClient Public Class Login1 Inherits System.Web.UI.Page Protected Sub ButtonLogin_Click(sender As Object, e As EventArgs) Handles ButtonLogin.Click Dim count As Integer = 0 '接続文字列' Dim connectionString As String = "Server=(local)\SQLEXPRESS;Initial Catalog=Test;User ID=user01;Password=pass" '接続作成' Dim con As SqlConnection = New SqlConnection(connectionString) 'プレースホルダで SQL 作成' Dim sql As String = "SELECT COUNT(*) AS CNT FROM LOGIN WHERE ID = @ID AND PASSWORD = @PASSWORD;" 'パラメーター取得' Dim id As String = Me.TextBoxID.Text Dim password As String = Me.TextBoxPassword.Text 'プレースホルダにパラメーター設定' Dim command As SqlCommand = New SqlCommand(sql, con) Dim pID As SqlParameter = New SqlParameter("@ID", id) command.Parameters.Add(pID) Dim pPassword As SqlParameter = New SqlParameter("@PASSWORD", password) command.Parameters.Add(pPassword) '接続オープン' con.Open() 'SQL 実行' Dim reader As SqlDataReader = command.ExecuteReader() If reader.HasRows Then While reader.Read() count = CType(reader("CNT"), Integer) End While End If reader.Close() con.Close() If count = 1 Then 'ログイン成功' Session("id") = id Server.Transfer("Welcome.aspx") End If End Sub End Class
Welcome 画面
・Welcome.aspx(C#)
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace TestCS { public partial class Welcome : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { //IDを表示 this.LabelID.Text = HttpUtility.HtmlEncode((string)Session["id"]); } } }
・Welcome.aspx(VB.NET)
Public Class Welcome Inherits System.Web.UI.Page Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 'IDを表示' Me.LabelID.Text = HttpUtility.HtmlEncode(CType(Session("id"), String)) End Sub End Class
参考
Webアプリケーションセキュリティに関する記事は、以下のページにまとまっています。ぜひご確認ください。
コメント