誰かがSQLインジェクションを説明できますか?どのように脆弱性が発生しますか? SQLが注入されるポイントはどこですか?
誰かがSQLインジェクションを説明できますか?
SQLインジェクションは、一部のコンテンツをSQLクエリ文字列に補間すると発生し、その結果、意図しない方法でクエリの構文が変更されます。
悪意のあるものである必要はなく、偶然の可能性があります。しかし、偶発的なSQLインジェクションは、脆弱性よりもエラーを引き起こす可能性が高くなります。
有害なコンテンツは、ユーザーからのものである必要はありません。アプリケーションが任意のソースから取得したコンテンツであるか、コードでそれ自体を生成することさえあります。
脆弱性の原因は何ですか?
攻撃者は、SQL文字列に補間されることがわかっているアプリケーションに値を送信できるため、脆弱性につながる可能性があります。非常に賢いことで、クエリの結果を操作したり、データを読み取ったり、許可されていないデータを変更したりすることさえできます。
PHPの例:
$password = $_POST['password'];
$id = $_POST['id'];
$sql = "UPDATE Accounts SET PASSWORD = '$password' WHERE account_id = $id";
攻撃者がPOSTリクエストパラメータを "password=xyzzy
"および" id=account_id
"次のSQLになります。
UPDATE Accounts SET PASSWORD = 'xyzzy' WHERE account_id = account_id
$id
を整数にするには、攻撃者は列の名前である文字列を選択しました。もちろん、every行の条件は真であるため、攻撃者はeveryアカウントのパスワードを設定しただけです。これで、攻撃者は特権ユーザーを含む誰のアカウントにもログインできます。
SQLが挿入されるポイントはどこですか?
インジェクトされるのはSQLではなく、SQL文字列に補間(「インジェクト」)されるコンテンツであり、意図したものとは異なる種類のクエリになります。動的コンテンツを検証せずに信頼し、結果のSQLクエリを盲目的に実行しました。それがトラブルの始まりです。
SQLインジェクションは、通常、データベースやデータベースアクセスライブラリまたはフレームワークではなく、アプリケーションコードの障害です。
SQLインジェクションのほとんどのケースは、クエリパラメーターを使用することで回避できます。例については、 PHPでSQLインジェクションを防ぐにはどうすればよいですか を参照してください。
SQLインジェクションは、アプリケーションのユーザーがデータベースクエリの意味に影響を与えることができる場合に発生します。これは、ユーザー入力からの任意の文字列が連結されてデータベースに供給されるSQLを作成する場合によく発生します。たとえば、ユーザーログインの処理に使用される可能性のある次のコード(PHPで、ただしすべての言語に当てはまる)があるとします。
$sql = "SELECT FROM users WHERE username='".$_GET['username']."' AND password='".$_GET['password']."'";
ユーザーが次のように入力すると、被害が発生します
administrator'; --
...ユーザー名用。適切なエンコードを行わないと、クエリは次のようになります。
SELECT * FROM users WHERE username='administrator'; -- AND password=''
ここでの問題は、ユーザー名の 'がユーザー名フィールドを閉じ、次に-がSQLコメントを開始し、データベースサーバーが残りの文字列を無視することです。最終的に、ユーザーはパスワードを知らなくても管理者としてログインできます。 SQL Inectionを使用して、UPDATE、DELETE、またはDROPクエリを実行し、データベースに実際に損害を与えることもできます。
SQLインジェクションは、パラメーター化されたクエリを使用するか、言語/ツールキットのエスケープ関数(PHPのmysql_real_escape_string()など)を適用することで防止できます。
SQLインジェクションを理解すると、 this cartoon の背後にある冗談が得られます。
SQLインジェクションとは、データと思われるものが不本意ながらSQLコードとして扱われる場合です。
たとえば、あなたがやったら
mysql_query("SELECT * FROM posts WHERE postid=$postid");
通常、指定されたIDの投稿を取得しますが、$postid
が文字列10; DROP TABLE posts --
に設定されていると仮定します。突然、送信している実際のクエリは
mysql_query("SELECT * FROM posts WHERE postid=10; DROP TABLE posts --");
悪意のあるユーザーが投稿テーブル全体を失うことになるため、これは非常に問題です。
これを防ぐ最も簡単な方法は、たとえば [〜#〜] pdo [〜#〜] または MySQLi を使用して準備済みステートメントを使用することです。
PDOの同等の例は次のようになります
$statement = $db->prepare('SELECT * FROM posts WHERE postid = :postid');
$statement->bindValue(':postid', $postid);
$statement->execute();
これにより、データベースシステムは$ postidがコードではなくデータとして扱われることを認識し、適切に処理されます。
この質問はStackOverflowで何度も回答されていますが、誰もが知っておくべき重要なトピックなので、この質問を終了するために投票するつもりはありません。
このトピックに関する過去の回答へのリンクを次に示します。
また、今月のMySQL Conferenceでプレゼンテーションを行いました。私のスライドはオンラインです。
SQLインジェクションは、悪意のあるユーザーがSQLを入力フィールドに入力して、サーバーでSQLを実行しようとする場所です。
私が固守している一番のアドバイスは、コードで生のSQLを構築するのではなく、パラメータ化されたストアドプロシージャを使用することです。
ストアドプロシージャのパラメーターは実行されないため、ほとんどの場合安全です。
このペーパーは、SQLインジェクション手法に関する非常に優れた資料であることがわかりました(リンクはPDFです): SQL Serverアプリケーションでの高度なSQLインジェクション 。
タイトルは「高度」と書かれていますが、SQLインジェクションに関する知識がなくても非常に読みやすくなっています。
this code projectの記事が好きです。 )
概要
- 機密データを暗号化します。
- 必要最小限の特権を持つアカウントを使用してデータベースにアクセスします。
- 必要最小限の特権を持つアカウントを使用してデータベースをインストールします。
- データが有効であることを確認してください。
- コードレビューを実行して、2次攻撃の可能性を確認します。
- パラメータ化されたクエリを使用します。
- ストアドプロシージャを使用します。
- ストアドプロシージャのデータを再検証します。
- エラーメッセージが、アプリケーションまたはデータベースの内部アーキテクチャについて何も伝えないようにします。
一般的な背景を確認するには、 SQLインジェクションに関するウィキペディアの記事 をご覧ください。
要するに、SQLインジェクション攻撃は、データベースデータの盗難と破壊のすべてのマナーに対する脆弱性を残す可能性があります。システムでできることの正確な詳細は、システム自体の詳細によって異なります。
ユーザーからデータベースに入力を渡すたびに、潜在的な注入ポイントがあります。多くの場合、新しいプログラマーはユーザーからの入力を処理するリスクを理解していないため、Webアプリケーションはこの点で欠けています。
SQLが挿入されるポイントは、アプリケーションがユーザーからの入力を受け入れるポイントです。
これがWebアプリケーションにとって危険な脆弱性になるかどうかは、この入力が後でタイプを適切にチェックし、必要に応じてエスケープせずにSQLクエリの一部として使用されるかどうかによって決まります。
適切にエスケープしないと、ユーザーが「挿入」したSQLコードの一部が、単純な文字列や値ではなく、SQLコードとしてSQLエンジンによって実行される可能性があります。