ポイントサイト「ポイントインカム」の開発環境が不正アクセスを受け、運営するセレスが2026年11月6日に公表しました。閲覧された可能性があるのは、テスト用に保管されていた約11,100名分の会員情報です。前半は、自分は対象か、ログインできないときはどうするか、届いた連絡は本物かという会員の疑問に公式の文言で答えます。後半では会員サイトの開発者に向けて、本番データを列ごとにマスキングするSQLと、開発DBに実データが残っていないかを調べるPythonを実行結果つきで示します。
まとめ:ポイントインカム不正アクセスの3事象と会員がまず行うパスワード再設定
セレス関連で公表された事象は3つあり、件数を足すことはできません。
| 事象 | 件数 | 主な項目 | 公表日 |
|---|---|---|---|
| 10月の不正アクセス | 195件 | 項目は非公表 | 10月7日 |
| 開発環境の不正アクセス | 約11,100名 | メール・暗号化PWなど | 11月6日 |
| CoinTradeの委託先 | 88,289件 | メールアドレスのみ | 11月6日 |
対象の会員は、すでにログインを止められています。個別のメールで案内が届くので、パスワード再設定ページで新しいパスワードを設定します。当時と同じパスワードを他のサービスで使っているなら、そちらも変更してください。
本番サーバーへの侵入と最新の会員情報の閲覧は、確認されていないとのことです。セレスの発表文によれば、漏れた可能性があるのは2025年11月15日時点のバックアップでした。
ポイントインカム会員が確かめる対象範囲、パスワード再設定と偽連絡の見分け方
個別メールで分かる対象範囲と2025年11月15日時点のデータという条件
対象者にはメールで個別に連絡されます。発表文に、自分で照会するページの案内はありません。閲覧された可能性がある項目は次のとおりです。
- ニックネーム、登録メールアドレス、生年月日
- 当時のパスワードと秘密の質問(いずれも暗号化された文字列)
- 当時の保有ポイント数
- 一部の会員のみ:電話番号(16名)、口座名義(1名)
データは2025年11月15日時点のものです。それより後に登録した会員の情報は、理屈の上ではこのバックアップに入りません。ただ、発表文がそう明言しているわけではないので、心配なら問い合わせで確かめるのが確実でしょう。別に端末ID4件も対象ですが、氏名やメールアドレスは含まれず、利用者の対応は不要とされています。
ログイン停止を解くパスワード再設定と秘密の質問・SNS連携の設定し直し
約11,100名のアカウントはログインできない状態です。元のパスワードを入れても入れない場合は、次の順番で戻します。
- 再設定ページで新しいパスワードを設定する
- ログインして秘密の質問を設定し直す
- SNSログインを使う人は、連携を改めて設定する
新しいパスワードは、他社サービスと別の文字列にするよう発表文が求めています。再設定は、メール内のリンクより、ブラウザに pointi.jp の正しいアドレスを入れて開くほうが安全です。
「電話やSMSで聞かない」を基準にした偽連絡の判断と他社パスワードの変更順
セレスは「弊社から電話やSMSでパスワード等をお伺いすることはございません」と明記しました。電話やSMSでパスワードを聞かれたら、その時点で偽物と判断できます。ニックネームや生年月日、保有ポイントまで言い当てられても、本物の証拠にはなりません。閲覧された項目そのものだからです。
同じパスワードを使い回していたなら、メール、ネット銀行、決済サービスの順に変えます。メールを先にするのは、他社の再設定がメールで届くためです。漏れた組み合わせが他社で試される手口はパスワードリスト攻撃の検知と漏えい照合で、偽の連絡の仕組みはフィッシング詐欺の成立の仕組みと対策で解説しました。
補償の記載がない現状と、電話窓口がなくフォームで受ける問い合わせ先
11月6日の発表文に、補償やお詫びのポイントの記載はありません。保有ポイントが不正に交換されたという記述もなく、閲覧された可能性として挙げられているのは「当時の保有ポイント数」です。
会員向けの窓口はポイントインカムの問い合わせフォームです。発表文の末尾に載っている電話番号は広報担当の連絡先で、会員の窓口として案内されているのはフォームです。
10月の195件、11月の約1.1万人、CoinTradeの8万8,289件を区別する根拠
10月7日発表の195件と11月6日発表の約11,100名を混同しない理由
ポイントインカムでは、1か月前にも別の発表がありました。10月7日の発表では、10月5日未明から不審な挙動を断続的に検知し、会員88件と従業員等107件の計195件が閲覧された可能性があるとされています。
検知日も件数も違い、11月の発表文は10月の件に触れていません。両者の関連については公表されておらず、同じ攻撃者かどうかは不明です。10月時点の情報だけを載せたページを読むと「195件なら自分は関係ない」と誤解しかねません。
CoinTradeの8万8,289件はメールアドレスのみ、アララのrepica経由の流出
セレスの連結子会社マーキュリーが運営するCoinTradeの件は、経路がまったく別です。委託先が使うメール配信システム「repica」への不正アクセスで、10月8日から29日に配信されたメールの宛先88,289件が流出しました。氏名やパスワードは含まれず、メールアドレスだけでは口座にログインできないと説明されています。
配信サービス側のアララの第2報は、持ち出されたメールアドレスを約77百万件(精査中)としていました。その後の件数の動きと契約企業の作業は、アララの不正アクセスと契約企業の対応で追っています。
公表されていない侵入経路と暗号化の方式、続報で確かめる5項目
次の5つは未公表のため、この記事では推測しません。
- 開発環境への侵入経路と利用された弱点
- 「暗号化された文字列」の具体的な方式
- データを開発環境へ置いた時期と理由
- 10月の195件との関係
- 個人情報保護委員会への報告の状況
会員が特に見ておきたいのは2番目です。パスワードを保存する方式としては、復号できる暗号化と、元に戻せないハッシュ化で強さがまったく違います。違いはハッシュ化と暗号化の仕組みの解説にまとめました。
開発環境の本番データが狙われる構造と、NIST SA-3(2)が求める同等の保護
348日前のバックアップが示す、開発環境に個人データを置く期間の問題
バックアップの時点は2025年11月15日、検知は2026年10月29日。その差は348日あります。発表文の表現は「テスト・検証用として一時的に保管」ですが、いつ開発環境へ置かれたのかは書かれていません。
それでも開発者が受け止めるべき点は明確です。本番サーバーが無事でも、複製が別の場所にあれば、そこから同じ会員の情報が出ていきます。開発環境は担当者が多く、外部公開の検証やテスト用の認証情報が入りやすい場所でもあります。本番と同じ防御を想定できないなら、置くデータのほうを変えるしかありません。
NIST SA-3(2)の承認・記録と、本番と同じ水準の保護を求める2要件
NIST SP 800-53 Rev.5のSA-3(2)は、本番前の環境(開発、テスト、統合)で本番データを使うことについて、2つを求めています。利用を承認、文書化、統制すること。そして、その環境を本番データと同じ影響度の水準で保護することです。
日本の法令にも、開発環境を別扱いにする規定はありません。個人情報保護法ガイドライン(通則編)の10-6はアクセス制御と外部からの不正アクセスの防止を求め、10-5(4)は個人データの削除を復元不可能な手段で行うよう定めています。法22条の、不要になった個人データを遅滞なく消去する努力義務も同じです。検証が終わった複製は、この条文の「利用する必要がなくなった」データに当たります。
本番データを渡す前の列別マスキングとPostgreSQL Anonymizerの設定例
ポイントインカムの漏えい項目に対応させた列別のマスキング方針と代替値
今回の項目を例に、開発環境へ渡すときの扱いを列ごとに決めます。迷った列は消す側に倒すのが基本です。
| 列 | 開発環境での扱い |
|---|---|
| メールアドレス | 予約ドメインに置換 |
| パスワード | 全行を固定値に |
| 秘密の質問 | NULLにする |
| 生年月日 | 固定日に置換 |
| 電話番号・口座名義 | NULLにする |
| ニックネーム・端末ID | 乱数文字列に置換 |
| 保有ポイント | 乱数に置換 |
パスワードのハッシュを「読めないから」と残すのは誤りです。解析の材料になるうえ、検証環境でログインを試す必要があるなら、テスト用アカウントを別に作れば済みます。年齢で分岐する機能の試験は、固定日のままでなく、境界値の行を合成して足します。
隔離DBで静的マスキングを流すSQLと元データが破壊される点の注意
PostgreSQLなら拡張機能のPostgreSQL Anonymizerで、列ごとの規則を宣言できます。列名は自社の表に読み替えてください。関数名は公式のマスキング関数一覧のものです。
-- 本番の複製を置いた隔離DBでだけ実行する。元の値は破壊される
CREATE EXTENSION IF NOT EXISTS anon CASCADE;
SELECT anon.init();
SECURITY LABEL FOR anon ON COLUMN members.nickname
IS 'MASKED WITH FUNCTION anon.random_string(12)';
SECURITY LABEL FOR anon ON COLUMN members.email
IS 'MASKED WITH FUNCTION anon.dummy_safe_email()';
SECURITY LABEL FOR anon ON COLUMN members.password_hash
IS 'MASKED WITH VALUE $$masked$$';
SECURITY LABEL FOR anon ON COLUMN members.secret_answer
IS 'MASKED WITH VALUE NULL';
SECURITY LABEL FOR anon ON COLUMN members.birth_date
IS 'MASKED WITH VALUE $$1970-01-01$$';
SECURITY LABEL FOR anon ON COLUMN members.phone
IS 'MASKED WITH VALUE NULL';
SECURITY LABEL FOR anon ON COLUMN members.account_name
IS 'MASKED WITH VALUE NULL';
SECURITY LABEL FOR anon ON COLUMN members.points
IS 'MASKED WITH FUNCTION anon.random_int_between(0,50000)';
SELECT anon.anonymize_database();
ANALYZE;
このSQLは公式の構文に沿った例で、筆者の環境のPostgreSQLでは実行していません。検証用の複製で結果を確かめてから使ってください。
静的マスキングの公式ドキュメントは、この方法が元データを破壊すると警告しています。流す場所は本番ではなく、開発環境でもありません。本番と同じ権限で守った隔離DBに複製を戻し、マスキングを済ませてからダンプを取り、そのダンプだけを開発環境へ渡します。誤実行を避けるために、anon.static_masking を off にして無効化する設定も用意されています。ビューには規則が適用されない点も、同じページの注意事項です。
開発DBに残った実データを検出するPython検査と古いダンプを探すコマンド
実データの残存を終了コードで止めるPythonスクリプトと実行結果
マスキングの漏れは、手順書では防げません。列が増えたときに規則を足し忘れるからです。次のスクリプトは、列ごとに「残っていてはいけない値」を定義して検査し、違反があれば終了コード1を返します。標準ライブラリだけで動き、検証用の表をメモリ上に作るのでそのまま実行できます。
# 開発DBに本番由来の個人情報が残っていないかを検査する(Python 3.9以上・標準ライブラリのみ)
# 残っていれば終了コード1で止まるので、環境の払い出しやCIの最後に置ける
import argparse
import sqlite3
import sys
AT = chr(64) # アットマークの文字
SAFE_DOMAINS = ("example.com", "example.net", "example.org", "test", "invalid")
MASKED_HASH = "masked" # マスキングで全行に入れる固定値
def real_email(value):
domain = value.rsplit(AT, 1)[-1].lower()
return not any(domain == d or domain.endswith("." + d) for d in SAFE_DOMAINS)
def filled(value):
return True
# 表、列、違反とみなす条件。NULLは検査しない
RULES = [
("members", "email", real_email),
("members", "password_hash", lambda v: v != MASKED_HASH),
("members", "secret_answer", filled),
("members", "phone", filled),
("members", "account_name", filled),
]
def seed(db):
db.execute("CREATE TABLE members (id INTEGER PRIMARY KEY, email TEXT, "
"password_hash TEXT, secret_answer TEXT, phone TEXT, account_name TEXT)")
domains = ["gmail.com", "notexample.com", "qa.example.com"]
for i, domain in enumerate(domains, 1):
db.execute("INSERT INTO members VALUES (?,?,?,?,?,?)",
(i, f"m{i}{AT}{domain}", "$2b$10$dummy", "enc:dummy", None, None))
db.execute("UPDATE members SET phone = '090-0000-0000', account_name = 'ダミー' WHERE id = 1")
db.commit()
def mask(db):
with db:
for (mid,) in db.execute("SELECT id FROM members").fetchall():
db.execute("UPDATE members SET email = ?, password_hash = ?, secret_answer = NULL, "
"phone = NULL, account_name = NULL WHERE id = ?",
(f"member{mid}{AT}example.invalid", MASKED_HASH, mid))
def inspect(db):
total = 0
for table, column, violates in RULES:
rows = db.execute(f"SELECT id, {column} FROM {table} WHERE {column} IS NOT NULL")
ids = [row_id for row_id, value in rows if violates(value)]
total += len(ids)
# 値そのものはログへ出さず、列と行IDだけを出す
print(f"{table}.{column}: 違反 {len(ids)} 件 {ids[:5]}")
return total
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--mask", action="store_true", help="検査の前に検証データをマスキングする")
args = parser.parse_args()
db = sqlite3.connect(":memory:")
seed(db)
if args.mask:
mask(db)
total = inspect(db)
print(f"合計 {total} 件")
sys.exit(1 if total else 0)
if __name__ == "__main__":
main()
Python 3.14.10(Windows)で2026年11月9日に実行した結果です。マスキングしない場合は終了コード1、--mask を付けると終了コード0で終わりました。
members.email: 違反 2 件 [1, 2]
members.password_hash: 違反 3 件 [1, 2, 3]
members.secret_answer: 違反 3 件 [1, 2, 3]
members.phone: 違反 1 件 [1]
members.account_name: 違反 1 件 [1]
合計 10 件
2番の notexample.com が違反になり、3番の qa.example.com は通っています。末尾の文字列だけで比べると前者を見逃すため、ドメインの区切りまで見る実装にしました。実データを扱う検査なので、ログには値を出していません。実運用では接続先を自社の開発DBに替え、表と列を RULES に足してください。
30日を超えたダンプを洗い出すfindコマンドと置き場の期限管理
DBの中がきれいでも、作業用のダンプファイルが残っていれば同じことです。次のコマンドは、更新から30日を超えたダンプの一覧を出します。
find /var/backups/dev -type f \( -name '*.dump' -o -name '*.sql' -o -name '*.sql.gz' \) -mtime +30 -print
40日前の .dump と .sql.gz、当日の .dump、40日前の .txt を置いて Git Bash で試すと、前の2つだけが表示されました。パスは自社の置き場に変えてください。オブジェクトストレージに置いているなら、ライフサイクル設定で自動削除の期限を決めます。消した記録も残すと、ガイドラインの言う削除の確認に使えます。
個人情報保護委員会への報告と、本番データの持ち込みを認める条件・診断の判断
1,000人超と不正目的の2類型に当たる漏えい等報告と確報60日の期限
個人情報保護委員会の案内では、報告の対象に、本人の数が1,000人を超える漏えい等と、不正の目的によるおそれがある漏えい等が含まれます。約11,100名分への不正アクセスのような事案は、この両方の類型に照らして判断するものです。速報は発覚から3〜5日以内、確報は30日以内で、不正の目的によるおそれがある場合は60日以内とされています。
開発環境の複製でも、「過去のデータだから」「テスト用だから」という理由で報告の対象から外れるわけではありません。本人への通知を含む流れは個人情報保護委員会への報告義務の実務にまとめました。
ハッシュ方式をOWASPの推奨値で点検し、強制リセットを実装する手順
セレスの対応で参考になるのは、パスワードだけでなく、秘密の質問のリセットとSNSログイン連携の停止まで行った範囲の取り方です。パスワードを変えても、別の経路が残っていれば乗っ取りは防げません。全会員のパスワードを無効化する実装はSONICWIREの全会員パスワード無効化と再設定で示しました。
保存方式はOWASP Password Storage Cheat Sheetの値で確かめます。Argon2idの最低設定はメモリ19MiB、反復2回、並列度1。bcryptは既存システム向けの扱いで、コストは10以上です。移行のコードはbcryptのコスト係数とArgon2idへの移行を参照してください。
本番データの持ち込みを認める条件と、第三者の診断を先に入れる場面
既定は「本番データの複製を開発環境へ置かない」です。例外を認めるのは、実データでしか再現しない障害の調査に限ります。そのときは、次の4つをすべて満たすことを条件にします。
- 責任者の承認と利用目的の記録がある
- 本番と同じアクセス制御と監視が効いている
- 削除の期限が日付で決まっている
- 調査後の削除を別の担当者が確認する
新機能の開発や画面の確認に、本番の複製は不要です。性能試験のために件数が要るだけなら、合成データかマスキング済みのダンプで足ります。会員数が数百人でパスワードを持たない小規模なサイトは、まず検査スクリプトとダンプの棚卸しから始めれば十分でしょう。
外部に診断を頼むべきなのは、会員数が万単位である、開発環境をインターネットから直接開いている、委託先が開発環境にアクセスしている、のいずれかに当てはまる場合です。委託先の権限は委託先管理の監督義務とチェックリストで、APIの認可とトークン失効はAPI不正アクセス対策の実装手順で点検できます。開発環境を含めて第三者の目で確かめたい場合は、脆弱性診断・セキュリティ診断でご相談いただけます。
よくある質問
ポイントインカムの不正アクセスについて、会員から出やすい質問をまとめました。内容は2026年11月6日と10月7日の公表文に基づきます。
ポイントインカムの不正アクセスで自分が対象かどうかはどう確かめますか?
対象の会員にはセレスから個別のメールが届きます。発表文に、自分で照会するページの案内はありません。対象になるのは2025年11月15日時点のバックアップに含まれていた約11,100名で、該当するアカウントはログインできない状態になっています。メールが見当たらず確かめたい場合は、ポイントインカムの問い合わせフォームから尋ねてください。迷惑メールのフォルダも確認しておくと確実です。
ポイントインカムに急にログインできなくなったのはなぜですか?
今回の対象者は、二次被害を防ぐためにログインを止められ、パスワードが強制的にリセットされています。パスワード再設定ページで新しいパスワードを設定すると、再びログインできる流れです。その後、秘密の質問の再設定と、使っている人はSNSログインの設定し直しが必要になります。ほかの原因でログインできない可能性もあるので、再設定で解決しないときは問い合わせフォームへ連絡します。
クレジットカード情報や銀行口座は漏れましたか?
10月7日の発表で、セレスはクレジットカード情報などの決済関連情報をサーバーに保持していないと説明しました。11月6日の項目にもカード番号はありません。一方で口座名義が1名分、電話番号が16名分含まれていたとされています。口座番号は項目に挙がっていません。対象の人にはメールで個別に案内があるので、その内容を確認し、心当たりのないカード番号の入力要求には応じないでください。
10月の195件の不正アクセスと同じ事件ですか?
発表は別で、検知日も件数も違います。10月の件は10月5日未明から検知され、会員88件と従業員等107件の計195件でした。11月の件は10月29日に開発環境で検知され、約11,100名分です。発表文は両者の関係を説明しておらず、同じ攻撃者によるものかは分かっていません。10月の連絡を受けていなくても、11月の件の対象になることはあり得ます。
ポイントインカムは退会したほうがよいですか?
退会しても、すでに閲覧された可能性がある過去のデータは取り消せません。先に行うべきことは、パスワードの再設定と、使い回していた他社パスワードの変更です。そのうえで続けるかどうかは、侵入経路と再発防止策の続報を見て決めれば間に合います。退会するなら、保有ポイントの交換を済ませてから手続きしてください。なお、発表文に退会時の扱いの記載はありません。
関連記事
- アララの不正アクセス:メール約8,100万件の持ち出しと公表した契約企業、APIキー再設定・代替送信・連名報告:CoinTradeの件が起きた配信サービス側の事案
- ネットマイル不正アクセスで最大約549万人に漏えいの可能性:ログイン・マイル・退会・登録した覚えがない場合:同じポイントサービスで起きた別の事案
- パスワードリスト攻撃とは?検知の指標と漏えい照合・レート制限の実装:漏れたパスワードが他社で試される手口
- API不正アクセス対策の実装手順:JPCERT注意喚起に沿うレート制限・認可・トークン失効とアプリ解析・SSRF対策:会員情報を返すAPIの点検
- 個人情報保護委員会への報告義務|対象4類型・速報3〜5日と確報30日の実務:事業者が行う報告の流れ