Project

General

Profile

Bug(バグ) #2534

管理画面: 招待メール送信からメンバー登録をおこなうと他人のメールアドレスが登録されてしまう場合がある

Added by Kiwa Sakai about 8 years ago. Updated about 4 years ago.

Status:
Fixed(完了)
Priority:
Urgent(急いで)
Assignee:
Target version:
Start date:
2011-10-19
Due date:
% Done:

100%

3.6 で発生するか:
Yes (はい)
3.8 で発生するか:
Unknown (未調査)

Description

Overview (現象)

管理画面:招待メール送信画面 (/pc_backend.php/member/invite)から複数のメールアドレスに対して招待をおこなうと、全てのデータ同じメンバーIDに登録され、有効なtokenをもつ招待メールが最後の一通のみとなる(携帯メールアドレスを含む場合は最後に記載されていた携帯メールアドレス宛のものになる?)。

同じメンバーIDに情報が登録されることで、以下の情報が同じメンバーのものとして扱われる。

  • PCメールアドレスのなかで最も下の行に記載されていたメールアドレス
  • 携帯メールアドレス(mobile_address_pre が複数登録される)

このため、最終行が携帯メールアドレスだった場合(もしくは、送信内容に携帯メールアドレスが含まれる場合?)、携帯で受け取ったメールアドレスを pc_frontend から登録すると、登録されるメールアドレスが他人のものになる。

現象再現手順

1. 招待メール送信画面を表示 (/pc_backend.php/member/invite)
2. 以下のようにメールアドレスを複数入力する

sakai+test1@tejimaya.com
senpai.so903@docomo.ne.jp
sakai+test2@tejimaya.com
kiw1540mm@docomo.ne.jp

2 の時点で4つのメールアドレスに招待メールが飛ばされるが、有効なtokenをもつ招待メールは kiw1540mm〜 宛のみ。
member_config のデータは以下のようになっている。

mysql> select * from member_config where member_id=22;
+-----+-----------+----------------------+------------------------------------+----------------+----------------------------------+---------------------+---------------------+
| id  | member_id | name                 | value                              | value_datetime | name_value_hash                  | created_at          | updated_at          |
+-----+-----------+----------------------+------------------------------------+----------------+----------------------------------+---------------------+---------------------+
| 142 |        22 | pc_address_pre       | sakai+test2@tejimaya.com           | NULL           | 97e8f0a409830627773610b4909180b5 | 2011-10-20 15:55:21 | 2011-10-20 15:55:22 |
| 143 |        22 | pc_address_token     | 5cf2a5b8040e0aac61fce6797c84ee97   | NULL           | 696ba1b398296980b5b8f6901e7a90d5 | 2011-10-20 15:55:21 | 2011-10-20 15:55:22 |
| 144 |        22 | register_token       | 225b6865c323a1931085e4d7184c66710d | NULL           | 37c681aa93e35f48f7c9a5b06007dd66 | 2011-10-20 15:55:21 | 2011-10-20 15:55:25 |
| 145 |        22 | register_auth_mode   | MailAddress                        | NULL           | fba890f9ba38ac0b250c1d2f2fc42afc | 2011-10-20 15:55:22 | 2011-10-20 15:55:22 |
| 146 |        22 | is_admin_invited     | 1                                  | NULL           | eb60f13757f1516e0031606640744834 | 2011-10-20 15:55:22 | 2011-10-20 15:55:22 |
| 147 |        22 | mobile_address_pre   | senpai.so903@docomo.ne.jp          | NULL           | 7c59d17726cd5398a8a00be873b7cd11 | 2011-10-20 15:55:23 | 2011-10-20 15:55:23 |
| 148 |        22 | mobile_address_token | 63280c310c45aa09319df583366611ca   | NULL           | c9d1952bb0a82c9137c1df0e11e446da | 2011-10-20 15:55:23 | 2011-10-20 15:55:23 |
| 149 |        22 | mobile_address_pre   | kiw1540mm@docomo.ne.jp             | NULL           | 7bcacac9ecdb4e0c0021941afcd4f0ba | 2011-10-20 15:55:24 | 2011-10-20 15:55:24 |
| 150 |        22 | mobile_address_token | 3cf29cc3889867ef3b72e6ef126b0556   | NULL           | 0afadaac6b87170b1b8e56470957ae67 | 2011-10-20 15:55:25 | 2011-10-20 15:55:25 |
+-----+-----------+----------------------+------------------------------------+----------------+----------------------------------+---------------------+---------------------+

