クッキーを使った認証の流れについて

Railsにおける認証は、deviseというライブラリで簡単に実装できるため、曖昧な理解をしてきた。これを機に整理する。

多くのWebアプリケーションには何らかの認証システムがあります。ユーザーがユーザー名とパスワードを入力すると、Webアプリケーションはそれらをチェックして、対応するユーザーIDをセッションハッシュに保存します。以後、そのセッションは有効になります。リクエストが行われるたびに、Webアプリケーションはセッションで示されたユーザーidを持つユーザーを読み込みます。このときに再度認証を行なう必要はありません。セッションは、cookie内のセッションidによって識別できます。

Rails セキュリティガイド - Railsガイド より

RailsのデフォルトのセッションストレージはCookieStoreというものらしい。この場合、次のような挙動を示すらしい。

Webアプリケーション(認証時)

  • ユーザー名とパスワードをチェック
  • 暗号化したユーザーIDをCookieにSetしてレスポンスとして返す。

Railsのコードで言うとこんな感じ。最近のRailsでは、sessions[:user_id] = @user.id と書くだけでユーザーIDが暗号化されCookieに保存される。

Simple Authentication Guide with Ruby on Rails | by Reinald Reynoso | Level Up Coding より

def create
   @user = User.find_by(username: params[:username])
   if @user && @user.authenticate(params[:password])
      sessions[:user_id] = @user.id
      redirect_to '/welcome'
   else
      redirect_to '/login'
   end
end

CookieにSetしてレスポンスとして返す。と説明したが、具体的には、HTTPヘッダーの中に次のような値を埋め込んでブラウザに返しているだけである。

set-cookie: _myapp_session=ae15f864aecb1e9336a5e281.................................................; path=/

ブラウザ(認証が必要なページへのアクセス時)

ドメインとパスを元に、Cookieがある場合には、CookieをHTTPヘッダーに埋め込んでアクセスしている。

cookie: _myapp_session=ae15f864aecb1e9336a5e281.................................................

Webアプリケーション(認証が必要なページへのアクセス時)

ブラウザから送られてきたCookieを元に、Webアプリケーションは、ユーザーIDを復号化してユーザー情報を取得する。

User.find_by(id: session[:user_id])  

O365の条件付アクセスで、レガシー認証ブロック

レガシー認証をブロックする理由

  • IDとパスワードによる認証のみで、多要素認証ができないため。
  • MSがあと数年以内にレガシー認証によるアクセスを禁止しようとしているから。
  • ちなみにレガシー認証の例としては、POP、SMTPIMAPなど。メールプロトコルだけではなく、従来の Microsoft Office アプリからの認証にもレガシー認証がある。
  • なお、ほとんど(9割以上)の攻撃がレガシー認証によるもので、レガシー認証を禁止することでよりセキュアな運用が可能。
  • なお、条件付きアクセスによる判断は、第 1 段階認証が完了した後で適用される。DoS攻撃を防ぐものではないが、結果的に防げる(ってことでいい?)。

レガシー認証をブロックする方法

  • セキュリティの既定値群がONになっていれば、レガシー認証はすでにブロックされている。 2019 年 10 月 22 日以降に作成されたテナントの場合は、標準でONになっている。

docs.microsoft.com

  • Azure AD 条件付きアクセスでレガシー認証をブロックする設定にする。この場合、Azure AD Premium 1 以上のライセンスが人数分必要。

設定方法

  • セキュリティの既定値群をオフにして、条件付アクセスを利用できるようにする。
  • 条件付きアクセスでレガシー認証をブロックする。

docs.microsoft.com

テスト方法

コマンドで接続

だいぶ省略しているけど、TELNETでのPOP3アクセスと似た感じでPOP3でアクセスする。 ただ、O365は、995ポートで接続するため、接続用のクライアントをopensslのものにする必要がある。 レガシー認証がブロックされていれば、ログインが失敗する。

$ openssl s_client -connect outlook.office365.com:995 -crlf
USER foobar@example.onmicrosoft.com
PASS yourpassowrd
LIST
QUIT

リモート接続アナライザー

testconnectivity.microsoft.com

Win10端末でAzureADから抜けるのに手こずった

一台のパソコンにつき、一つの Azure AD にしか参加できないことを知らずに遊んでいたら、本命の Azure AD に参加できなくなった。 Windows 10の設定画面から解除しようと思ったけどうまくできなかった。次の方法で合ってるかわかんないけど とりあえずメモ程度に残しておく。

Azure AD の参加状態を確認する

