LaravelのXSS対策で意識することをまとめます。
要点
1、htmlのタグ内ではダブルクオテーションで囲う
<input value="{{ $text }}">
2、フロントに文字列を渡す時は、htmlspecialcharsでサニタイズする
htmlのタグ内ではダブルクオテーションで囲う
ダブルクオテーションで囲わないと予期せぬ属性が追加されてしまう。
実行例
TestController.php
class TestController extends Controller
{
public function index()
{
$text = "test onclick=alert(1);";
return view('tests.test', compact('text'));
}
}
test.blade.php
<input type="text" value="{{$text}}"> {{-- 正しい --}}
<br>
<br>
<input type="text" value={{$text}}> {{-- 誤り --}}
結果
クオテーションで囲まない方はonclick属性が追加できてしまった。
フロントの言語に変数を渡す時は、htmlspecialchars関数でサニタイズする
実行例
ボタンを押下したらlogが出力される機能を作成
{{-- ボタン(onclick属性) --}}
<button onclick="test({{$text}})">ボタン</button>
{{-- js --}}
<script>
function test(text){
console.log(text);
}
</script>
渡すテキスト
$text = "test' onclick=alert(1);";
・シングルクオートあり
・()あり
出力されたログ
エラー
Uncaught SyntaxError: missing ) after argument list (at
修正例
{{-- シングルクオテーションで囲むことで()が文字列として扱われる --}}
{{-- さらにhtmlspecialchars関数でシングルクオテーションをサニタイズする --}}
<button onclick="test('{{htmlspecialchars($text,3)}}')">ボタン</button>
出力結果
test' onclick=alert(1);
サニタイズする前の文字列を表示したい場合はjs側で処理する必要あり。
今回は範囲外とします。
追加
別パターン:json形式で渡す
blade.html
<button onclick="test2( {{ json_encode(['text' => $text], JSON_HEX_TAG | JSON_HEX_AMP) }} )">ボタン</button>
script.js
function test2(text){
console.log(text.text);
}
出力結果
test' onclick=alert(1);
渡したテキストがそのまま取れました。これが一番良さそうです。
上司が教えてくれました。感謝。