web-dev-qa-db-ja.com

文字列内のスペースを削除すると、SQLインジェクションから保護されますか?

文字列入力からすべてのスペースを削除することでSQLインジェクション攻撃から保護できるかどうか知りたいですか?

私は [〜#〜] owasp [〜#〜] でSQLインジェクションについて読んでいますが、スペースの削除については何も言及されていないので、なぜそうなるのか、そうでないのか興味がありました作業?


私は この質問 を見ていましたが、これはtrimについて尋ね、一番上の答えは次のとおりです:

いいえ、トリムを追加してもSQLインジェクションは妨げられません。 trimは、文字列の外側のスペースのみを削除します。

Select * from aTable where name like '%'+@SearchString+'%'

@SearchStringが次のようなものを保持している場合

'' update aTable set someColumn='JackedUpValue' where someColumn like '

それをすべてまとめて動的に実行すると、

Select * from aTable where name like '%' update aTable set someColumn='JackedUpValue' where someColumn like '%'

ただし、その検索文字列を取得した場合

update aTable set someColumn='JackedUpValue' where someColumn like 

この質問 に示されている操作を実行しましたが、

updateaTablesetsomeColumn='JackedUpValue'wheresomeColumnlike

どちらを実行するべきではありませんか?

これを無効にできるSQLインジェクションの形式があるかどうか知りたいのですが。 1つのWordの危険なコマンドはありますか?これを打ち負かすことができるなら、スペースを削除することは少なくとも防御に少し役立つでしょうか?

注:この質問は、SQLインジェクション防止の「適切な」メソッドの使用を回避する方法としてではなく、純粋に好奇心からのものです。

21
XaolingBao

いいえ。パーサーが入力を処理する方法は他にもたくさんあるので、スペースを削除してもSQLインジェクションは妨げられません。例を見てみましょう。クエリでユーザー提供の入力を安全に使用しないURLがあるとします。

http://example/index.php?id = 1 => SELECT * from page where id = 1

あなたの例では、攻撃者はスペースを使用します:

http://example/index.php?id = 1%20or%201 = 1 => SELECT * from page where id = 1 or 1=1

スペースを削除すると、注入が文字列に折りたたまれます。

次に、攻撃者が別の形式の空白、つまりタブを使用したと想像してください。

http://example/index.php?id = 1%09or%091 = 1 => SELECT * from page where id = 1 or 1=1

スペースを削除しても、注入は可能です。

使用しているテクノロジーによっては、攻撃者はスペースを/**/%00%09%0a%0dまたはSQLパーサーによるトークン化を引き起こす任意の数のUnicode。参照されている例ではスペースだけではなく、前述の例ではSQLコメントを利用して、空白ではないトークン化を引き起こしています。あなたはまだ脆弱です。

SQLインジェクションを防ぐ唯一の信頼できる方法は、パラメーター化されたクエリを使用することです。

117
wireghoul

2016年です。安全でないコードを使用しない限り、SQLインジェクションは過去のものです。

使用する言語が何であれ、all SQLインジェクションを防止したい場合は、準備されたステートメントまたは他のタイプのデータを使用しますバインディング。

準備されたステートメントはクエリをデータから分離し、データがクエリに影響することを不可能にします。

質問に直接答えるために、スペースを削除するとSQLインジェクションは削減されますが(古いコードとライブラリを使用する場合)、入力テキストは確実に制限されます(スペースはありません)。

48
Julie Pelletier

それは問題を制限しますが、それを排除しません。次の状況を考慮してください。

$un = str_replace(" ", "", $_POST["username"]);
$pw = hash($_POST["password"];
$sql = "SELECT * FROM users WHERE username = '$un' AND password = '$pw'";

ユーザー名を投稿するとしましょうadmin'--。それは私を単一のスペースを使用せずに管理者としてログインします。

wireghoul が指摘するように、タブなどの他の空白文字も削除する必要があります。しかし Julie Pelletier が指摘するように、準備されたステートメントを使用してください。 SQLiを使わずにSQLiを停止するための巧妙なスキームを考え出そうとするのは楽しいゲームかもしれませんが、準備されたステートメントが行うようなセキュリティは決して得られません。他のすべては単なる気晴らしです。

17
Anders

いいえ。これをSQLとして持っているとしましょう:

_"select * from people where last_name = '" + surname + "'"
_

入力すると:'OR(1=1)OR'a'='が入力になり、次のようになります。

_select * from people where last_name = ''OR(1=1)OR'a'=''
_

これは、OracleとMySQLで(少なくとも)実行され、テーブルからすべての行を返します。

13
JimmyJames

ただし、その検索文字列を取得した場合

update aTable set someColumn='JackedUpValue' where someColumn likeとこの質問に示されている操作を実行したのですが、

updateaTablesetsomeColumn='JackedUpValue'wheresomeColumnlike実行してはいけませんよね?

他の人が指摘したように、タブや\n(改行)など、考慮する必要のあるさまざまなSQLデータベース実装に空白を入れる他の方法があります。ほとんどすべてのデータベースエンジンは次のように受け入れます。

update
aTable
set
someColumn='JackedUpValue'

さまざまなデータベースのローカリゼーション設定に基づいて空白として機能するさまざまなUnicode文字があるかもしれませんが、それを理解するには実装の詳細を掘り下げる必要があります。パラメータ化されたクエリを使用するだけでなく、文字列を置換するこれらすべてのEdgeケースを試してカバーする理由は本当にありません。

2
nvuono

だからここにアイデアがあります。データベースサーバーは、受信したSQLクエリを受け取り、それをパーサーで実行して、解析ツリーを作成します。次に、ツリーを計画に変換して実行します。

インジェクションの本質は、パーサーがプログラマーが意図したものとは異なるツリーを生成することです。

したがって、修正は異常な解析ツリーを検出できるようにすることです。解析後、ツリーを歩き、データ値を差し引いた標準形式の文字列を生成します。文字列のSHA=ハッシュを計算します。アプリケーション/データベースユーザーの既知のハッシュのテーブルを保持します。サーバーが不明なハッシュを検出した場合は警告または中止します。

明らかに、起動の問題があります。したがって、プログラマーはテストモードでアプリケーションを実行し、徹底的なテストの後にハッシュを抽出し、アプリケーションの起動時にサーバーにハッシュをロードする必要があります。次に、abort-on-new-hashをオンにすると、SQLインジェクトができなくなります。

1
user126572