🛡️

LaravelでXSS脆弱性があるフォームを作って修正してみた

2024/11/12に公開

はじめに

XSS(クロスサイト・スクリプティング)について調べたのでメモとして残します
XSS脆弱性があるシンプルなフォームを作って実際に攻撃をし、その後に直す手順を書いています
この記事では文字入力の際に起きるXSS攻撃だけ書いており、HTML属性から攻撃するパターンなどは書いていません

対象読者

セキュリティ初心者
Laravelを使っている方

事前準備

以下を用意します。フォームに入力された文字を出力するだけです

XssController.php
public function showForm()
{
    return view('form');
}

public function showOutput(Request $request)
{
    $input = $request->input('user_input');
    return view('output', ['user_input' => $input]);
}
routes/web.php
Route::get('/xss', [XssController::class, 'showForm']);
Route::post('/xss', [XssController::class, 'showOutput']);
form.blade.php
<form action="/xss" method="POST">
    @csrf
    <textarea id="user_input" name="user_input" rows="5"></textarea>
    <button type="submit">送信</button>
</form>
output.blade.php
<!-- 改行も可能にする -->
<p>{!! nl2br($user_input) !!}</p>

実行

  • 文字を入力して送信します

    • 問題なく表示できています
  • 次は<script>alert('XSSテスト');</script> と入力して送信します

    • すると以下のようにscript内の処理が実行されてしまいます!!

このようにエスケープ処理がされていないと、ブラウザがscriptをコードとして理解し実行できてしまいます。そのため、不正ログインなどの不正操作などが起きる可能性がありとても危険!!

対処法:エスケープ処理をする

上記のoutput.blade.phpは改行をするためエスケープ処理を無効化しているため
{!! nl2br(e($user_input)) !!} と書き換えてエスケープをさせます

ただの文字列変換してから改行タグのみ変換することで問題が解決しました

細かい動き

  1. e()でhtmlspecialchars()が実行され、ただの文字列に変換されます

    php artisan tinker
    >  e("<br>");
    = "&lt;br&gt;"
    
    > htmlspecialchars("<br>");
    = "&lt;br&gt;"
    
  2. nl2brで改行文字 \r\n、 \n\r、\n および \r の前に <br /> が追加されます

    php artisan tinker
    > nl2br("\r\n")
    = "<br />\r\n"
    
    > nl2br("\n")
    = "<br />\n"
    
  3. その2つを組み合わせる

    php artisan tinker
    > $escapedStr = e("<script>alert('XSSテスト');</script>\nテスト")
    = """
      &lt;script&gt;alert(&#039;XSSテスト&#039;);&lt;/script&gt;\n
      テスト
      """
    
    > nl2br($escapedStr)
    = """
      &lt;script&gt;alert(&#039;XSSテスト&#039;);&lt;/script&gt;<br />\n
      テスト
      """
    

これによって、ユーザー入力が無害化されつつ、改行が反映されるので問題が解決しました

最後に

XSS脆弱性の報告件数は多く、それだけ対応が難しいと思うがもれなく対応できるようにしなければ
これ以外にも攻撃パターンはあるので、そちらも調べてまとめます!

参考

Discussion