ぽかぽかコード日和

とっても暑い夏の日にプログラミングはじめました☀️

【Security】アクセス制御や認可制御の欠落+Laravel実装

概要

アクセス制御や認可制御の欠落とは、
認証や認可が不十分なために、攻撃者やユーザーが本来アクセスできないページに入り、情報を閲覧したり操作できてしまう状態のこと。

ログインできた(認証)後、ユーザーを識別して適切な権限を与える(認可)。
認証・認可を組み合わせて対策をする。


認証と認可の違い
  • 認証(Authentication)とは

    • ユーザーが本人であるかを確認する仕組み
      (パスワード認証、指紋認証、多要素認証(MFA)など)
    • 「アクセス制御の欠落」・・・認証(ログイン)しなくてもアクセスできてしまう状態。直接URLを指定すると誰でもログインした後のページに入れるなど。
  • 認可(Authorization)とは

    • 認証済みのユーザーに、なにをどこまで許可するかの権限を付与する。
      (ファイルの閲覧や端末の制限など)
    • 「認可制御の欠落」・・・本来許可されていないページにアクセスできてしまう状態。他人のデータを閲覧・編集できてしまうなど。


発生しうる脅威

アクセス制御の欠落による脅威

  • 情報漏洩、不正操作、データ改ざん
  • 本来権限を持たないユーザーによる不正ログイン
  • 認証を経ずに直接URLを指定することで、誰でもログイン後のページにアクセスできる

認可制御の欠落による脅威

  • 他人の情報を参照・操作(クエリパラメータ改ざんによるIDOR)
  • 低権限ユーザーが本来できない操作を実行できる(権限昇格)

☀︎IDOR(Insecure Direct Object Reference)とは、
ユーザーIDなどをURLに直接指定することで、他人のリソースにアクセスできてしまう脆弱性のこと。

原因

認証・認可の実装や設計の不足

対策

根本的解決

1.ユーザー入力値のバリデーションは必ずサーバー側で行う。

クライアント側だけでなく、サーバー側で厳格にバリデーションして不正なデータや攻撃を防ぐ

2.認証にパスワードなどの入力を必要とする

メールアドレスなど公開されやすい情報だけではなく、秘密情報を使って本人確認をする。

3.利用者IDをURLやPOSTパラメータに埋め込まない

他のユーザーにIDを推測されるため、IDを推測困難な値にする。
サーバー側で「そのユーザーがそのリソースにアクセスする権限があるか」を必ず認可チェックする。

4.メニューの表示/非表示だけで制御しない

クライアント側の画面上でメニューを非表示にしても、URLやパラメータを知っていれば権限がなくても操作できてしまう。
サーバー側での認可チェックが必須。

Laravel実装例

1.Laravel Breezeなどのパッケージを使う(認証)

Laravelが提供しているパッケージ使って、
ユーザー登録やログイン、パスワードリセットなどの機能を設定する。

composer require laravel/breeze --dev
php artisan breeze:install
npm install && npm run dev
php artisan migrate

2.パスワードを暗号化する(認証)

Laravelではデフォルトでパスワードを暗号化し、ハッシュ化して保存する。

//パスワードを暗号化してDBに保存
$password = Hash::make('your-password') 

//ログイン時にハッシュファザードで認証
if (Hash::check('your-password', $storedPassword)) { 
 // パスワードが一致しているときの処理
}

3.ポリシーやゲートを使う(認可)

ポリシー(Policy)で、
そのユーザーがそのリソースにアクセスできる権限を持っているか確認する。

モデルのファイルでポリシーを定義する

public function update(User $user, Post $post) {
  // ユーザーが投稿のオーナーなら編集可能とする処理
   return $user->id === $post->user_id;
}

コントローラーのファイルでポリシーを使用する

class PostController extends Controller
{
$this->authorize('update', $post);
}
  • ゲート(Gate)は、シンプルな認可制御。管理者ページではない個人のページへの権限を確認する。
  • ポリシーやゲートで認可したあと、authorizeメソッドで判定(認可確認)をする。

参考にしたサイト