2/17以降にGoogle Chromeを使って、
「①あるドメインのURL」→(POST or GET)→
「②別ドメインのURL」→(POST)→
「③元のドメインのURL」
の順でページ遷移した場合、セッションが切れるように仕様が変わる事が判明したので、
対応方法をメモ。
(例:リンク型決済サイト等を利用して、クレカ決済の部分だけ他社サービスを利用している場合等)
#発生する現象
2/17までのChromeでは、上記のように
「①あるドメインのURL」→(POST or GET)→
「②別ドメインのURL」→(POST)→
「③元のドメインのURL」
の順でページ遷移をした場合でも、③の時点で①のセッションが切れずに残っています。
その理由は、①の時点でCookieに保存されたセッション用キーが、③の際にもサーバ側に送信されているからです。
今回、この挙動が変わり、SameSiteという属性をNoneに設定していないCookieについては、③の際に元のドメインのサーバに送信されなくなります。
すると、元のドメインのサーバ側では③のリクエストが①のリクエストど同一セッションである判定ができませんので、
セッション切れと同じ状態となります。
この変化は、以下の理由によります。
サーバ側では、Cookieに保存されたセッション管理用のキーをブラウザからサーバに送信してもらう事で同一セッションかを判別しています。
Cookieに「SameSite」という属性が明示的に指定されていない場合、
2/17までのGoogle Chromeではデフォルトが「SameSite=None」を指定した場合と同じ挙動をしていました。
「SameSite=None」では、あるドメインのサイトから別ドメインのURLにPOSTやGETで遷移する場合でも、
遷移先のドメインで設定したCookie情報をHTTPヘッダーに入れて送信してくれるので、
遷移先のドメインで既にセッション管理している場合は、そのセッション情報を引き続き利用する事ができました。
これは、「ユーザーがあるサイトにログイン中である場合、第3者が作成した別サイトから、そのサイトに対してログイン中のセッションを使ってPOSTリクエストを送る事ができる」
事を意味しており、CSRF攻撃を可能とする危険性を持った仕様です。
その属性が、2/17日以降、Chrome 80ではデフォルトで「Lax」を指定した場合と同じ動作に変わります。(一度にすべてのChromeで変わるのではなく、徐々に対象を拡大するようです)
「SameSite=Lax」は「GETの場合は遷移先ドメインが管理しているCookie情報を一緒に送信しても良いが、POST等、特定の条件ではダメ」という指定です。
その結果、「SameSite」属性を明示的に指定していないサイトは、CSRF攻撃に対して安全性が高まりますが、
半面、リンク型決済サイト等、別ドメインのページから決済完了画面にPOSTで遷移する機能を利用するECサイトでは、
セッションを維持するためのCookieが決済サイトへの遷移する前とは異なる値になってしまい、
同一セッションとして処理する事ができなくなります。
#事前の検証方法
1:Chromeで以下の設定ページを開きます。
chrome://flags/
2:設定の中から、「SameSite by default cookies」と「Cookies without SameSite must be secure」を「Enabled」に切り替えてChromeを再起動します。
これで、2/17以降のChromeのデフォルトと同じ動作になるはずです。
3:ChromeでF12ツールを開き、「Application」タブの左メニューで「Cookies」を開きます。
※JSESSIONIDについては、フィルターに「SESSION」等を入れれば絞り込めます。
4:JSESSIONIDが、決済サイトへの遷移前と、戻って来た時とで違っていたら、セッションは切れています。
#対応方法
Cookie「JSESSIONID」にSameSite=None属性をつければ、現行のデフォルトと同じ動作となるので、セッション切れを回避できます。
ただし、このCookieは自動で作成されているので、何らかの方法で割り込んでSameSite=Noneを付ける必要があります。
サーバがApacheでTomcatに連携している場合、
以下の方法でサーバ側の対応を行えば、SameSite=None属性をCookieに追加することができます。
□概要
mod_headers.soを使って、Apache→Tomcatの連携部分の設定に、
Cookieに一律SameSite=Noneを設定する指定を追加します。
以下に手順を書きます。
1:Apache→Tomcatの連携部分の設定ファイルを開きます。
※「/etc/httpd/conf.modules.d/00-proxy.conf」または、
「/etc/httpd/conf.d/proxy_ajp.conf 」等
2:各転送設定を以下のように変更します。
□変更前:
ProxyPass /{アプリケーション名}/ ajp://localhost:8009/{アプリケーション名}/
□変更後:
<Location /{アプリケーション名}/> ProxyPass ajp://localhost:8009/{アプリケーション名}/ Header edit Set-Cookie ^(.*)$ $1;Secure;SameSite=None </Location>
3:Apacheを再起動します。
以上