オンラインゲームポータル「ハンゲ」を運営するENSAPIA Tokyoは、2026年11月13日の第4報で、ハンゲのサーバーへの不正アクセスによりハッシュ化されたパスワード61,962件、メールアドレス51,025件などが漏えいしたと公表しました。11月4日の第2報では流出の痕跡は確認されていないとしていたため、説明が途中で変わった事案です。この記事では、公表で確定した事実と未公表の項目を分けて整理し、利用者が今やることを短く示します。後半は会員制サービスを持つ開発者向けに、ハッシュ方式ごとの危険度の見積もり、旧方式からの移行、漏えい済みパスワードの照合、セキュリティコードを保存しない決済設計の点検を、実行できるPythonのコード付きで解説します。
まとめ:ハンゲの不正アクセスで確定した事実と、自社の会員DBで確かめる作業
確定しているのは、第三者によるハンゲのサーバーへの不正アクセス、11月3日夜の緊急メンテナンスによる全サービスの停止、ハッシュ化パスワードやメールアドレス、決済時の情報の一部の漏えい、の3点です。侵入経路、パスワードのハッシュ方式、再開の時期は公表されていません。
ハンゲの利用者は、ハンゲと同じパスワードを使っている他のサービスを先に変更します。ハンゲ本体はサービスが止まっているためです。
会員制のサービスを持つ開発者が自社で確かめる作業は、優先度の高い順に次の4つです。
- 会員DBのパスワードが、Argon2id・scrypt・bcryptなど計算コストの高い方式とソルトで保存されているかを確かめる
- 旧方式が残っているなら、ログイン成功時に新方式へ置き換える処理と、休眠会員の扱いを決める
- パスワードの登録・変更時に、漏えい済みの値を拒否する照合を入れる
- 決済の画面・ログ・問い合わせ記録に、セキュリティコードやカード番号が残っていないかを洗い出す
どれも事故が起きてからでは間に合いません。
11月13日の第4報で確定した漏えい項目・件数と、侵入経路など未公表の範囲
11月3日の緊急メンテナンスから第4報まで、四度の公表で変わった説明
ENSAPIA Tokyoの第4報によると、経緯は次のとおりです。11月3日23時に不正な接続の可能性を受けて緊急メンテナンスに入り、サービスを止めました。11月4日16時の第2報では、同日13時時点でIDとパスワードが流出した痕跡は確認されていないと説明しています。11月6日20時20分の第3報では全サービスの停止が続き、影響範囲を調査中としていました。
11月13日14時の第4報で、個人情報の一部の漏えいが判明したと説明が変わります。初動から10日での確定です。
開発者の立場で読むべきなのは、第2報の「痕跡なし」が調査の途中経過だった点です。侵入から数日の段階では、どのテーブルが読まれたかをログで裏付けきれないことが多くあります。自社で同じ立場になったときは、「現時点で確認されていない」と時点を添えて書き、断定を避けるほうが後の訂正が小さく済みます。
ハンゲ会員・外部サービスID・決済時の情報、区分ごとの漏えい件数
第4報が挙げた漏えいの項目と件数は次のとおりです。
| 区分 | 項目と件数 |
|---|---|
| ハンゲ会員情報 | ハッシュ化されたパスワード61,962件 |
| ハンゲ会員情報 | メールアドレス51,025件 |
| ハンゲ会員情報 | 生年月日28,251件 |
| ハンゲ会員情報 | 氏名・住所・郵便番号・電話番号2,994件 |
| 外部サービスID | メールアドレス36,545件 |
| 決済時の情報 | マスク済みのカード番号の一部2,961件 |
| 決済時の情報 | セキュリティコード6件・電話番号97件 |
| 決済時の情報 | クレジットカード名義2件 |
| その他 | メールアドレス97件 |
原因は第三者によるハンゲのサーバーへの不正アクセスとされ、攻撃の手法と侵入経路は外部のセキュリティ専門企業が調査しています。同社は不正アクセスに使われた通信経路を遮断し、対象者へメールで個別に連絡したうえで、個人情報保護委員会と所轄の警察署へ報告しました。安全確保と再発防止を優先し、再開まで相応の時間がかかる見込みです。
利用者が今やることと、パスワードの使い回し先を先に変える理由
同社が利用者に求めているのは3点です。他のサービスと同じパスワードを使っていれば速やかに変えること、同社や関係機関を装ったメールや電話の添付ファイルとURLを開かず削除すること、身に覚えのない請求や引き落としが無いかを利用明細で確かめることです。
使い回し先を先に変えるのは、ハッシュから復元されたパスワードが他のサービスへ試されるためです。漏えいしたメールアドレスと組み合わせれば、ログインIDの推測は要りません。この型の攻撃の仕組みと検知の指標はパスワードリスト攻撃の解説で整理しています。メールアカウント、決済や送金に関わるサービス、クラウドの管理画面の順に手を付けます。
ハッシュ化パスワード61,962件の危険度を、方式とソルトの有無で見積もる手順
MD5・SHA-1とbcrypt・Argon2idで変わる、漏えい後に解読される難度の差
「ハッシュ化されているから安全」とは言えません。危険度を桁違いに左右するのは、方式とソルトの有無です。MD5やSHA-1のような汎用の高速ハッシュは、GPUで1秒間に膨大な回数を試せるため、短いパスワードや辞書に載る語は短時間で復元されます。ソルトが無ければ、同じパスワードの利用者は同じハッシュになり、まとめて割れます。
一方、OWASPのPassword Storage Cheat Sheetが挙げるArgon2id・scrypt・bcryptは、1回の計算にわざと時間とメモリを使わせる方式です。利用者ごとのソルトと組み合わせると、総当たりの費用が1件ずつ掛かります。それでも「123456」のような値は早い段階で当たるため、強い方式は弱いパスワードまでは守りません。
| 保存方式 | 漏えい後の見立て |
|---|---|
| MD5・SHA-1(ソルトなし) | 漏えいとほぼ同じ扱いで動く |
| SHA-256(ソルト付き) | 短い値と辞書の語は復元される前提 |
| bcrypt(work factor 10以上) | 弱い値だけ先に当たる |
| Argon2id・scrypt(推奨値) | 弱い値以外は費用が見合わない |
方式が非公表のときは弱い前提で動く、利用者と運営者それぞれの線引き
ハンゲの第4報には、ハッシュ方式の記載がありません。方式が分からない以上、利用者は弱い方式だった前提で動きます。使い回しの変更を確定まで待たない、という判断です。
運営者の側は逆で、自社の方式を説明できる状態にしておく必要があります。漏えいを公表するとき「bcrypt(work factor 12)で保存しており」と書ければ、利用者は危険度を自分で見積もれます。書けないなら、それは保存方式を誰も把握していないという意味です。点検は会員テーブルのパスワード列の先頭を数件見るだけで始められます。「$2b$」ならbcrypt、「$argon2id$」ならArgon2id、32文字の16進数だけならMD5を疑います。
旧方式のハッシュをログイン時にscryptへ置き換えるPythonの移行コード
OWASPが示すArgon2idとscryptの最低パラメータと、移行先の選び方
OWASPは第一の選択肢としてArgon2idを挙げ、最低構成をメモリ19MiB・反復2回・並列度1としています。Argon2idが使えない環境ではscryptで、最低ラインはN=2^17(128MiB)・r=8・p=1です。bcryptは旧来のシステム向けとされ、work factorは10以上、入力の上限は多くの実装で72バイトです。
移行先は、使っている言語に保守されたライブラリがあるかで決めます。PythonでArgon2idを使うならargon2-cffiが定番で、25.1.0の既定値はtime_cost=3・memory_cost=65536(約64MiB)・parallelism=4です。パラメータが古いかを判定する check_needs_rehash も用意されています。追加の依存を避けたい場合は、標準ライブラリのhashlib.scryptで対応できる構成です。次の例はこちらを使います。
平文を受け取るログイン成功時だけ置き換えられる、再ハッシュの実装例
ハッシュから平文は取り出せないため、新方式へ置き換えられるのは、利用者がパスワードを入力して照合に成功した瞬間だけです。次のコードは、旧方式(ソルト付きSHA-256)で保存された会員がログインに成功したとき、その場でscryptのハッシュへ書き換えます。保存形式に方式とパラメータを含めておくと、将来パラメータを上げたときも同じ判定で置き換えられます。
# 旧方式(ソルト付きSHA-256)のハッシュを、ログイン成功時にscryptへ置き換える(Python 3.9以上・標準ライブラリのみ)
import base64
import hashlib
import hmac
import os
N, R, P = 2**17, 8, 1 # OWASPが示すscryptの最低ライン(N=2^17・r=8・p=1)
def b64(b):
return base64.b64encode(b).decode()
def scrypt_hash(password):
salt = os.urandom(16)
dk = hashlib.scrypt(password.encode(), salt=salt, n=N, r=R, p=P, maxmem=256 * 1024 * 1024, dklen=32)
return f"scrypt${N}${R}${P}${b64(salt)}${b64(dk)}"
def verify(stored, password):
algo, *rest = stored.split("$")
if algo == "sha256": # 旧方式: sha256$ソルト$ダイジェスト
salt, digest = rest
calc = hashlib.sha256((salt + password).encode()).hexdigest()
return hmac.compare_digest(calc, digest)
n, r, p, salt, dk = rest
calc = hashlib.scrypt(password.encode(), salt=base64.b64decode(salt), n=int(n), r=int(r), p=int(p),
maxmem=256 * 1024 * 1024, dklen=32)
return hmac.compare_digest(calc, base64.b64decode(dk))
def needs_rehash(stored):
algo, *rest = stored.split("$")
return algo != "scrypt" or (int(rest[0]), int(rest[1]), int(rest[2])) != (N, R, P)
def login(users, user_id, password):
stored = users[user_id]
if not verify(stored, password):
return "失敗"
if needs_rehash(stored):
users[user_id] = scrypt_hash(password) # 平文を持っているこの瞬間だけ置き換えられる
return "成功(scryptへ置き換え)"
return "成功"
legacy_salt = "a1b2c3"
users = {"u100": f"sha256${legacy_salt}${hashlib.sha256((legacy_salt + 'correct horse').encode()).hexdigest()}"}
print(login(users, "u100", "wrong"))
print(login(users, "u100", "correct horse"))
print(login(users, "u100", "correct horse"))
print(users["u100"].split("$")[:4])
Python 3.14.10(Windows)で2026年11月14日に実行した結果です。値は説明用に作ったもので、ハンゲのデータを再現したものではありません。
失敗
成功(scryptへ置き換え)
成功
['scrypt', '131072', '8', '1']
2回目のログインで旧方式のハッシュがscryptに置き換わり、3回目は置き換えずに通っています。照合に hmac.compare_digest を使うのは、比較にかかる時間から一致した桁数を推測されないようにするためです。N=2^17は1回の計算に128MiBを使うので、同時ログインの多いサービスではサーバーのメモリと応答時間を先に測ってから値を決めます。
ログインしない休眠会員の旧ハッシュを残さないための外側ラッピング
ログイン時の置き換えだけでは、長くログインしない会員の旧ハッシュが残り続けます。漏えいしたときに割れるのはこの層です。OWASPは2つの手を挙げています。休眠会員のハッシュを消して次回にパスワードの再設定を求める方法と、旧ハッシュそのものを入力にして新方式で包む方法です。
包む方法は、平文が無くても今日中に全件を新方式へ移せる点が利点です。scrypt(sha256(ソルト+パスワード)) の形で保存し、次のログイン成功時に平文から直接作ったハッシュへ置き換えます。ただしOWASPは、重ねたハッシュは割れやすくなる場合があると注意しています。移行期間の一時的な形と割り切り、置き換えの進み具合を件数で追ってください。パスワードをハッシュ化ではなく復号できる暗号化で保存していた場合は、ログインを待たずに全件を一括でハッシュへ移せます。その手順はスカイライナーの不正アクセスでコードとともに解説しています。
漏えい済みパスワードを登録時に拒否する、Pwned Passwordsの照合実装
NIST SP 800-63B-4が求める、漏えい済みの値を拒否するブロックリスト照合
保存方式を強くしても、利用者が他所で漏れたパスワードを登録すれば、パスワードリスト攻撃でそのまま通ります。NIST SP 800-63B-4の3.1.1.2は、パスワードの設定・変更時に、よく使われる値や漏えい済みの値を含むブロックリストと照合すること(SHALL)を求め、該当したら理由を示して別の値を選ばせるとしています。
同じ節は、定期的なパスワード変更を求めてはならない(SHALL NOT)一方、侵害の証拠がある場合は変更を強制する(SHALL)と定めています。ハンゲのように漏えいが確定した場面は、後者にあたります。
SHA-1の先頭5文字だけを送るrange APIで、登録時に照合するPythonの例
漏えい済みの値の一覧として広く使われているのが、Have I Been PwnedのPwned Passwordsです。range APIはAPIキーが要らず、パスワードのSHA-1の先頭5文字だけを送ると、その5文字で始まるハッシュの残りの部分と出現回数の一覧が返ります。パスワード本体もハッシュ全体も外部に出ません。Add-Paddingヘッダを付けると応答の行数が水増しされ、通信量から問い合わせ内容を推測されにくくなります。
# パスワード設定・変更時に、漏えい済みの値かをPwned Passwordsのrange APIで確かめる(Python 3.9以上・標準ライブラリのみ)
import hashlib
import urllib.request
def pwned_count(password):
sha1 = hashlib.sha1(password.encode()).hexdigest().upper()
prefix, suffix = sha1[:5], sha1[5:] # 送るのは先頭5文字だけ。パスワードもハッシュ全体も外に出さない
req = urllib.request.Request(
f"https://api.pwnedpasswords.com/range/{prefix}",
headers={"Add-Padding": "true", "User-Agent": "password-check-example"},
)
with urllib.request.urlopen(req, timeout=10) as res:
for line in res.read().decode().splitlines():
s, count = line.split(":")
if s == suffix:
return int(count) # 水増し行は件数0なので、そのまま0として扱える
return 0
for pw in ["password123", "Hange-2026-11-13-example!"]:
n = pwned_count(pw)
print(f"{pw}: {'拒否(漏えい済み ' + format(n, ',') + '回)' if n else '受理'}")
同じ環境で2026年11月14日に実行した結果です。件数は照合した時点の値で、データの更新に応じて増えます。
password123: 拒否(漏えい済み 2,266,677回)
Hange-2026-11-13-example!: 受理
本番では、APIが応答しないときに登録を止めるか通すかを先に決めます。外部APIの障害で会員登録が止まるのを避けるなら、タイムアウト時は通して記録を残し、後から照合し直す設計が扱いやすい形です。ログインの試行回数を抑えるレート制限と組み合わせる手順はAPI不正アクセス対策の実装手順にまとめました。
セキュリティコード6件の保存が示す、カード情報を持たない決済設計の点検
PCI DSS要件3が承認後の保存を禁じるセキュリティコードと、今回の6件
件数は6件と小さいものの、技術的に見逃せないのがセキュリティコードの漏えいです。カード業界の基準を定めるPCI SSCのFAQは、カード検証コードを取引の承認後に保存してはならないとし、暗号化していても、顧客が同意していても例外にならないと説明しています。根拠はPCI DSSの要件3です。
国内では、日本クレジット協会が掲載するクレジットカード・セキュリティガイドライン(2026年11月時点で6.1版)が、EC加盟店のカード情報保護対策の指針を定め、カード情報を自社のサーバーに通さない「非通過型」の決済の導入を勧めています。第4報は、セキュリティコードがどの経路でどこに残っていたかを説明していません。決済代行会社の画面ではなく、自社のフォームや問い合わせ記録を通った可能性もあり、ここは続報を待つ部分です。
決済画面・ログ・問い合わせ記録に残るカード情報を洗い出す点検の順序
非保持化した「つもり」でも、カード情報は思わぬ場所に残ります。点検は次の順で進めます。
- 決済画面:入力フォームが決済代行会社のリンク型・トークン型か、自社サーバーを経由する形かを確かめる
- アプリのログ:リクエスト本文を丸ごと出力するデバッグログに、カード番号やセキュリティコードが混ざっていないかを確かめる
- 問い合わせ記録:返金や決済エラーの問い合わせで、利用者が本文にカード情報を書いたまま保存されていないかを確かめる
- バックアップ:非保持化より前のテーブルやダンプが、今もストレージに残っていないかを確かめる
実務で最初に当たるべきは2のログです。リクエストを丸ごと出力する設定は開発中に入れたまま本番へ出やすく、ログは本番DBより緩い権限で読めることが多いためです。不正アクセスの痕跡をログから追う手順は不正アクセスの調べ方で解説しています。
判断:全会員のパスワード再設定を強制する場面と、個別通知で足りる場面
方式が弱いか不明なら全会員の再設定を強制し、強い方式なら絞る条件
自社で同じ事態になったら、次の条件で決めます。保存方式がMD5・SHA-1・ソルトなし、または方式を説明できない場合は、漏えいの範囲にかかわらず全会員のパスワード再設定を強制します。割れる前提のハッシュが出回っている以上、対象者を絞る理由がありません。発行済みのセッションも同時に無効にします。
対象者だけに絞ってよいのは、Argon2id・scryptなどを推奨値で使っていて、かつどのレコードが読まれたかをログで特定できた場合です。それでも対象者には再設定を強制し、漏えい済み照合を通らない値は受け付けません。迷ったら全員です。
再設定の案内メールは、偽メールが最も効く時期と重なります。メールに再設定のリンクを入れず、「公式サイトやアプリから開いてください」と書くほうが安全です。
個人情報保護委員会の報告4類型に当てはめたときの速報と確報の期限
個人情報保護委員会は、報告が必要な事態として4つの類型を示しています。不正の目的によるおそれがある漏えい、財産的被害のおそれがある漏えい、本人の数が1,000人を超える漏えい、要配慮個人情報の漏えいです。今回のような不正アクセスは、件数にかかわらず不正の目的によるおそれの類型にあたります。
速報は発覚から3〜5日以内が目安で、確報は30日以内、不正の目的によるおそれがある場合は60日以内です。速報の期限に間に合わせるには、どの区分の会員の、どの項目が読まれたかを示せる必要があります。報告の流れは個人情報保護委員会への報告義務の実務で解説しました。自社の会員DBの保存方式や、カード情報が残っていないかを第三者の目で確かめたい場合は、脆弱性診断・セキュリティ診断で相談できます。
よくある質問
ハンゲの不正アクセスについて、利用者と開発者から出やすい質問をまとめました。2026年11月14日時点の公表内容にもとづきます。
ハンゲの不正アクセスで漏えいしたのは何件ですか?
第4報では、ハッシュ化されたパスワード61,962件、メールアドレス51,025件、生年月日28,251件、氏名・住所・郵便番号・電話番号2,994件、外部サービスIDのメールアドレス36,545件が挙げられています。決済時の情報として、マスク済みのカード番号の一部2,961件、セキュリティコード6件などもあります。区分ごとの件数で、人数の合計は示されていません。
自分が対象かどうかはどうやって確かめればよいですか?
同社は対象者へメールで個別に連絡し、メールで連絡できない人には公表をもって案内に代えるとしています。届いたメールのリンクは開かず、確認に使うのはハンゲの公式サイトからたどった第4報とヘルプセンターです。同社や関係機関を装った不審なメール・電話への注意も呼びかけられています。
ハンゲのパスワードは変更したほうがいいですか?
ハンゲは全サービスが止まっているため、まず同じパスワードを使っている他のサービスを変更します。メールアカウントと、決済や送金に関わるサービスが先です。ハンゲ本体のパスワードは、再開時の同社の案内に沿って変更します。
ハッシュ化されたパスワードは元に戻せるのですか?
ハッシュは計算で元に戻す仕組みではありませんが、候補を順に試して一致するものを探すことはできます。MD5やSHA-1などの高速な方式なら短いパスワードは短時間で見つかり、Argon2idやscryptなら費用が大きく増えます。ハンゲの方式は公表されていないため、弱い方式だった前提で使い回しを断つのが安全です。
ハンゲのサービスはいつ再開しますか?
11月14日時点で再開の時期は示されていません。第4報では、安全確保と再発防止を優先し、再開まで相応の時間がかかる見込みとしています。問い合わせはハンゲのヘルプセンターで受け付けています。
関連記事
- パスワードリスト攻撃とは?検知の指標と漏えい照合・レート制限の実装:ハッシュ流出後の使い回しを狙う攻撃の仕組みと検知
- API不正アクセス対策の実装手順:JPCERT注意喚起に沿うレート制限・認可・トークン失効とアプリ解析・SSRF対策:ログインAPIのレート制限とトークン失効
- 個人情報保護委員会への報告義務|対象4類型・速報3〜5日と確報30日の実務:不正アクセスで漏えいしたときの報告の流れ
- 不正アクセスの調べ方|ログの確認方法と痕跡を見つけるコマンド例:侵入の痕跡をログから追う手順