3. kiw1540mm〜 におくられてきたメールをPCに転送し、PCからメンバー登録をおこなう
4. sakai+test2〜 のメールアドレスでメンバー登録が完了し、 sakai+test2〜 宛にメンバー完了通知が届く
メンバー登録完了後の member_config は以下のとおり。

mysql> select * from member_config where member_id=22;
+-----+-----------+----------------------+------------------------------------+---------------------+----------------------------------+---------------------+---------------------+
| id  | member_id | name                 | value                              | value_datetime      | name_value_hash                  | created_at          | updated_at          |
+-----+-----------+----------------------+------------------------------------+---------------------+----------------------------------+---------------------+---------------------+
| 142 |        22 | pc_address           | sakai+test2@tejimaya.com           | NULL                | 5daba3b9e300785c2d7f2b32766a2d27 | 2011-10-20 15:55:21 | 2011-10-20 15:58:41 |
| 144 |        22 | register_token       | 225b6865c323a1931085e4d7184c66710d | NULL                | 37c681aa93e35f48f7c9a5b06007dd66 | 2011-10-20 15:55:21 | 2011-10-20 15:55:25 |
| 145 |        22 | register_auth_mode   | MailAddress                        | NULL                | fba890f9ba38ac0b250c1d2f2fc42afc | 2011-10-20 15:55:22 | 2011-10-20 15:55:22 |
| 146 |        22 | is_admin_invited     | 1                                  | NULL                | eb60f13757f1516e0031606640744834 | 2011-10-20 15:55:22 | 2011-10-20 15:55:22 |
| 147 |        22 | mobile_address_pre   | senpai.so903@docomo.ne.jp          | NULL                | 7c59d17726cd5398a8a00be873b7cd11 | 2011-10-20 15:55:23 | 2011-10-20 15:55:23 |
| 148 |        22 | mobile_address_token | 63280c310c45aa09319df583366611ca   | NULL                | c9d1952bb0a82c9137c1df0e11e446da | 2011-10-20 15:55:23 | 2011-10-20 15:55:23 |
| 149 |        22 | mobile_address_pre   | kiw1540mm@docomo.ne.jp             | NULL                | 7bcacac9ecdb4e0c0021941afcd4f0ba | 2011-10-20 15:55:24 | 2011-10-20 15:55:24 |
| 151 |        22 | secret_question      | 1                                  | NULL                | 388f9fd417f5cc3e8f0fdf68c16b8b9f | 2011-10-20 15:58:41 | 2011-10-20 15:58:41 |
| 152 |        22 | secret_answer        | 098f6bcd4621d373cade4e832627b4f6   | NULL                | eb308689eafa0f3aaddc10b8960b8d06 | 2011-10-20 15:58:41 | 2011-10-20 15:58:41 |
| 153 |        22 | age_public_flag      | 3                                  | NULL                | 5a988ab486eb640588b479e1c0155045 | 2011-10-20 15:58:41 | 2011-10-20 15:58:41 |
| 154 |        22 | password             | 5f4dcc3b5aa765d61d8327deb882cf99   | NULL                | 927246e0e2492bb1c4334e89edfa252f | 2011-10-20 15:58:41 | 2011-10-20 15:58:41 |
| 155 |        22 | mail_address_hash    | 4ivf7soaf6rv                       | NULL                | e435e5b97398ffb458bb6b591bcdf337 | 2011-10-20 15:58:41 | 2011-10-20 15:58:41 |
| 156 |        22 | lastLogin            |                                    | 2011-10-20 15:58:49 | 83f893f513b36f24c7bbdf4839c518b0 | 2011-10-20 15:58:44 | 2011-10-20 15:58:49 |
+-----+-----------+----------------------+------------------------------------+---------------------+----------------------------------+---------------------+---------------------+

確認バージョン

OpenPNE 3.6.0

Causes (原因)

Way to fix (修正内容)


Related issues

Related to OpenPNE 3 - Backport(バックポート) #2713: 管理画面: 招待メール送信からメンバー登録をおこなうと他人のメールアドレスが登録されてしまう場合がある Fixed(完了) 2011-10-19

Associated revisions

Revision 739ac9b0 (diff)
Added by Yuya Watanabe almost 8 years ago

