目次
SQLインジェクションとは
SQL インジェクションは、攻撃者がアプリケーションの入力に悪意のある SQL コードを挿入することによって、不正なデータベース操作を実行できるようにする一般的なセキュリティ脆弱性です。アプリケーションがユーザー入力を適切に検証およびフィルタリングしない場合、攻撃者はこの脆弱性を悪用して、予期しないデータベース クエリを実行したり、操作を変更または削除したり、機密データを取得したりする可能性があります。
SQL インジェクションは通常、ユーザーが指定したデータを使用してクエリ ステートメントを構築する場合など、動的に構築される SQL クエリを使用するアプリケーションで発生します。攻撃者は、ユーザー入力に特殊な SQL 文字またはステートメントを挿入することでアプリケーションのクエリ ロジックを妨害し、悪意のある操作を実行する可能性があります。
以下は、SQL インジェクションがどのように機能するかを示す簡単な例です。ユーザーがユーザー名とパスワードを入力して認証するログイン フォームがあるとします。
$username = $_POST['username'];
$password = $_POST['password'];
$query = "SELECT * FROM users WHERE username='$username' AND password='$password'";
上記のコードは、ユーザー入力を SQL クエリ ステートメントに直接結合します。入力が検証およびフィルタリングされていない場合、攻撃者は特殊文字を入力することで認証をバイパスできます。
ユーザー名:' OR 1=1 --
パスワード: 任意のパスワード
この場合、入力はクエリ ステートメントに直接挿入されるため、クエリは次のようになります。
SELECT * FROM users WHERE username='' OR 1=1 --' AND password='任意密码'
これは常に当てはまり1=1
ます。攻撃者は、有効なユーザー名とパスワードを提供しない場合でも、認証を回避してアカウントにログインします。
SQL インジェクション攻撃は、データ漏洩、データ破壊、権限昇格攻撃などの重大なセキュリティ問題を引き起こす可能性があります。したがって、安全な SQL クエリを作成し、ユーザー入力を検証してフィルタリングすることが非常に重要です。それで、それを防ぐ方法、ここに例があります
SQLインジェクションを防ぐ方法
PHP には、SQL インジェクション攻撃の防止に役立つ一般的な方法がいくつかあります。
-
プリペアド ステートメントの使用: プリペアド ステートメントは、SQL クエリを実行する前に事前に準備されたテンプレートです。プレースホルダー (疑問符や名前付きプレースホルダーなど) を使用してクエリ内のパラメーターを表し、パラメーター値をクエリから分離します。これにより、悪意のあるユーザーが悪意のある SQL コードを挿入してクエリを破損するのを防ぎます。PDO (PHP データ オブジェクト) と PHP の mysqli 拡張機能はどちらも準備済みステートメントをサポートしています。
プリペアドステートメントを使用したサンプルコードは次のとおりです。
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?"); $stmt->execute([$username]);
-
パラメータ化されたクエリを使用する (パラメータ化されたクエリ): パラメータ化されたクエリは、クエリ パラメータをクエリ ステートメントから分離する方法です。これは、パラメータをクエリ内のプレースホルダにバインドすることによって行われます。パラメーター化されたクエリは、ユーザー入力が SQL コードとして解釈される状況を防ぐことで、SQL インジェクション攻撃を防ぎます。
パラメータ化されたクエリを使用したサンプル コードは次のとおりです。
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username"); $stmt->bindParam(':username', $username); $stmt->execute();
-
入力の検証とフィルタリング: ユーザー入力を受信する前に検証してフィルタリングすることは、重要なセキュリティ対策です。入力は、PHP が提供するフィルター関数 ( など) を使用して検証し
filter_var()
、期待される形式と型に準拠しているかどうかを確認できます。またmysqli_real_escape_string()
、関数または PDO の定義済みパラメータ タイプ (PDO::PARAM_STR など) を使用して入力をフィルタリングし、入力内の特殊文字が SQL コードとして解釈されないようにすることもできます。入力検証とフィルタリングのサンプル コードは次のとおりです。
$username = filter_var($_POST['username'], FILTER_SANITIZE_STRING); $username = $pdo->quote($_POST['username']);
-
最小権限の原則: データベース ユーザーに最小限の権限を割り当てることは、効果的なセキュリティ手法です。潜在的な攻撃の範囲を減らすために、データベース ユーザーには必要な操作を実行する権限のみが付与されていることを確認してください。
-
エラー メッセージの処理: 運用環境では、データベースの機密情報が含まれている可能性があるため、詳細なエラー メッセージをユーザーに表示しないでください。開発者のトラブルシューティングのために、エラー メッセージをログ ファイルに記録できます。
これらの方法は絶対的なセキュリティ対策ではないため、安全な SQL クエリを作成するときは、入力検証、認証、アクセス制御、そしてもちろん SQL インジェクションの最も基本的な防止などの他のセキュリティ対策を考慮する必要があります。私たちが一般的に使用するトークンです。最後に、予防しないとどうなるかを説明します。
SQL インジェクションを防止しないとどうなるか
データベースが SQL インジェクションから保護されていない場合、次の問題が発生する可能性があります。
-
データ漏洩: SQL インジェクション攻撃により、データベース内の機密データが漏洩する可能性があります。攻撃者は、悪意のある SQL コードを挿入することで認証をバイパスし、ユーザーのパスワード、個人情報、その他の機密データを含むデータベース内のデータにアクセスして取得する可能性があります。
-
データ破壊: SQL インジェクション攻撃によって、データベース内のデータが破壊されたり改ざんされたりする可能性もあります。攻撃者は、悪意のある SQL コードを挿入することでデータベース内のデータを変更、削除、または破壊し、それによってアプリケーションの整合性と可用性を損なう可能性があります。
-
権限昇格攻撃: SQL インジェクションを通じて、攻撃者はデータベースの権限を使用して悪意のある操作を実行できます。データベース ユーザーが高い権限を持っている場合、攻撃者は挿入された SQL コードを使用して、新しいユーザーの作成、データ テーブルの削除、システム コマンドの実行などの危険な操作を実行する可能性があります。
-
サービス拒否 (DoS) 攻撃: 悪意のある SQL インジェクション攻撃は、データベース サーバーに過負荷をかけ、アプリケーションを動作不能にする可能性があります。攻撃者は大量の悪意のある SQL コードを挿入し、データベース サーバーのリソースが不足し、通常のリクエストを処理できなくなる可能性があります。
要約すると、SQL インジェクションを防止できないと、データ漏洩、データ破壊、権限昇格攻撃、サービス拒否攻撃などのセキュリティ リスクが発生する可能性があります。したがって、SQL インジェクションを防止することは、データベースに関係するアプリケーションにとって非常に重要なセキュリティ対策になります。プリペアドステートメント、パラメータ化されたクエリ、入力検証とフィルタリングなどを使用することで、SQL インジェクション攻撃を効果的に防止し、アプリケーションのセキュリティを向上させることができます。