dsregcmd.exe /status を実行して、AzureAdJoined の項目が YES になっていることを確認。色々やったけど、PCとしては参加しているということなんだろう。

> dsregcmd.exe /status
+----------------------------------------------------------------------+
| Device State                                                         |
+----------------------------------------------------------------------+
             AzureAdJoined : YES
          EnterpriseJoined : NO
…略…

Azure ADから抜ける

ハイブリッド Azure AD 参加済み Windows 10 および Windows Server 2016/2019 デバイスを再登録するには、次の手順を実行します。 管理者としてコマンド プロンプトを開きます。 「dsregcmd.exe /debug /leave」と入力します。

いろいろ試したため、これで抜けられたかどうかわからないが、多分これだと思う。

なりすましメールを防止する(Office365 DMARC編)

DMARCとは

なりすましメールの防止技術。

なりすましメールを受信サーバが検知した場合、DNSのDMARCレコードを見て、その後の対応を判断するプロトコル

設定方法

自身のDNSレコードにTXTレコードを追加する。 Office365側では特に設定は必要ない模様。 DMARCに関する詳細は、参考のリンク先を参考にしてください。

txt _dmarc v=DMARC1; p=none; pct=100; rua=mailto:dmarc@XXXX.XX; ruf=mailto:dmarc@XXXX.XX

確認方法

次のような文法チェッカーがあります。正しいDMARCになっているか確認してください。

dmarcian.com

参考

blog.kazuakix.jp

sendgrid.kke.co.jp

なりすましメールを防止する(Office365 DKIM編)

DKIMとは

なりすましメールを防止する技術。

送信元のメールサーバーが、秘密鍵から生成した署名を挿入する。

受信のメールサーバーが、DNSから取得した公開鍵によって署名を検証する。

もし、送信元のメールサーバーとDNSが異なれば(なりすましメール)であれば、署名の検証は失敗する。

Office365での設定方法

主に次の3つの手順で設定可能。

  1. DKIMキーの生成
  2. DNSレコードへの追加
  3. DKIMの有効化

1. DKIMキーの生成

Microsoft 365 管理センター」->管理センターの「セキュリティ」->「驚異の管理」->「ポリシー」->「DKIM

対象ドメインを選択し、「DKIMキーの作成」ボタンをクリックすると、CNAMEが発行される。

2. DNSレコードへの追加

Host Name : selector1._domainkey
Points to address or value: selector1-XXXX-onmicrosoft-com._domainkey.XXXX.onmicrosoft.com

Host Name : selector2._domainkey
Points to address or value: selector2-XXXX-onmicrosoft-com._domainkey.XXXX.onmicrosoft.com

上記のようなCNAMEが発行されるので、自身のDNSサーバーに登録する。

3. DKIMの有効化

1項「DKIMキーの生成」のページで有効化する。 DNSの設定には時間を要するので、1時間くらいほっておくと良い。

rails dbconsoleでDBサーバーに接続する

今更感があるけど、rails dbconsole を利用すると、Railsで設定しているDBに、接続できるんですね。

$ rails dbconsole
Enter password: 
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 25
Server version: 8.0.19 MySQL Community Server - GPL

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [hogedb_devel]> 

Railsのログをlogrotateする

Railsproduction.log などのログは、際限なく容量が増えるため、古いものから削除するなどの必要があります。これをログのローテーションと言います。

Linuxではlogrotateを使うことが一般的ですが、ローテーション後に、アプリケーションサーバーが新たにログを書き出せなくなる問題があります。これは、logrotateが新しいログファイルにした際に、アプリケーションサーバーが新しいログファイルの検知に失敗するために発生します。

この問題は、次のようにlogrotateのオプションに copytruncate を追加することで解決できます。このオプションは、新たにログファイルを作成するのではなく、ログをコピーして古いログをファイルの中身を空にするものです。

$ cat /etc/logrotate.d/my_rails_app
/var/www/my_rails_app/log/*.log {
  weekly
  missingok
  rotate 280
  compress
  delaycompress
  create 0664 ec2-user ec2-user 
  copytruncate
}

参考

copytruncate – Copy the log file and then empties it. This makes sure that the log file Rails is writing to always exists so you won’t get problems because the file does not actually change. If you don’t use this, you would need to restart your Rails application each time.

gorails.com

補足

ログのローテーション後に、pumaというアプリケーションサーバーに次のようなシグナルを送り、ログのリオープンを指示したが、うまく行きませんでした。

$ kill -HUP $puma_pid 

tech.basicinc.jp