#前提知識
SQLについて勉強していく中でSQLインジェクション攻撃というものを知りました。
複数の解説サイト等を読んでいくと自分がこれまで書いていたコードが「危険性のあるコード」として紹介されているものと近いのではないかと不安になりました。
自分の知識不足は反省するとして、これから書いていくコードをSQLインジェクション攻撃の対策が取れたコードにしなくてはいけないと思いました。
ただ、本当に自分が知識不足過ぎるだけなのですがいくつかの解説サイトを読んでもどう直せばSQLインジェクション攻撃の対策が取れたセキュア?なコードになるのかがいまいち理解できませんでした。
#聞きたいこと
0. 今の自分の理解に間違っている部分があれば指摘してほしいです。
-
(今の自分の理解があっているとするなら)こうすれば対策が取れたコードになるんじゃないか、というコードは書いてみたのですが、これではたして対策できているのか、なぜこれで対策になるのかがわかりません。対策できていますか。また、対策できていないとすればどこを直せばいいですか。
-
これまでは
'SQL文を実行するコードに続く
の部分でSQLを実行する実態部分をCallしていました。(引数がSQL文で、返り値が実行結果)直した方法のうち、例2の方法だとSQL文を作るためには接続を先に作成しなくてはいけません。つまり、セキュア?なSQL文を作成するためにもSQL文を作成する部分とSQL実行部分を分けてはいけないということでしょうか。
#利用環境
VB.NET
SQL Server
#勉強したことまとめ
##SQLインジェクション攻撃とは
例えばログインIDとパスワードを入力してログインするフォームがあるとする。
ユーザはログインIDとパスワードをテキストボックスに入力してログインする。
このとき、テキストボックスにSQL文を直接入力されてしまうと、こちらが意図していないSQL文が実行されてしまう可能性がある。
SQL文がこうなっているとして、
SQL
1SELECT 2 COUNT(UserID) AS cnt 3FROM m_User 4WHERE UserID = 'ユーザIDテキストボックスの値' AND pass= 'パスワードテキストボックスの値'
パスワードのテキストボックスに
a' OR '1' = '1
と入力されてしまうと、SQL文の結果が
SQL
1SELECT 2 COUNT(UserID) AS cnt 3FROM m_User 4WHERE UserID = 'ユーザIDテキストボックスの値' AND pass= 'a' OR '1' = '1'
となってしまい、だれでも入れるログインフォームになってしまう。
OR句が入っているので、ORの右側の条件'1' = '1'
に該当するとOKになってしまう。
(つまり100%該当してしまう)
##防ぐためにはどうすればいいか
いくつか紹介されていた(例えばテキストボックスの値を利用する場合エスケープを毎回挟むなど)が、これについて調べたいと思った。
###SQL 文の組み立ては全てプレースホルダで実装する。
プレースホルダによる組み立てとは、パラメータ部分を?などの記号で示しておき、後に、そこへ実際の値を機械的な処理で割り当てる方法である。
##SQLインジェクション攻撃を知るまでに書いていたコード
ログインフォームを例とする。
###例1
VB.net
1Private Sub bt_login_Click(sender As Object, e As EventArgs) Handles bt_login.Click 2 Dim sqlstr As String = "SELECT COUNT(UserID) AS cnt FROM m_User WHERE UserID = '" & tx_userid.Text & "' AND pass= '" & tx_pass.Text & "'" 3 'SQL文を実行するコードに続く 4 Dim dt As DataTable = SqlExecution(sqlstr) 5End Sub
###例2
vb.net
1Private Sub bt_login_Click(sender As Object, e As EventArgs) Handles bt_login.Click 2 Dim userid As String = tx_userid.Text 3 Dim pass As String = tx_pass.Text 4 Dim sqlstr As String = "SELECT COUNT(UserID) AS cnt FROM m_User WHERE UserID = '" & userid & "' AND pass= '" & pass & "'" 5 'SQL文を実行するコードに続く 6 Dim dt As DataTable = SqlExecution(sqlstr) 7End Sub
##知ったうえで対策を考えて書いたコード
###例1
説明を読んでこういうことか?と思いながら作ったもの。
今までと何が変わったのかよくわからない
vb.net
1 Dim userid As String = tx_userid.Text 2 Dim pass As String = tx_pass.Text 3 Dim sqlstr As String = "SELECT COUNT(UserID) AS cnt FROM m_User WHERE UserID = '@ID' AND pass= '@PASSWORD'" 4 sqlstr = sqlstr.Replace("@ID", userid) 5 sqlstr = sqlstr.Replace("@PASSWORD", pass) 6 'SQL文を実行するコードに続く 7 Dim dt As DataTable = SqlExecution(sqlstr)
###例2
VB.netで解説されているサイトを探して書いたもの
何をやっているのかはよくわかってないし、SQL文を作成する部分とSQL文を実行する部分を分けることができないのかな、と思ってしまう。
vb.net
1Private Sub bt_login_Click(sender As Object, e As EventArgs) Handles bt_login.Click 2 Dim userid As String = tx_userid.Text 3 Dim pass As String = tx_pass.Text 4 5 Dim connectionString As String = "" '接続文字列は今回伏せる 6 Dim con As SqlConnection = New SqlConnection(connectionString) 7 8 Dim sqlstr As String = "SELECT COUNT(UserID) AS cnt FROM m_User WHERE UserID = @ID AND pass= @PASSWORD" 9 10 Dim command As SqlCommand = New SqlCommand(sqlstr, con) 11 Dim pID As SqlParameter = New SqlParameter("@ID", userid) 12 command.Parameters.Add(pID) 13 Dim pPassword As SqlParameter = New SqlParameter("@PASSWORD", pass) 14 command.Parameters.Add(pPassword) 15 'SQL文を実行するコードに続く 16End Sub
#まとめ
0. SQLインジェクション攻撃について知った。
0. 自分のコードは対策ができていないのではと思った。
0. 対策方法を考えたが、対策できているのかよくわからなくなった。
知識不足ゆえに質問も的を射ていないかもしれませんが、よろしくお願いします。
#試した上での追記
例1、例2、修正例1、修正例2全て試しました
結果として
例1、例2、修正例1はダメ。修正例2はOKでした。
修正例1は例1、例2と同じ結果になりました。
(ユーザテーブルの全件のカウントが返ってくる)
実行されたSQLを出力すると以下のようでした。
SQL
1SELECT COUNT(UserID) AS cnt FROM m_User WHERE UserID = '0001' AND pass= 'a' OR '1'='1'
それに対して修正例2は0件(該当なし)が返ってきました
実行されたSQLを出力すると以下のようでした。
SQL
1SELECT COUNT(UserID) AS cnt FROM m_User WHERE UserID = @ID AND pass= @PASSWORD
回答6件
あなたの回答
tips
プレビュー