(fixes #2534) fixed admin invite form to add correct member pre

Revision d249cd6e (diff)
Added by Yuya Watanabe over 7 years ago

(fixes #2534) fixed admin invite form to add correct member pre

History

#1 Updated by Kiwa Sakai about 8 years ago

  • Description updated (diff)

現在までの確認の限りでは悪意をもったユーザが意図的に操作できる問題ではなさそうですが、念の為セキュリティイシューにさせてもらいました。

#2 Updated by Yuya Watanabe about 8 years ago

原因

#1816 でのコミット b6471e84 によって追加された以下の部分が正しくない.
具体的には,すべてのMemberが新規登録の場合,$this->validateAddress('pc_address', $value)がtrueになるため一回もcreatePre()が実行されずに現在ある$this->memberの一つを用いてmember_configへの記録が行われる.
また,$this->memberに既存のMemberオブジェクトを取得する処理が行われないため,すでに登録されているメンバのアドレスの前後に記載したアドレスに影響を与える可能性がある.
追記:validateAddress()内で$this->memberを更新する処理があるため,問題ないと考えられる.

apps/pc_backend/modules/member/lib/AdminInviteForm.class.php 76行目,87行目

 73 
 74     foreach ($this->getValue('pc') as $value)
 75     {
 76       if (!$this->validateAddress('pc_address', $value))
 77       {
 78         $this->member = Doctrine::getTable('Member')->createPre();
 79       }
 80       $this->saveConfig('pc_address', $value);
 81       $this->member->setConfig('register_auth_mode', $authMode);
 82       $this->member->setConfig('is_admin_invited', true);
 83     }
 84 
 85     foreach ($this->getValue('mobile') as $value)
 86     {
 87       if (!$this->validateAddress('mobile_address', $value))
 88       {
 89         $this->member = Doctrine::getTable('Member')->createPre();
 90       }
 91       $this->saveConfig('mobile_address', $value);
 92       $this->member->setConfig('register_auth_mode', $authMode);
 93       $this->member->setConfig('is_admin_invited', true);
 94     }
 95 

#3 Updated by Yuya Watanabe about 8 years ago

修正案

diff --git a/apps/pc_backend/modules/member/lib/AdminInviteForm.class.php b/apps/pc_backend/modules/member/lib/AdminInviteForm.class.php
index 4eda478..9e69235 100644
--- a/apps/pc_backend/modules/member/lib/AdminInviteForm.class.php
+++ b/apps/pc_backend/modules/member/lib/AdminInviteForm.class.php
@@ -71,26 +71,33 @@ class AdminInviteForm extends InviteForm
     $authMode = $authModes[$this->getValue('auth_mode')];
     $this->setOption('authMode', $authMode);

+    $memberConfigTable = Doctrine::getTable('MemberConfig');
     foreach ($this->getValue('pc') as $value)
     {
-      if (!$this->validateAddress('pc_address', $value))
+      if ($this->validateAddress('pc_address', $value))
       {
-        $this->member = Doctrine::getTable('Member')->createPre();
+        if (!$memberConfigTable->retrieveByNameAndValue('pc_address_pre', $value))
+        {
+          $this->member = Doctrine::getTable('Member')->createPre();
+        }
+        $this->saveConfig('pc_address', $value);
+        $this->member->setConfig('register_auth_mode', $authMode);
+        $this->member->setConfig('is_admin_invited', true);
       }
-      $this->saveConfig('pc_address', $value);
-      $this->member->setConfig('register_auth_mode', $authMode);
-      $this->member->setConfig('is_admin_invited', true);
     }

     foreach ($this->getValue('mobile') as $value)
     {
-      if (!$this->validateAddress('mobile_address', $value))
+      if ($this->validateAddress('mobile_address', $value))
       {
-        $this->member = Doctrine::getTable('Member')->createPre();
+        if (!$memberConfigTable->retrieveByNameAndValue('mobile_address_pre', $value))
+        {
+          $this->member = Doctrine::getTable('Member')->createPre();
+        }
+        $this->saveConfig('mobile_address', $value);
+        $this->member->setConfig('register_auth_mode', $authMode);
+        $this->member->setConfig('is_admin_invited', true);
       }
-      $this->saveConfig('mobile_address', $value);
-      $this->member->setConfig('register_auth_mode', $authMode);
-      $this->member->setConfig('is_admin_invited', true);
     }

     return true;

#4 Updated by Kousuke Ebihara about 8 years ago

既にこの現象に遭遇している SNS において、画面からの操作によって妥当な状態にデータを変更する手段は存在しません。そのため、以下の SQL を実行することをアドバイスすることになると思います。

# 削除対象となる未登録メンバーを確認します (2020-01-01 00:00:00 は OpenPNE 3.6 にアップデートしてから、管理画面からの招待をおこなうまでの任意の日時に置き換えてください)
SELECT * FROM member WHERE id IN (SELECT member_id FROM member_config WHERE name = "is_admin_invited" AND value = "1" AND created_at > "2020-01-01 00:00:00") AND is_active = 0;

# 確認した未登録メンバーを削除します (2020-01-01 00:00:00 は OpenPNE 3.6 にアップデートしてから、管理画面からの招待をおこなうまでの任意の日時に置き換えてください)
DELETE FROM member WHERE id IN (SELECT member_id FROM member_config WHERE name = "is_admin_invited" AND value = "1" AND created_at > "2020-01-01 00:00:00") AND is_active = 0;

※登録済みメンバーの復旧方法は追って提示します

#5 Updated by Kousuke Ebihara about 8 years ago

# 削除対象となるメールアドレスおよび登録用トークンを確認します (2020-01-01 00:00:00 は OpenPNE 3.6 にアップデートしてから、管理画面からの招待をおこなうまでの任意の日時に置き換えてください)
SELECT * FROM member_config WHERE name IN ("mobile_address_pre", "pc_address_pre", "mobile_address_token", "pc_address_token") AND member_id IN (SELECT member_id FROM member_config WHERE name = "is_admin_invited" AND value = "1" AND created_at > "2020-01-01 00:00:00");

# 確認したメールアドレスおよび登録用トークンを削除します (2020-01-01 00:00:00 は OpenPNE 3.6 にアップデートしてから、管理画面からの招待をおこなうまでの任意の日時に置き換えてください)
DELETE FROM member_config WHERE name IN ("mobile_address_pre", "pc_address_pre", "mobile_address_token", "pc_address_token") AND member_id IN (SELECT member_id FROM member_config WHERE name = "is_admin_invited" AND value = "1" AND created_at > "2020-01-01 00:00:00");

この操作をおこなうと、指定した日時以降に設定変更から「携帯メールアドレス登録」もしくは「PCメールアドレス登録」をおこなおうとしたメンバーのうち、管理者からの招待状を経由して登録した者による手続きがすべて無効になります。そのため、実施後は「携帯メールアドレス登録」もしくは「PCメールアドレス登録」をやり直すように利用者に対して告知をおこなってください。

#6 Updated by Kousuke Ebihara about 8 years ago

この問題により生じうるリスクを以下にまとめます。

  • このチケットで説明されているような「このため、最終行が携帯メールアドレスだった場合(もしくは、送信内容に携帯メールアドレスが含まれる場合?)、携帯で受け取ったメールアドレスを pc_frontend から登録すると、登録されるメールアドレスが他人のものになる。」という手順を踏まれてしまうことで、他人のメールアドレスによる登録がおこなわれてしまう
  • 登録に使われなかったメールアドレスを本当に所有するユーザが、そのメールアドレスを使用して新規登録できなくなる

ここに示した以外のリスクは、確認した限りでは特に見つかりませんでした。

#7 Updated by Kiwa Sakai about 8 years ago

note-5 のSQLを(created_at の条件を削除して)実行してみましたが、エラーが発生してデータの削除に失敗しました。

DELETE文実行結果 (エラーが発生)

mysql> DELETE FROM member_config WHERE name IN ("mobile_address_pre", "pc_address_pre", "mobile_address_token", "pc_address_token") AND member_id IN (SELECT member_id FROM member_config WHERE name = "is_admin_invited" AND value = "1");
ERROR 1093 (HY000): You can't specify target table 'member_config' for update in FROM clause

SELECT文実行結果 (問題ない)

mysql> SELECT * FROM member_config WHERE name IN ("mobile_address_pre", "pc_address_pre", "mobile_address_token", "pc_address_token") AND member_id IN (SELECT member_id FROM member_config WHERE name = "is_admin_invited" AND value = "1");
+----+-----------+----------------------+----------------------------------+----------------+----------------------------------+---------------------+---------------------+
| id | member_id | name                 | value                            | value_datetime | name_value_hash                  | created_at          | updated_at          |
+----+-----------+----------------------+----------------------------------+----------------+----------------------------------+---------------------+---------------------+
| 27 |         5 | mobile_address_pre   | senpai.so903@docomo.ne.jp        | NULL           | 7c59d17726cd5398a8a00be873b7cd11 | 2011-10-21 16:26:16 | 2011-10-21 16:26:16 |
| 28 |         5 | mobile_address_token | c3a9264f890aa76aef1c9437329912b5 | NULL           | 2bdf6295e3b87b7add018385a655ab6b | 2011-10-21 16:26:16 | 2011-10-21 16:39:32 |
| 29 |         5 | mobile_address_pre   | kiw1540mm@docomo.ne.jp           | NULL           | 7bcacac9ecdb4e0c0021941afcd4f0ba | 2011-10-21 16:26:18 | 2011-10-21 16:26:18 |
+----+-----------+----------------------+----------------------------------+----------------+----------------------------------+---------------------+---------------------+
3 rows in set (0.00 sec)

#8 Updated by Minoru Takai about 8 years ago

note-7 についてですが、

mysql> DELETE FROM member_config WHERE name IN ("mobile_address_pre", "pc_address_pre", "mobile_address_token", "pc_address_token")
 AND member_id IN (SELECT member_id FROM member_config WHERE name = "is_admin_invited" AND value = "1");

ERROR 1093 (HY000): You can't specify target table 'member_config' for update in FROM clause

このエラーは「サブクエリ内の不正使用されたテーブル」の項に示されています。 http://dev.mysql.com/doc/refman/5.1/ja/subquery-errors.html

また、このエラーの概要と回避策については http://www.mysqlfaqs.net/mysql-faqs/Errors/1093-You-can-not-specify-target-table-comments-for-update-in-FROM-clause で次のように示されています。

「 UPDATE や DELETE 文では、対象とするテーブルと同一のテーブルをサブクエリー内で同時に参照することは MySQL ではできないので、そのようなことをしたい場合は、サブクエリーの中でもう一つサブクエリーをラップして temporary table として扱われるようにします」

つまり、 note-7 で示されている DELETE 文は、次のように書き換えることで実行できます。

DELETE FROM member_config WHERE name IN ("mobile_address_pre", "pc_address_pre", "mobile_address_token", "pc_address_token")
 AND member_id IN (SELECT member_id FROM (SELECT * FROM member_config WHERE name = "is_admin_invited" AND value = "1") AS tmp_member_config);

#9 Updated by Kiwa Sakai about 8 years ago

note-3 の修正ですが、軽く基本的な動作を確認した限りでは問題なさそうでした。正式の動作テストの参考になればと思います。

確認内容

確認バージョン: OpenPNE 3.6RC2

  • PCメールアドレス・携帯メールアドレスが混在する招待
    • PCメールアドレス・携帯メールアドレスで別々のメンバーを登録することができる
  • 携帯メールアドレスの招待URLをPCでひらく
    • 「この登録用URLは携帯電話専用です。」エラーメッセージが表示される
  • PCメールアドレスの招待URLを携帯でひらく
    • 「この登録用URLはPC専用です。」エラーメッセージが表示される
  • 招待メールアドレスのなかに既に登録されているメールアドレスが含まれる
    • エラーにならず、登録済みのメールアドレスが無視される
  • 招待メールアドレスのリストのなかに pre に登録されているメールアドレスが含まれる
    • pre に登録されているメールアドレスも無視される
  • 招待メールアドレスのリストのなかに空行が含まれる
    • エラーにならず、全てのメールアドレスあてにメールがおくられる
  • 招待メールアドレスのなかにメールアドレスではない文字列が含まれる
    • エラーにはならず、全ての(正しい)メールアドレス宛にメールが送られる
  • 400メールアドレスを一気に入力し、招待メールを送信する
    • 30秒程度でタイムアウトになり、60件程度までしかメールを送れない

(具体的な入力値については記録していませんでした)

#10 Updated by Kousuke Ebihara about 8 years ago

  • Priority changed from Normal(通常) to Urgent(急いで)
  • 3.6 で発生するか set to Yes (はい)
  • 3.4 で発生するか set to No (いいえ)

#11 Updated by Kousuke Ebihara about 8 years ago

  • Project changed from OpenPNE Security Issue to OpenPNE 3

#12 Updated by Yuya Watanabe almost 8 years ago

  • Target version set to OpenPNE 3.7.0

#13 Updated by Yuya Watanabe almost 8 years ago

  • Status changed from New(新規) to Accepted(着手)
  • Assignee set to Yuya Watanabe

note-3の修正内容を適用します.

#14 Updated by Yuya Watanabe almost 8 years ago

  • Status changed from Accepted(着手) to Pending Review(レビュー待ち)
  • % Done changed from 0 to 50

更新履歴 739ac9b0dd4f248e44d996490f66a4cc0af43b7f で適用されました。

#15 Updated by Kousuke Ebihara almost 8 years ago

  • Status changed from Pending Review(レビュー待ち) to Pending Testing(テスト待ち)
  • % Done changed from 50 to 70

#16 Updated by Youichi Kimura almost 8 years ago

  • Status changed from Pending Testing(テスト待ち) to Fixed(完了)
  • % Done changed from 70 to 100

テスト完了しました。

#17 Updated by kaoru n about 4 years ago

  • 3.8 で発生するか set to Unknown (未調査)

Also available in: Atom PDF