このコードは SQL インジェクションを防止しますか?
-
05-07-2019 - |
質問
背景
私は既存のデータ プロバイダーの分析を請け負っていますが、次のコードに欠陥があることがわかっています。しかし、それがどれほど悪いかを指摘するには、SQL インジェクションの影響を受けやすいことを証明する必要があります。
質問
どの「キー」パラメータが問題を壊す可能性があるか PrepareString
関数を実行して、 DROP
声明?
コードスニペット
Public Shared Function GetRecord(ByVal Key As String) As Record
Dim Sql As New StringBuilder()
With Sql
.Append("SELECT * FROM TableName")
If String.IsNullOrEmpty(Agency) Then
.Append(" ORDER BY DateAdded")
Else
.Append(" WHERE Key = '")
.Append(PrepareString(Key))
.Append("'")
End If
End With
Return ExecuteQuery(Sql.ToString())
End Function
Public Shared Function PrepareString(ByVal Value As String) As String
Return Value.Replace("''", "'") _
.Replace("'", "''") _
.Replace("`", "''") _
.Replace("´", "''") _
.Replace("--", "")
End Function
解決
直接の質問への回答:このコードはSQLインジェクションを防ぎますか:いいえ
ここに証拠があります-この文字列をPrepareStringメソッドにプッシュします:
Dim input = "'" & Chr(8) & "; Drop Table TableName; - " & Chr(8) & "-"
Dim output = PrepareString(input)
Console.WriteLine(input)
Console.WriteLine(output)
データベースからレコードを取得するのではなく、完全に準備されたSQL文字列を返すように、投稿したGetRecordメソッドを変更しました。
Console.WriteLine(GetRecord(output))
そしてこれが出力です
Input = ; Drop Table TableName; --
Output = '; Drop Table TableName; --
Query = SELECT * FROM TableName WHERE Key = ''; Drop Table TableName; --'
コードを1行追加します:
My.Computer.Clipboard.SetText(input)
そして、SQLインジェクションを完了するために、Webサイトの入力フィールドに貼り付けるためにクリップボードにコピーする必要がある文字列があります:
'; Drop Table TableName; - -
[StackOverflowによるポスト出力から制御文字が省略されていることに注意してください。したがって、出力を作成するにはコード例に従う必要があります]
PrepareStringメソッドが実行されると、まったく同じ出力が得られます-Chr(8)ASCIIコードは、余分な" '"を削除するバックスペースです。あなたは私の文字列を閉じる私のものに追加しているので、最後に私が自由に追加できます。あなたのPrepareStringには、スペースを削除するためのバックスペース文字が含まれているため、実際には-を使用しているため、-が表示されません。
作成している結果のSQLコードは、Drop Tableステートメントを妨げられずに実行し、クエリの残りを即座に無視します。
これの面白いところは、印刷できない文字を使用して、基本的に作成できる文字チェックをバイパスできることです。したがって、パラメーター化されたクエリを使用するのが最も安全です(これはあなたが尋ねたものではありませんが、これを避けるための最良の方法です)。
他のヒント
疑わしい質問に答えるには、機能しません。
.Replace(" ``&quot ;," ''")
は、 '`'を使用した正当なクエリを防ぎます
.Replace("´&quot ;," ''")
は、 '´'を使用した正当なクエリを防ぎます
.Replace("-&quot ;,"")
は、「-」が含まれる正当なクエリを防ぎます
.Replace(" ''&quot ;," '")
は、' '' '' 'が含まれる正当なクエリを誤って変更します
など。
さらに、エスケープ文字の完全なセットは、RDBMSごとに異なる場合があります。パラメータ化されたクエリFTW。
'を' 'に置き換えるだけでは、ハッキングできないと思います。エスケープクォート文字を変更することは可能だと聞いていますが、これは潜在的にこれを壊す可能性がありますが、よくわかりません。あなたは安全だと思います。
(少なくともSQLサーバーでは)安全だと思うし、実際に必要なことは s = s.Replace(" '&quot ;,"' '")だけだと思う
。もちろん、パラメーター化されたクエリを使用する必要がありますが、既に知っています。
これ MSDN の記事 注意しなければならないことのほとんどがカバーされています (SQL インジェクションに関してすべてを言うのは怖いですが)。
しかし、私はパラメータパラメータパラメータに関する他の皆さんの意見をエコーします。
あなたの例に関しては、いくつかの問題があります[編集:これらを更新しました]:
文字列「1 OR 1=1」を使用すると、ユーザーはすべてを取り戻すことができるのではないでしょうかさらに悪いことに「1;テーブル sometablename をドロップします」
確認したい記事によると、次のとおりです。
;- クエリの区切り文字。
' - 文字データ文字列の区切り文字。
-- - コメント区切り文字。
/* ... / - コメント区切り文字。テキスト 間/ かつ */ は サーバー。
xp_ - 名前の先頭で使用されます。 カタログ拡張ストアドプロシージャ、 xp_cmdshellなど。
文字をブラックリストに登録して、独自のバージョンのSQL Escapingを実装しようとしています。 このURL を確認することをお勧めします-SQLエスケープは必ずしも最悪の選択ではありません既存のアプリを修正します)が、脆弱性を回避するために正しく行う必要があります。
anotherへのURLリンクSQL Serverでエスケープするためのページでは、機能を制限せずに脆弱性を回避するのに役立つ提案を著者が提供しています。
それが役立つ場合、記事は中括弧もエスケープすることを提案します(私はそれらを角括弧と呼びます-しかし[])。
コードを使用しようとすると、キーを渡すことができます(; select * from table;そして、必要なテーブルのリストを取得します。
コード内でセミコロンをチェックしないと、t-sqlステートメントを終了して別のステートメントを開始できます。
パラメータ化されたクエリを使用します。