最新のWeb開発のチュートリアル
 

SQL注入


SQLインジェクションは、データベースを破壊することができます。


WebページでのSQL

前の章では、SQLを使用して、(および更新)データベースのデータを取得するために学んできました。

SQLは、ウェブページ上のデータを表示するために使用される場合には、Webユーザが入力独自の検索値をさせるのが一般的です。

SQL文はテキストのみであるため、それが動的に選択されたデータをユーザに提供するために、SQLステートメントを変更するには、コンピュータコードの小さな作品で、簡単です。

サーバコード

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;

上記の例では、選択文字列に変数(txtUserId)を追加することにより、select文を作成します。 変数は、ユーザ入力(要求)からページに取り出されます。

この章の残りの部分では、SQL文でユーザー入力を使用しての潜在的な危険性を説明しています。


SQLインジェクション

SQLインジェクションは、悪意のあるユーザーがWebページの入力を介して、SQL文にSQLコマンドを注入することができる技術です。

注入されたSQLコマンドは、SQL文を変更し、Webアプリケーションのセキュリティを侵害することができます。


1 = 1に基づいて、SQLインジェクションは常にtrueです

上記の例では1より多くの時間を見て。

それでは、コードの本来の目的は、与えられたユーザーIDを持つユーザーを選択するには、SQL文を作成することでしたとしましょう。

入力からユーザーを防ぐために何もない場合は"wrong"入力は、ユーザーがいくつか入ることができる"smart"このような入力を:

ユーザーID:

サーバー結果

SELECT * FROM Users WHERE UserId = 105 or 1=1

上記のSQLは有効です。 1 = 1は常に真であるWHEREので、それは、テーブルのユーザーからすべての行を返します。

上記の例では、危険なように見えるでしょうか? Usersテーブルが名とパスワードが含まれている場合はどう?

上記のSQLステートメントは、この限り同じです。

SELECT UserId, Name, Password FROM Users WHERE UserId = 105 or 1=1

スマートハッカーは単に入力ボックスに105または1 = 1を挿入することにより、データベース内のすべてのユーザー名とパスワードへのアクセスを得るかもしれません。


基づいて、SQLインジェクションは、 ""=""常に真であります

ここでは、Webサイトへのユーザのログインを確認するために使用される一般的な構成は、次のとおりです。

ユーザー名:

パスワード:

サーバコード

uName = getRequestString("UserName");
uPass = getRequestString("UserPass");

sql = "SELECT * FROM Users WHERE Name ='" + uName + "' AND Pass ='" + uPass + "'"

スマートハッカーは単に挿入」またはによってデータベースのユーザ名とパスワードへのアクセスを得るかもしれない""="ユーザー名またはパスワードのテキストボックスに。

サーバーでのコードは、このような有効なSQL文を作成します。

結果

SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""

結果SQLは有効です。 WHERE "" = "は、"常に真であるので、それは、テーブルのユーザーからすべての行を返します。


バッチSQL文に基づいて、SQLインジェクション

ほとんどのデータベースは、セミコロンで区切られたバッチSQLステートメントをサポートしています。

SELECT * FROM Users; DROP TABLE Suppliers

上記のSQLユーザーのテーブルのすべてのローを返し、その後、仕入先と呼ばれるテーブルを削除します。

我々は、次のサーバーコードを持っていた場合:

サーバコード

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;

そして、次の入力:

ユーザーID:

サーバーでのコードは、このような有効なSQL文を作成します。

結果

SELECT * FROM Users WHERE UserId = 105; DROP TABLE Suppliers

保護のためのパラメータ

いくつかのウェブ開発者が使用する"blacklist"のSQLインジェクション攻撃を防ぐために、SQL入力に検索する単語または文字のを。

これは非常に良いアイデアではありません。 これらの単語の多く(のように削除するか、またはドロップ)と(セミコロンと引用符のような)文字は、共通の言語で使用され、入力の多くの種類で許可されるべきです。

(実際にはデータベースフィールド内のSQL文の入力に完全に合法でなければなりません。)

SQLインジェクション攻撃からWebサイトを保護するための唯一の実証済みの方法は、SQLのパラメータを使用することです。

SQLパラメータは、制御された方法で、実行時にSQLクエリに追加される値です。

ASP.NETカミソリ例

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);

パラメータは、@マーカーによってSQL文で表現されていることに注意してください。

SQLエンジンは、その列のために正しく、文字通り扱われ、SQLの一部が実行されないようにすることを確実にするために、各パラメータをチェックします。

もう一つの例

txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
db.Execute(txtSQL,txtNam,txtAdd,txtCit);

あなただけのSQLインジェクションを回避するために学んできました。 トップウェブサイトの脆弱性の一つ。


次の例は、いくつかの一般的なウェブ言語でパラメータ化クエリを作成する方法を示しています。

ASP.NETでのSELECT文:

txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txtUserID);
command.ExecuteReader();

ASP.NETでINSERT INTOステートメント:

txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
command = new SqlCommand(txtSQL);
command.Parameters.AddWithValue("@0",txtNam);
command.Parameters.AddWithValue("@1",txtAdd);
command.Parameters.AddWithValue("@2",txtCit);
command.ExecuteNonQuery();

PHPでINSERT INTOステートメント:

$stmt = $dbh->prepare("INSERT INTO Customers (CustomerName,Address,City)
VALUES (:nam, :add, :cit)");
$stmt->bindParam(':nam', $txtNam);
$stmt->bindParam(':add', $txtAdd);
$stmt->bindParam(':cit', $txtCit);
$stmt->execute();