CodeIgniterのセキュリティ対策を完全ガイド!初心者が守るべき基本設定
生徒
「CodeIgniterでWebサイトを作ってみたいのですが、ハッカーとかに攻撃されないか心配です……。」
先生
「それはとても大切な視点ですね!Webサイトを公開するなら『セキュリティ対策』は絶対に欠かせません。CodeIgniterには、最初から身を守るための便利な道具がたくさん備わっているんですよ。」
生徒
「初心者でも、プロのような対策ができるんでしょうか?」
先生
「もちろんです。難しい仕組みをすべて丸暗記する必要はありません。まずは何をすべきか、基本のステップから順番に確認していきましょう!」
1. セキュリティ対策とは?なぜ必要なのか
Webアプリケーションにおけるセキュリティ対策とは、一言で言えば「悪い人から自分のサイトや利用者の情報を守るための鍵」のことです。インターネットの世界には、他人のサイトを壊したり、個人情報を盗み取ろうとしたりする悪いプログラム(攻撃)が常に飛び交っています。
もし対策を怠ると、あなたのサイトが勝手に書き換えられたり、ログインパスワードが流出したりといった大きなトラブルに繋がります。CodeIgniter(コードイグナイター)は、PHPという言葉で作られたWeb開発の「ひな形(フレームワーク)」ですが、このフレームワークにはあらかじめ強力な防護服のような機能が組み込まれています。これらを正しく「オン」にするだけで、初心者でも安全なサイトを作ることができるのです。
2. クロスサイト・リクエスト・フォージェリ(CSRF)を防ぐ
CSRF(シーサーフ)とは、利用者が気づかないうちに「勝手に投稿させられたり、パスワードを変えられたりする」恐ろしい攻撃です。例えば、あなたがSNSにログインしている状態で、悪い人が作った罠のボタンを押すと、勝手にあなたの名前で変な投稿がされてしまうといったイメージです。
CodeIgniterでは、この攻撃を防ぐために「合言葉(トークン)」を使います。フォームを送信するたびに、サーバーとブラウザで秘密の合言葉を照らし合わせ、一致しない場合は処理を拒否する仕組みです。設定ファイル(App.phpなど)でこの機能を有効にするだけで、あなたのサイトはぐっと安全になります。
以下は、CodeIgniterのフォーム作成機能を使って、自動的に合言葉(CSRFトークン)を埋め込む例です。これを使うだけで、難しい計算をせずにセキュリティを高められます。
// フォームを開くときに、自動でセキュリティ用の合言葉(トークン)を生成します
echo form_open('contact/send');
// 入力欄などの作成
echo form_input('user_name', '名前を入力してください');
// フォームを閉じます
echo form_close();
このコードを実行すると、HTML上では自動的に目に見えない「隠し入力欄」が作られ、そこに複雑な文字列(トークン)がセットされます。これが盾の役割を果たしてくれるのです。
3. クロスサイト・スクリプティング(XSS)とエスケープ処理
XSS(エックスエスエス)は、Webサイトの掲示板などに悪いプログラム(JavaScript)を書き込まれ、それを表示した他の利用者の情報を盗み取る攻撃です。例えば、名前を入力する欄に「画面を真っ白にするプログラム」を書き込まれると、サイトが壊れてしまいます。
これを防ぐ一番の方法は、ユーザーが入力した文字を「ただの文字列」として安全に処理することです。これをエスケープ(無害化)と言います。CodeIgniterでは「esc()」という便利な魔法の言葉(関数)が用意されています。これを使えば、たとえ攻撃コードが入力されても、単なるテキストとして表示されるだけなので安全です。
実際のコードで、どのように文字を安全に表示するか見てみましょう。
// ユーザーから送られてきたデータ(攻撃の可能性がある文字列)
$user_comment = "<script>alert('攻撃!');</script>";
// そのまま表示すると危険ですが、esc() を通せば安全な文字に変換されます
echo esc($user_comment);
実行結果は以下のようになります。プログラムとして動かずに、文字としてそのまま表示されるのがポイントです。
<script>alert('攻撃!');</script>
4. SQLインジェクションを防ぐ「クエリバインディング」
Webサイトでは、データベース(情報を貯めておく倉庫)からデータを取り出すことがよくあります。この倉庫に対して「データを全部消せ!」という不正な命令を送り込む攻撃がSQLインジェクションです。これを許すと、顧客データが盗まれたり、サイトが消滅したりするリスクがあります。
CodeIgniterでは、データベースへの命令文を組み立てる際、命令とデータを切り離して処理する「クエリバインディング」という手法を使います。これにより、データの中に含まれる「悪い命令」が実行されるのを防ぎます。
以下のコードは、安全にデータベースから特定のユーザーを探す方法です。直接変数を命令文に入れず、「?」を使って後からデータを当てはめるのがコツです。
// 探したいユーザーのID
$id = 10;
// 直接命令の中に変数を入れず、?(プレースホルダ)を使います
$sql = "SELECT * FROM users WHERE id = ? AND status = ?";
// 後から安全にデータを流し込みます(これがバインディング!)
$db->query($sql, [$id, 'active']);
こうすることで、もし$idの中に「10 OR 1=1(すべて表示せよ)」のような悪い命令が入っていても、単なる「10 OR 1=1」という名前のIDとして扱われるため、攻撃は失敗します。
5. パスワードの保存は必ず「ハッシュ化」する
ユーザーが登録したパスワードを、そのまま(生パスワード)の形で保存するのは絶対にNGです。万が一データベースの中身が盗まれたとき、全員のパスワードが丸見えになってしまうからです。そこで使うのがハッシュ化です。
ハッシュ化とは、パスワードを一度だけ「元に戻せない、でたらめな文字列」に変換することです。CodeIgniter(および現代のPHP)では「password_hash」という機能を使って、簡単に強力な暗号化が可能です。ログイン時には、入力されたパスワードと、保存されているハッシュ化された文字列が一致するかどうかだけを確認します。
パスワードを安全に処理するコードの例を見てみましょう。
// ユーザーが決めたパスワード
$password = "my_secret_123";
// パスワードをハッシュ化(暗号のようなものに変換)します
$secure_hash = password_hash($password, PASSWORD_DEFAULT);
// 画面に表示してみると、元のパスワードとは似ても似つかない文字列になっています
echo $secure_hash;
実行結果(一例)はこのようになります。毎回違う文字列が生成されるので、非常に安全です。
$2y$10$8f6S.A.pP/T7l9I6g6E5S.wN9oV5UqF5yG1p/kM.rR2...
6. フォームバリデーションで入力ミスを防ぐ
バリデーション(検証)とは、送られてきたデータが「正しい形式かどうか」をチェックすることです。例えば、メールアドレスの欄に電話番号が入力されていないか、必須の項目が空っぽになっていないかを調べます。これは使いやすさだけでなく、予期しないデータによるシステムの不具合(バグ)や攻撃を防ぐためにも重要です。
CodeIgniterには「Validationライブラリ」という強力な味方がいます。これを使えば、「この項目は10文字以上で、必ず数字でなければならない」といったルールを、一行書くだけで設定できます。ユーザーが間違えた場合には、自動的に「エラーメッセージ」を表示してくれるので、開発の手間も大幅に減ります。
// バリデーションのルールを決めます
$rules = [
'username' => 'required|min_length[5]',
'email' => 'required|valid_email',
];
// ルールを守っているかチェック!
if (!$this->validate($rules)) {
// 守られていない場合の処理(エラーを表示するなど)
echo "入力内容に間違いがあります。";
}
7. フォルダ構造と「public」フォルダの重要性
最後に、サーバー上のファイルの置き場所についてです。CodeIgniter 4以降では、インターネットから直接アクセスできるファイルを「public」というフォルダの中だけに制限しています。これは、プログラムの心臓部である設定ファイルやソースコードが、外部から勝手に覗かれないようにするための工夫です。
初心者の方がよくやってしまうミスは、すべてのファイルを誰でも見られる場所に置いてしまうことです。CodeIgniterのルールに従い、設定ファイルなどは「public」の外側にある「app」や「system」という場所に置くことで、物理的にファイルが盗まれるリスクを回避できます。この「見せたくないものは隠す」という物理的な隔離も、立派なセキュリティ対策の一つなのです。