44
37

More than 3 years have passed since last update.

[Laravel] XSS,CSRF,SQLインジェクションまとめ

Last updated at Posted at 2021-06-20

はじめに

初学者が学ぶべきセキュリティ攻撃である、XSS,CSRF,SQLインジェクションについて、Laravelではどのように対策がされているのか、今一度おさらいしてみた。

検証環境

  • macOS Catalina ver 10.15.7
  • Docker ver 20.10.5
  • docker-compose ver 1.29.0
  • Laravel ver 7.30.4
  • MySQL ver 8.20.3

XSS(クロスサイトスクリプティング)

XSSとは何か

3分でわかるXSSとCSRFの違いに書いてあるように「ユーザーがWebページにアクセスすることで不正なスクリプトが実行されてしまう脆弱性または攻撃手法」です。こちらの記事は大変わかりやすいので、ぜひ一読してください。
XSS対策のポイントは「特殊文字(< や > や " など)をエスケープする」ことです。そうすることでスクリプトではなく、単なる文字列として扱うことになるため、意図しない処理を防ぐことができます。
エスケープするためにはhtmlspecialchars関数を用います。

index.php
$script = "<script>window.alert('hello world')</script>";
$script = htmlspecialchars($script,ENT_QUOTES,"UTF-8");

echo $script; // エスケープされるためalertは実行されない

Laravelではどのように対策しているのか

PostController.php
public function create()
    {
        $script = "<script>window.alert('hello world')</script>";
        return view('posts.create',compact(
            'script'
        ));
    }
posts/create.blade.php
{{ $script }} // エスケープされるためalertは実行されない
{{!! $script !!}} // ちなみに両端「!!」の場合は、alertが実行されますので注意です

ドキュメントにも書いてある通り、{{ 変数 }}とすることでhtmlspecialchars関数が適用されます。

CSRF(Cross Site Request Forgeries)

脆弱なサイトと罠サイトを実際に作って学ぶ『CSRF』とその対策に書いてあるように「『罠サイト』から『標的サイト』へ HTTP リクエストを送信することで『標的サイト』を操作してしまおうという攻撃手法」です。
どのような被害が生まれるのかについて、上記記事でご確認ください。
CSRF対策のポイントは「リクエストが送信先が想定しているリクエストかどうか」です。
そのためリクエストを送信する側とそのリクエストを受信する側で合鍵のようなものを持っておけば、正しいリクエストかどうかわかるわけです。

Laravelではどのように対策しているのか

input.blade.php
<form action="" method="POST">
    @csrf
</form>

この@csrf

<input type="hidden" name="_token" value="ランダムな文字列">

に置換され、このvalueを用いて正しいリクエストであるか否かを確認しているというわけですね。
まさに合鍵の役割を果たしています。

SQLインジェクション

【 Laravel 】クエリビルダ と Eloquent ORM の違いを整理!に書いてあるように、SQLインジェクションとは悪意のあるユーザーが不正なクエリ( データベースへの命令文 )を書き、データベースへアクセスしてデータの漏洩・改ざんを行う攻撃のことです。
SQLインジェクションのポイントは

  • XSSと同様にエスケープ処理をする
  • ユーザによる入力値を必要とするクエリはプリペアードステートメント(静的プレースホルダ)を用いる

です。
プリペアードステートメント?ってなられた方は安全なSQLの呼び出し方をご覧ください。

Laravelではどのように対策しているのか

先ほど紹介させていただいた【 Laravel 】クエリビルダ と Eloquent ORM の違いを整理!に書いてあるように、SQLインジェクション対策は基本的になされているが、DB::rawなどの素のSQL文を使用するときは注意が必要です。
この点について、ドキュメントにもきちんと書かれています。
例えば以下のコードを見てみましょう。

PostController.php
public function store(Request $request)
{
    // 悪意のあるユーザによって送られてきたid
    $id = '5; delete from posts'; 
    $posts = DB::table('posts')->whereRaw("id = ${id}")->get();

}

こんなコードを書くことはまずありませんですが、この場合はpostsテーブルのデータが全て削除されてしまいます。
続けて、

PostController.php
public function search(Request $request)
{ 
    // ユーザによって検索がかけられた値
    $word = "果汁100%"; 
   // 正しくエスケープされないためエラー
    $results = DB::table('posts')->whereRaw("content like %${word}%")->get(); 
    // 正しくエスケープされる
    $results = Post::where("content","like","%${word}%")->get(); 

    return view('posts.search',compact(
        'results'
    ));
}

このようにエスケープ処理を行っていないためSQLインジェクションの脆弱性を生む原因となってしまいます。
よってDB::rawなどの素のSQL文を使用するときは、エスケープ処理をして、しっかり対策を取らなければならないことがわかります。
rawメソッドをどうしても使わなければならない時は注意して使いましょう。

さいごに

いかがだったでしょうか。
初学者が押さえておくべきセキュリティについて、Laravelではどのように対策を行っているのかを見てきましたが、普段それらを特に意識することなく、開発することができる点はやはりLaravelのすばらしい点だと思います。
一方で、「Laravelを使っていても、セキュリティ対策は不完全である」こともお分かりいただけたと思います。
Laravelでできることはフル活用して、できないことは補うようにしてセキュリティ対策をしていきたいですね。

参考サイト

44
37
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
44
37