Case 002: 境界値テスト
街に入った瞬間、俺は後悔した。
ここは人が多すぎる。
石畳の大通りには、行商人、冒険者らしき武装した男女、買い物帰りの主婦、走り回る子供たち。
あらゆる人間がひしめき合い、活気に満ちた喧騒が耳を打つ。
「……うわ」
思わず足が止まった。
人間不信を発症してから二週間、ほとんど外出していなかった俺にとって、この人混みは地獄に等しい。
ゲームだと分かっていても、視線が刺さる気がしてならない。
「とりあえず、人の少ない場所を探すか……」
俺は人混みを避けるように、路地裏へと逃げ込んだ。
◆◆◆◆◆
少し落ち着いた場所で、改めて管理者ツールを確認する。
ステータスの編集ができることまでは確認した。
だが、管理者権限で入ってしまった以上、他にどんな機能があるのか把握しておく必要がある。
「ふむ……」
ステータス画面を開き、機能を一つずつ確認していく。
『admin』
『HP: 100/100』
『MP: 100/100』
『STR: 10』
『DEX: 8』
『INT: 99』
『職業: 管理者』
『スキル: 管理者ツール』
『所持金: 0G』
『所持アイテム:
・干し肉 ×1
・水筒 ×1』
「所持金ゼロか……。 まあ、正規のスタートじゃないからな」
初期装備すら怪しい。
干し肉と水筒だけとは、随分と質素だ。
ふと、アイテム欄の右下に見慣れた鉛筆マークがあることに気付いた。
「……まさか」
タップしてみる。
『干し肉: 1 → ?』
『変更する数値を入力してください』
「いやいやいやいや」
編集できてしまった。
ステータスだけじゃなく、所持アイテムの数まで弄れるのか。
試しに「10」と入力する。
『干し肉: 1 → 10』
『変更しますか? [Yes/No]』
恐る恐る「Yes」を選択すると、インベントリの中で干し肉が十個に増えた。
「おいおい……。 これ、アイテム増殖バグそのものじゃねーか」
いや、バグじゃない。
管理者権限による正規の機能ではある。
だが、普通のプレイヤーがこれを使えたら、ゲームバランスは崩壊する。
「じゃあ、これは……」
嫌な予感がして、所持金の欄をタップする。
『所持金: 0 → ?』
やっぱり編集できる。
「10000」と入力。
『所持金: 0 → 10000G』
『変更しますか? [Yes/No]』
「Yes」
『変更完了』
『所持金: 10000G』
「…………」
金が増えた。
一万ゴールド。
このゲームの通貨単位がゴールドなのかは知らないが、とりあえず増えた。
「現実だったら嬉しいんだがな……」
思わず呟く。
「ゲーム内通貨って、やってると次第にインフレして価値がなくなっていくんだよな……」
RMTで現金化できるゲームならまだしも、開発中のゲームでは意味がない。
そもそもこれはテストのために入っているだけで、正式リリース時には削除される機能だろう。
間違ってバグで一般ユーザーにこんなスキルが割り振られでもしたら、たまったもんじゃない。
「まあ、宿代くらいには――」
ふと視線を感じて顔を上げると、通りすがりの商人らしき男がこちらをじっと見ていた。
「……なんだよ」
男は何も言わず、足早に去っていく。
その後ろ姿を見送りながら、俺は小さく舌打ちした。
「ゲームの挙動だと分かってはいるが……人間不信の俺にはキツすぎる」
独り言を呟く黒ローブの男。
そりゃ不審者だ。
NPCだって警戒する。
「……宿を取ろう。 とりあえず、人目につかない場所で落ち着きたい」
俺は逃げるように路地裏を進み始めた。
◆◆◆◆◆
宿を探すこと三十分程。
メインストリートの宿屋は論外だった。
客引きの声、出入りする冒険者たち、賑やかな酒場の喧騒。
俺の精神にはダメージが大きすぎる。
結局、街のはずれにある閑散とした宿屋を見つけた。
『辺境の休息亭』
看板は色褪せ、客の気配もほとんどない。
だが、俺にとっては理想的な環境だ。
「よし、ここにしよう」
意を決して扉を開ける。
……と、そこで重大なことを失念していたことに気付いた。
そう、宿を取るには、店主と会話する必要がある。
「……」
カウンターの奥から、ガタイのいい強面の大男が現れた。
傷だらけの顔に、鋭い目つき。
元冒険者か、あるいは元傭兵か。
どう見ても堅気ではない風貌だ。
俺は思わず後ずさりしかけた。
だが、男の方から声をかけてきた。
「宿泊か? 何日休んでいく?」
意外にも、声は低いが穏やかだった。
「あ、ああ……」
助かった。
向こうから話しかけてくれた。
こいつの顔が怖いから不人気なんだろうが、俺にとってはありがたい。
目の前に入力欄が表示される。
『宿泊日数を入力してください』
『一泊: 1000G』
「……ん?」
入力欄。
数値を直接入力するタイプのUIだ。
そこでまたもや俺の中で、セキュリティエンジニアの血が騒いだ。
境界値テスト。
プログラムが想定している入力の「境界」で、正しく動作するかを確認するテスト手法だ。
例えば「一泊何日」という入力欄があったとして、普通は1以上の整数を想定している。
だが、もし入力チェックが甘ければ――
「-1日だ」
俺は試しにマイナスの値を入力してみた。
一泊1000Gなら、マイナス一泊で「-1000G払う」、つまり「1000Gもらえる」というバグがあるゲームは珍しくない。
「は?」
店主が怪訝な顔をした。
『エラー: 無効な入力です』
……まあ分かってはいたが、さすがに弾かれるよな。
「すまん、間違えた」
気を取り直して、今度は上限を試す。
「65536日だ」
コンピュータでよく使われる数値の上限。
2の16乗。16ビットの符号なし整数で表現できる最大値プラス1した値だ。
この辺りでオーバーフローが起き、0日扱いされたりマイナス日になったり、とにかく変な挙動をし始めるシステムは多い。
「……面白い冗談を言うヤツだな」
店主が鼻で笑った。
『エラー: 最大365日まで入力可能です』
「……チェックしてんのかよ」
思わず声に出た。
ログイン画面ではSQLインジェクションが通ったくせに、なんで宿屋の入力欄はちゃんと入力チェックしてるんだよ。
どう考えても、力入れるところ間違えてるだろ……。
「前払いで可能な最大日数は?」
「所持金次第だが、一年分までなら受け付けてる」
「じゃあ、365日で」
『365日 × 1000G = 365000G』
『所持金が不足しています』
「…………」
さっき一万ゴールドに増やしたばかりなのに、全然足りない。
仕方なく、管理者ツールで所持金を50万Gまで増やしてから、改めて一年分の宿泊を申し込んだ。
『宿泊予約完了』
『365日分: 365000G』
『残金: 135000G』
「あ、ああ……確かに受け取った。 毎日メシはつくが、酒は別料金だ。 部屋は二階の奥」
店主が「よく用意できたな」とでも言いたげにしながら、無骨な鍵を投げてよこした。
「……助かる」
俺は鍵を受け取り、足早に階段を上がった。
セキュリティの力の入れるべき場所をとことん履き違えている。
心の中で、そうぼやきながら。
◆◆◆◆◆
部屋に入った瞬間、糸が切れたように倒れ込んだ。
人と話すのは、今の俺にはやはり疲れる。
店主との会話はほんの数分だったはずだが、精神的な消耗は半日分くらいあった。
「……寝よう」
ベッドに潜り込み、目を閉じる。
VRゲームで睡眠を取るという不思議な体験だが、疲労感はリアルだった。
意識が遠のいていく。
気付けば、俺は泥のように眠っていた。
◆◆◆◆◆
目が覚めると、窓から差し込む光が眩しかった。
「……朝か」
どれくらい眠っていたのか分からない。
体感では丸一日以上寝ていた気がする。
ふと、違和感に気付いた。
やはりログアウトできていない。
普通のVRゲームなら、長時間プレイすると強制的にログアウトさせられるか、少なくとも警告が出る。
だが、この世界に来てからそんな通知は一度もない。
「…………」
少し不安になる。
だが、冷静に考えてみれば、俺は今、無職だ。
妻子はおろか、恋人すらいない。
ゲームの世界から帰ったところで、どのみち一人暮らしの家。
誰かが心配しているわけでもない。
「……まあ、別に死んでも困ることはないか」
自分で言って、少し虚しくなった。
開発中のゲームだ。ログアウト機能が未実装なだけだろう。
ヘッドセットを物理的に外せば戻れるはずだ。
……たぶん。
◆◆◆◆◆
階下から、声が聞こえてきた。
どうやら食事付きの宿らしく、一階の食堂で朝食が出ているようだ。
降りていくのは億劫だったが、二階の部屋にまで会話が筒抜けで聞こえてくる。
「――だからよ、冒険者ギルドで依頼受けるのが一番確実なんだって」
「でも、あそこ登録料かかるじゃん」
「身分証代わりにもなるんだから、安いもんだろ」
冒険者ギルド。
その単語に、俺の耳がぴくりと反応した。
冒険者ギルド。依頼。登録。
ファンタジー世界の定番中の定番だ。
人と話すのは嫌だが……そういう浪漫にあふれる場所は、少し見てみたい気持ちがあった。
「……でもな」
問題がある。
俺は今、アドミンというアカウント名で、黒髪黒ローブの地味な姿をしている。
この姿は、現実の三十歳の俺を少し若くしたような、二十代の見た目だ。
自分の顔に自信があるわけでもない。
むしろ、目立たないほうがいいのに、中途半端に冴えない顔が余計に気になる。
「なんとかならないかな……」
管理者ツールを開き、試行錯誤を始めた。
まず目についたのは、自分のアカウント情報欄だった。
「おいおい……」
『id: 1』
『username: admin』
『userkana: アドミン』
『password: 1234』
「…………は?」
パスワードが「1234」。
しかも平文で保存されている。
普通、パスワードは暗号化して保存する。
万が一データベースが漏洩したとしても、元のパスワードが何なのか分からないようにするためだ。
「なんで暗号化しないで平文のままパスワード保存してんだよ……」
その上、アカウント情報の表示画面にパスワードそのまま表示しちゃダメだろ。
VR機器盗まれたり、家族とかに使われたらそれだけでパスワード漏洩するじゃねぇか。
それに今の時代、配信しながらVRゲームをやる人間だっているだろう。
そんな中パスワードを生のまま表示するなんて、テロ行為と言ってもいいレベルだ。
これ、本当に一般向けにリリース予定のゲームなんだよな?
頭が痛くなってきた。
このアカウントを誰かに乗っ取られたら困る。
俺はパスワードを変更することにした。
新しいパスワードは……そうだな、1000桁のランダム文字列にしておこう。
自分でも覚えられないくらい複雑なやつで、見られても到底覚えられないやつ。
『password: 1234 → くぁwせdrftgyふじこlp……』
『変更しますか? [Yes/No]』
というか、なんで日本語がパスワードで使えるんだよ、いろいろとおかしいだろ……。
まあ、適当な値に変えたところで、どうせ次ににログインする時には由仁からもらったアカウントでやるんだし。
「Yes」
『変更完了』
「……受け入れちゃったよ」
もう一度見ると、長すぎる文字はUIがクソなせいか「くぁwせdrftgyふじ」くらいで見切れてしまっていた。
まあ見切れるならある意味漏洩はしないかもしれんが、脆弱性をクソUIでカバーするなよ……。
由仁に報告することがどんどん増えていく。
まあいい。
パスワードを変えたら、普通はセッションが切れてログイン画面に戻されるはずだ。
…………。
戻されない。
「アカウント乗っ取られたら終わりじゃねーか……」
パスワード変更してもセッションが維持されるということは、一度ログインされたら追い出す手段がないということだ。
ついでに、もう一つ気になることがあった。
『id: 1』
俺のアカウントのIDが「1」。
つまり、データベースの一番最初のレコードだ。
SQLインジェクションで認証をすり抜けた時、たまたま一番上にあった管理者アカウントにログインしてしまった、という俺の予想は正しかったらしい。
ということは、他の誰かが同じ手法を試したら、同じようにこの管理者アカウントに入ってしまう可能性がある。
「順番を変えておくか……」
俺はidを「1」から「999999」に変更した。
アカウントIDを後から自由にいじれるって、どんなシステムだよ。
これで、もし他のやつがたまたまSQLインジェクションを成功させてしまったとしても、最初に取得されるのは少なくともアドミンではなくなる。
まあその前に不正ログインできてしまうバグを直せって話だが。
◆◆◆◆◆
さて、本題だ。
「アバター設定……これか」
自分でやっておいてなんだが、後で自由にアバター変えられるってのも変な話だよな。
流石にネカマになるつもりはないが、女にでもなれるってことだよな?
まあいい、見た目を変えるか。
『display_name: admin』
『display_kana: アドミン』
『hair_color: black』
『eye_color: black』
『height: 175』
『build: slim』
「これを弄ればいいのか……」
まず、名前を変えよう。
「admin」のままでは、いかにも管理者アカウントだとバレてしまう。
新しい名前……そうだな。
暗号化しろよ、という意味を込めて。
『display_name: admin → CheckSum』
『display_kana: アドミン → チェックサム』
チェックサム。
データが改ざんされていないかを確認するための値。
セキュリティの基本中の基本だ。
「……我ながら皮肉が効いたな」
次に、見た目だ。
鏡を見つけて、そこに自分の姿を映しながら値を調整していく。
髪の色を黒から金に。
目の色を黒から碧に。
身長は少し高めに。
顔立ちは……まあ、整った方向に。
『hair_color: black → blonde』
『eye_color: black → blue』
『height: 175 → 180』
『face_type: plain → handsome』
「変更」を押すたびに、鏡の中の自分が変わっていく。
小一時間鏡とにらめっこして最終的に出来上がったのは、金髪碧眼の美男子だった。
「……誰だこれ」
鏡に映った顔は、もはや俺の知っている自分ではない。
だが、これくらい別人になっていた方が、逆に自分という感覚が抜けるので、こちらとしても好き放題できるというものだ。
ついでに、ステータスも調整しておく。
厄介事に巻き込まれた時のために、ある程度は強くしておいた方がいい。
『STR: 10 → 50』
『DEX: 8 → 50』
『HP: 100 → 500』
『MP: 100 → 500』
INTはもともと99あるので、そのままにしておいた。
「よし……」
準備は整った。
新しい姿、新しい名前。
「CheckSum」として、冒険者ギルドに向かうとしよう。
◆◆◆◆◆
冒険者ギルドは、街の中心部にある大きな建物だった。
扉を開けると、中は思ったより静かだった。
朝早い時間だからか、冒険者の姿はまばらだ。
受付カウンターには、若い女性職員が座っていた。
「いらっしゃいませ。 ご用件は?」
「冒険者登録をしたい」
「かしこまりました。 こちらの用紙にお名前をお願いします」
差し出された用紙に「チェックサム」と記入する。
「チェックサム様ですね。登録料は5000Gになります」
金を払い、簡単な説明を受ける。
依頼の受け方、報酬の受け取り方、ランクシステムについて。
「――以上が基本的な説明になります。 なお、試験を受けていただければ、初めから高ランクでの登録も可能ですが」
「いや、身分証が欲しいだけだ。 ランクは最低でいい」
「……そうですか」
受付嬢が少し残念そうな顔をしたが、すぐに笑顔に戻った。
「では、Fランクでの登録となります。 こちらが冒険者証です」
金属製のプレートを受け取る。
『冒険者証』
『名前: チェックサム』
『ランク: F』
「……あっさりだな」
試験も審査もなく、金を払っただけで冒険者になれてしまった。
身元確認とか、そういうのはないのか。
まあ、ゲームだしな。
細かいことを気にしても仕方ない。
俺が踵を返そうとした時だった。
「ちょっと待てよ、お前」
背後から声がかかった。
振り返ると、いかにも柄の悪そうな冒険者が三人、俺の前に立っていた。
「新人か? 随分と小綺麗な格好してるじゃねえか」
リーダー格らしき男が、ニヤニヤしながら近づいてくる。
「見たことねえ顔だな。 どこの出身だ?」
「……答える義務はない」
「おいおい、先輩に対してその態度はねえだろ」
男が俺の肩に手を置こうとした。
その瞬間、俺は反射的に一歩下がった。
触られるのは嫌だ。
人間が近づいてくるのも嫌だ。
「……悪いが、急いでるんだ」
「逃げんなよ。 ちょっと話そうぜ」
「断る」
俺は早足でギルドを出た。
背後から「おい、待てって!」という声が聞こえたが、無視した。
人混みに紛れ、路地裏を抜け、できるだけ距離を取る。
「……はぁ、はぁ……っはぁ」
息が上がっている。
別に走ったわけでもないのに、心臓がバクバクしている。
人と関わるのは、やはり疲れる。
「こういう時は……酒だな」
俺は、酒を出す店を探し始めた。
◆◆◆◆◆
念のためアドミンの姿に戻ってから歩いていると、街のはずれにひっそりとしたバーを見つけた。
看板には『静寂の杯』と書かれている。
中に入ると、照明は暗く、客は誰もいなかった。
カウンターの奥には、口ひげを整えたダンディな中年男性が立っていた。
バーテンダーらしい。
俺がカウンターに座ると、男は無言でグラスを差し出した。
「……頼んでないんだが」
「水です」
「あ……ああ」
なるほど、まず水を出すタイプか。
メニューを見て、適当なエールを注文する。
男は黙ってエールを注ぎ、俺の前に置いた。
「…………」
「…………」
会話がない。
だが、それが心地よかった。
男は何も聞いてこない。
詮索しない。
ただ黙って、俺が飲むのを見ている。
「……いい店だな」
思わず呟いた。
男は小さく頷いただけだった。
俺はエールを一口飲んで、カウンターに肘をついた。
冒険者ギルドは騒がしすぎる。
あそこを拠点にするのは無理だ。
だが、ここなら。
この静かなバーなら、俺でもやっていける気がする。
「……ここを拠点にしよう」
俺は心の中で決めた。
情報収集は酒場でやるものだと、相場は決まっている。
このバーテンダーなら、余計なことを聞いてこないだろう。
エールを飲み干し、二杯目を注文する。
窓の外では、街の喧騒が遠くに聞こえていた。
異世界二日目。
俺は「チェックサム」として、この世界で生きていくことを決めた。
まだログアウトできない理由は分からない。
この世界が本当にゲームなのかも、確信が持てない。
だが、少なくとも――このバーの居心地だけは、悪くなかった。




