カテゴリ: PHP 更新日: 2026/01/21

PHPのSQLインジェクション対策を完全解説!初心者でも安全にデータベースを扱う方法

PHP の SQL インジェクション対策(PDO, mysqli)
PHP の SQL インジェクション対策(PDO, mysqli)

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

生徒

「PHPでデータベースに保存する処理を作っているんですが、SQLインジェクションって危ないと聞きました。どうやって防げばいいんですか?」

先生

「SQLインジェクションは、フォームなどに入力された文字を悪用して不正なSQLを実行されてしまう攻撃のことです。PHPでは、PDOやmysqliを正しく使うことで簡単に対策できますよ。」

生徒

「PDOって聞いたことはありますけど、どう書けば安全になるんですか?」

先生

「では、まずSQLインジェクションがどんな攻撃かを理解して、次にPDOとmysqliを使った安全な書き方を見ていきましょう。」

-

1. SQLインジェクションとは?初心者でもわかる危険性の解説

1. SQLインジェクションとは?初心者でもわかる危険性の解説
1. SQLインジェクションとは?初心者でもわかる危険性の解説

SQLインジェクションとは、ユーザーが入力する文字の中に「特別な命令」を混ぜて、データベースに不正な操作をさせてしまう攻撃です。例えば、ログイン画面で本来はIDとパスワードだけを入力させる部分に、悪意のあるSQL文を紛れ込ませることで、データの書き換えや削除が行われてしまうことがあります。

たとえるなら、注文書を書く欄に「配送先:倉庫→そのまま全部捨てろ」と追加で書かれてしまって、そのまま実行してしまうようなものです。普通はそんな指示は無視すべきですが、対策をしていないとPHPはそのまま命令を実行してしまいます。

2. なぜSQLインジェクションが起きるのか?

2. なぜSQLインジェクションが起きるのか?
2. なぜSQLインジェクションが起きるのか?

原因は「文字列をそのままSQL文にくっつけてしまうこと」です。PHPでありがちな失敗例として、下記のようなコードがあります。


$user = $_POST['user'];
$sql = "SELECT * FROM users WHERE name = '$user'";
$stmt = $pdo->query($sql);

このコードは一見正しく見えますが、ユーザーが次のように入力したらどうでしょう?


' OR '1'='1

SQL文は下記のようになり、全ユーザーの情報が表示されてしまいます。


SELECT * FROM users WHERE name = '' OR '1'='1'

これがSQLインジェクションの典型的な例です。このような危険を防ぐためには、入力された値を「そのままSQLにつなげない」ことが重要です。

3. PDOを使った安全なSQLインジェクション対策

3. PDOを使った安全なSQLインジェクション対策
3. PDOを使った安全なSQLインジェクション対策

もっとも一般的で安全な方法は「プリペアドステートメント」を使うことです。プリペアドステートメントとは、SQL文の中に「?」などのプレースホルダー(後で値を入れる場所)を用意して、入力値を自動で安全に処理してくれる仕組みのことです。

PDOを使った安全なコードは下記のようになります。


$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');

$user = $_POST['user'];

$stmt = $pdo->prepare("SELECT * FROM users WHERE name = :name");
$stmt->bindParam(':name', $user, PDO::PARAM_STR);

$stmt->execute();
$result = $stmt->fetchAll();

ポイントは、値を prepare()bindParam() に渡すことで、mysql側が自動で危険な文字をエスケープ(安全に変換)してくれる点です。これにより、不正なSQL文が実行されることを防げます。

4. mysqliでのSQLインジェクション対策

4. mysqliでのSQLインジェクション対策
4. mysqliでのSQLインジェクション対策

PHPではPDOだけでなく、mysqli を使ったデータベース接続でもSQLインジェクション対策ができます。難しそうに見えますが、基本はPDOと同じ「プリペアドステートメント」を使うだけです。


$mysqli = new mysqli("localhost", "root", "", "test");

$user = $_POST['user'];

$stmt = $mysqli->prepare("SELECT * FROM users WHERE name = ?");
$stmt->bind_param("s", $user);

$stmt->execute();
$result = $stmt->get_result();

「s」は文字列(string)の意味で、値の型を指定します。mysqliでも、prepare → bind → execute の流れで安全にSQLを実行できます。

-

5. SQLインジェクション対策として絶対にやってはいけないこと

5. SQLインジェクション対策として絶対にやってはいけないこと
5. SQLインジェクション対策として絶対にやってはいけないこと

初心者の方が特にやってしまいがちなNG例も紹介します。これらは危険なので避けましょう。

  • ユーザー入力を直接SQLに連結する
  • addslashes() でエスケープすれば大丈夫だと思い込む
  • Magic Quotes(古いPHPの機能)に頼る

現代のPHPでは、プリペアドステートメントを使うことがもっとも安全で、最も推奨される方法です。

6. フォーム入力をバリデーションして安全性をさらに高める

6. フォーム入力をバリデーションして安全性をさらに高める
6. フォーム入力をバリデーションして安全性をさらに高める

SQLインジェクション対策には、プリペアドステートメントが絶対ですが、さらに安全性を高めるためには「バリデーション」が重要です。バリデーションとは、入力値に対して「正しい形式かどうか」を確認する処理です。

例えば、ログインフォームで「ユーザー名は20文字以内」「ひらがなは禁止」などのルールを作り、それを守らない入力をはじくことで、攻撃の入り口を狭めることができます。

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

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

カテゴリの一覧へ
新着記事
New1
PHP
PHPのCookieセキュリティを完全ガイド!初心者でもわかるSecureとHttpOnlyの使い方
New2
PHP
PHPのCSRF対策を完全理解!トークンを使った安全なフォーム送信の仕組みを初心者向けに徹底解説
New3
PHP
PHPのSQLインジェクション対策を完全解説!初心者でも安全にデータベースを扱う方法
New4
PHP
PHPでカウントダウンタイマーを作る方法!初心者向けにやさしく解説
-
人気記事
No.1
Java&Spring記事人気No1
Python
Pythonでテキストファイルを1行ずつ読み込む方法(readline() / readlines())
No.2
Java&Spring記事人気No2
PHP
初心者向けPHPでMySQLからデータを取得する方法(SELECT文)完全ガイド
No.3
Java&Spring記事人気No3
Python
Pythonのリストの重複を削除する方法を解説!初心者向けにsetとdict.fromkeysの使い方をやさしく説明
No.4
Java&Spring記事人気No4
Python
Pythonで経過時間を測る方法をやさしく解説!初心者向けtime.perf_counterとtime.sleepの使い方
No.5
Java&Spring記事人気No5
Python
Pythonでエラースタックトレースを表示・取得する方法を徹底解説!初心者向け例外処理入門
No.6
Java&Spring記事人気No6
Python
PythonでExcelファイル(.xlsx)を操作する方法を徹底解説!初心者でもできるopenpyxl・pandasの使い方
No.7
Java&Spring記事人気No7
PHP
PHPのOAuth認証をやさしく解説!Google・Facebookログインを初心者向けに実装しよう
No.8
Java&Spring記事人気No8
PHP
PHPのXSS対策を完全ガイド!初心者でもわかる安全なWebアプリの作り方
-
-