カテゴリ: PHP 更新日: 2025/12/29

PHPのプリペアドステートメントを完全ガイド!初心者でも分かるSQLインジェクション対策

PHP の SQL インジェクション対策(プリペアドステートメント)
PHP の SQL インジェクション対策(プリペアドステートメント)

先生と生徒の会話形式で理解しよう

生徒

「PHPでデータベースを使うときって、悪い人に操作される危険があるって聞いたんですが、本当ですか?」

先生

「そうですね。特にSQLインジェクションという攻撃はとても有名で、初心者のころに必ず理解しておきたいポイントです。」

生徒

「SQLインジェクションって難しそう…。どうすれば防げるんですか?」

先生

「PHPではプリペアドステートメントという仕組みを使うことで、安全にデータベースを操作できます。仕組みと具体例をこれから説明しますね。」

-

1. SQLインジェクションとは?初心者でも分かる危険な攻撃の仕組み

1. SQLインジェクションとは?初心者でも分かる危険な攻撃の仕組み
1. SQLインジェクションとは?初心者でも分かる危険な攻撃の仕組み

PHPでデータベースを操作する場合に必ず理解してほしいのが「SQLインジェクション」という攻撃です。これは、入力欄に悪意ある文字を入れることで、プログラムが本来想定していない命令を実行させてしまう攻撃のことです。例えば、ログインフォームに名前を入力するだけでデータベースの情報を盗まれたり、削除されたりする危険があります。

初心者がよく書くコードでは、ユーザーが送った文字をそのままSQL文にくっつけてしまうことがあります。これはとても危険で、たとえば以下のような入力があったとします。


' OR '1'='1

このような文字が送られると、データベースは「常に正しい条件」と判断してしまい、ログインチェックを突破される可能性が出てきます。これがSQLインジェクションです。

2. SQLインジェクションを防ぐにはプリペアドステートメントが最強

2. SQLインジェクションを防ぐにはプリペアドステートメントが最強
2. SQLインジェクションを防ぐにはプリペアドステートメントが最強

PHPではSQLインジェクションを防ぐための仕組みとして「プリペアドステートメント」が用意されています。これはデータベースに送るSQL文と、実際のデータ(ユーザーが入力した内容)を完全に分けて扱う技術です。

プリペアドステートメントを使うと、データベースは「これは命令ではなくただの値だな」と認識するため、どれだけ変な入力をされても勝手にSQL文として実行されなくなります。つまり、どんなに悪意のある入力がきても安全なのです。

3. PHP(PDO)でプリペアドステートメントを使う実例

3. PHP(PDO)でプリペアドステートメントを使う実例
3. PHP(PDO)でプリペアドステートメントを使う実例

PHPでデータベースを扱うとき、もっとも一般的なのがPDO(PHP Data Objects)という方法です。ここでは初心者でもできるよう、基本のログイン確認の例を使って説明します。


<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'user', 'password');
$stmt = $pdo->prepare('SELECT * FROM users WHERE name = :name');
$stmt->bindValue(':name', $_POST['name'], PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetch();
?>

このコードでは次のように安全な処理を行っています。

  • prepare() で SQL 文のひな型をあらかじめ作る
  • bindValue() でユーザー入力を安全にセットする
  • execute() で実行する

SQL文と値が分離されているため、どんな入力が来てもSQLインジェクションは起きません。

4. MySQLiでもプリペアドステートメントは使える

4. MySQLiでもプリペアドステートメントは使える
4. MySQLiでもプリペアドステートメントは使える

PHPにはPDO以外に「MySQLi」というデータベース操作の方法もあります。こちらでもプリペアドステートメントを利用できます。


<?php
$mysqli = new mysqli('localhost', 'user', 'password', 'test');
$stmt = $mysqli->prepare('SELECT * FROM users WHERE name = ?');
$stmt->bind_param('s', $_POST['name']);
$stmt->execute();
$result = $stmt->get_result();
?>

PDOと同じく、SQL文とユーザーの入力が完全に分離されるため、安全なデータベース処理ができます。

-

5. プリペアドステートメントがなぜ安全なのか?初心者向けのたとえ話で解説

5. プリペアドステートメントがなぜ安全なのか?初心者向けのたとえ話で解説
5. プリペアドステートメントがなぜ安全なのか?初心者向けのたとえ話で解説

プリペアドステートメントの安全性を理解するために、簡単なたとえを使ってみましょう。

例えば、料理をするときに「レシピ(SQL文)」と「材料(ユーザーが入力する値)」を分けますよね。プリペアドステートメントはこれとまったく同じで、レシピを先に確定させ、材料が変なものでも料理は変わらないようにする仕組みです。

これにより、たとえ悪意ある文字が入力されても、命令として扱われないため安全なのです。

6. 初心者がやりがちな危険な例と安全な書き方の比較

6. 初心者がやりがちな危険な例と安全な書き方の比較
6. 初心者がやりがちな危険な例と安全な書き方の比較

初心者がついやってしまう危険な書き方を紹介し、その後に安全な書き方を示します。

危険なコード(絶対に書いてはいけない)


<?php
$name = $_POST['name'];
$sql = "SELECT * FROM users WHERE name = '$name'";
$result = $pdo->query($sql);
?>

ユーザーの入力がそのままSQLに組み込まれているため、SQLインジェクションが起きます。

安全なコード(必ずプリペアドステートメントを使う)


<?php
$stmt = $pdo->prepare("SELECT * FROM users WHERE name = :name");
$stmt->bindValue(':name', $_POST['name'], PDO::PARAM_STR);
$stmt->execute();
?>

SQL文と値が分離されているため、安全にデータベースを扱えます。

コメント
コメント投稿は、ログインしてください

まだ口コミはありません。

関連記事:
カテゴリの一覧へ
新着記事
New1
PHP
PHP のフォームデータの受け取り($_POST, $_GET)を完全解説!初心者向けガイド
New2
PHP
PHPのスコープとは?グローバル・ローカル・スーパーグローバルを完全解説!
New3
PHP
PHPの演算子をやさしく解説!算術・比較・論理・ビット演算子の使い方
New4
PHP
PHP の変数とは?基本的な使い方とデータ型を徹底解説!
-
人気記事
No.1
Java&Spring記事人気No1
Python
Pythonで辞書のキー・値・アイテムを取得する方法(keys(), values())
No.2
Java&Spring記事人気No2
Python
Pythonで辞書のネスト構造(入れ子辞書)を扱う方法 初心者向け完全ガイド
No.3
Java&Spring記事人気No3
Python
Pythonでエラースタックトレースを表示・取得する方法を徹底解説!初心者向け例外処理入門
No.4
Java&Spring記事人気No4
Python
PythonでMySQLに接続する方法を完全解説!初心者でもわかるpymysqlの基本
No.5
Java&Spring記事人気No5
Python
PythonでExcelファイル(.xlsx)を操作する方法を徹底解説!初心者でもできるopenpyxl・pandasの使い方
No.6
Java&Spring記事人気No6
PHP
PHP の日付と時間の取得(date, time, strtotime)を完全解説!初心者でもわかる使い方
No.7
Java&Spring記事人気No7
PHP
PHPで画像ファイルをアップロードする方法を初心者向けに徹底解説!わかりやすい画像処理入門
No.8
Java&Spring記事人気No8
PHP
PHP のデータ型を完全ガイド!初心者でもわかる int, string, float, bool など
-
-