Works by

Ren's blog

@rennnosuke_rk 技術ブログです

ユーザ情報に紐づく情報はセッションIDをもとに取得すべき

ここ一ヶ月仕事でフロントエンドの開発業務に携わっており、その流れでサーバサイドもいじるようになった。 その際、クライアント・サーバ間の情報のやり取りについて職場の先輩に指摘していただいたので、メモ。

結論から述べると

アカウント登録制のWebサービスにおいて、
サーバサイドでユーザ情報を元にDBからカラムを取得する場合、
(基本的に)サーバはクライアントから送信されたユーザ情報を使用すべきでない。

たとえば

一般的なオンラインショッピングサービスを例にとると、ユーザはアカウント登録・ログインを行った上で商品をカートに入れ、決済を行う。
当然、決済時にはユーザ情報(メールアドレスや住所等)やカート情報を参照する。
このとき、カート情報のテーブルの外部キーとしてユーザ情報の一意識別子(以下ユーザID)を設定しているものとする。

もし、クライアント側からユーザIDとともにリクエストが送信され、そのIDをもとにサーバがDBに問い合わせをするという実装の場合、どのようなリスクが考えられるだろう。


f:id:rennnosukesann:20180204160323p:plain

仮に二人のユーザAとBがいたとする。ユーザAはカートに商品を入れている状態である。 このとき、ユーザBがユーザAのIDを含むカート情報取得リクエストをサーバに送信することで、ユーザBはユーザAの カートの中身を参照できてしまう。
そのカート情報が単に商品情報だけ持っているのならいいが、個人を特定するに足る情報があったらどうだろう。


f:id:rennnosukesann:20180204161734p:plain

ユーザBがAのユーザIDを知るわけないだろうと思うかもしれないが、 ユーザBがサーバに適当な値を送信してしまえば、簡単に誰かしらのカートを盗み見ることはできる。

対処方法

この問題に対応するには、そもそもクライアントから任意のIDを指定できなくすれば良い。 すなわち、一つのユーザアカウントのリクエストに用いられるユーザIDが一意に定まる状態になればよい。

これを実現するには、クライアント・サーバ間のセッションを利用する。 クライアントがサービスにログインした時、サーバはクライアントとのセッションを確立し、 そのクライアント固有のセッションIDを発行、クッキーに含めてクライアントに送る。

そしてサーバはセッションIDをキーとしたユーザIDのハッシュテーブルを用意しておく。 クライアントからリクエストが来たときは、クライアントからユーザIDを受け取る代わりに、 セッションIDを用いてハッシューテーブルからユーザIDを引当てる。 こうすることで、クライアントはユーザIDを指定したカート情報の参照ができなくなる。


f:id:rennnosukesann:20180204163425p:plain

但し、このやり方を採用してもセッションハイジャックへの脆弱性が懸念される。 通信経路をSSLで暗号化するのはもちろんのこと、セッション情報の扱い方も気をつける必要がある。 (この辺についても別途調査したい)

さいごに

上記図でさくらのアイコンを使わせていただいた。 使いやすいアイコンが揃っていて、とっても助かりました。