1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【10選】Web開発で遭遇する「え、これダメなやつでは?」な実装たち

Posted at

Web開発の現場では、時々「あれ、これって普通にまずいのでは...?」と思う実装に出くわすことがあります。技術的に高度な話ではなく、むしろ「言われてみれば確かに」というレベルの話なのだけど、意外と見落とされがちなポイントをいくつか挙げてみます。

1.パスワードをそのまま保存してしまう

データベースに password というカラムがあって、そこに「password123」みたいな文字列がそのまま入っている状態。

何が問題なのか:
データベースを見られる人(開発者、インフラ担当者、または侵入者)が、ユーザーのパスワードをそのまま知ることができてしまう。多くの人は複数のサービスで同じパスワードを使い回しているため、一箇所から漏れると他のサービスでも被害が広がる。

どうすればいいのか:
パスワードは「ハッシュ化」という一方通行の変換をかけて保存する。bcryptやArgon2といったアルゴリズムを使えば、元のパスワードに戻すことができない形で保存できる。ログイン時は、入力されたパスワードを同じ方法でハッシュ化して、保存されているハッシュと比較する。

2.個人情報をURLに含めてしまう(GETメソッド)

https://example.com/user?name=山田太郎&email=taro@example.com&phone=090-1234-5678 みたいなURLでページを表示している状態。

何が問題なのか:
URLはブラウザの履歴、サーバーのアクセスログ、プロキシサーバー、リファラー(どのページから来たかの情報)など、様々な場所に記録される。つまり個人情報が色々なところにバラまかれてしまう。URLを誰かに見られただけでも情報が漏れる。

どうすればいいのか:
個人情報を送る時はPOSTメソッドを使う。POSTならデータはリクエストボディに入るので、少なくともURLには表示されない。それでも通信はHTTPSで暗号化することが前提。

3.他のユーザーの情報が見えてしまう(認可の欠如)

/api/users/123/profile にアクセスすると、ユーザーID 123番の人のプロフィールが表示される。ここで「じゃあ124番にしたらどうなる?」とURLを書き換えると、他人の情報が見えてしまう。

何が問題なのか:
これは「認可(Authorization)」が抜けている状態。「ログインしているか」のチェック(認証)だけでは不十分で、「その情報にアクセスする権限があるか」のチェックが必要。URLのパラメータを変えるだけで他人のデータにアクセスできるのは、玄関の鍵は一応かかっているけど、部屋の鍵は全部開きっぱなしみたいなもの。

どうすればいいのか:
サーバー側で「このリクエストをしているユーザーが、このデータにアクセスする権限を持っているか」を必ずチェックする。例えば、ログイン中のユーザーIDとリクエストされたユーザーIDが一致するか、管理者権限を持っているか、などを確認する。

4.他のユーザーの情報を編集できてしまう

上記の「見えてしまう」問題の更新版。/api/users/123 にPUTやPATCHリクエストを送ると、他人のプロフィールや設定を書き換えられてしまう。

何が問題なのか:
情報を見られるだけでも問題だが、書き換えられるのはもっと深刻。メールアドレスを変更されてアカウントを乗っ取られたり、住所を書き換えられて商品が別の場所に送られたり、実害が発生する。

どうすればいいのか:
読み取りと同様に、書き込み操作でも必ず権限チェックを行う。「このユーザーはこのデータを変更できるのか?」という確認を、API側で毎回実装する。フロントエンドで制御するだけでは不十分(ブラウザの開発者ツールで簡単に回避できる)。

5.クレジットカード情報をログに出力してしまう

デバッグのために console.log(requestBody)logger.info(request) みたいなコードを書いて、リクエスト内容をログに残している。ここにクレジットカード番号やセキュリティコードが含まれている。

何が問題なのか:
ログファイルは開発者、運用担当者、場合によっては監視ツールなど、多くの人や システムがアクセスできる。クレジットカード情報は「決済時に一瞬だけメモリを通過して、すぐに忘れる」べきもの。ログに残すと、その情報が長期間、広範囲に晒されることになる。

どうすればいいのか:
機密情報(カード番号、パスワード、個人番号など)は、そもそもログに出力しない設計にする。どうしてもリクエスト全体をログに残したい場合は、機密情報をマスキング(一部を***に置き換える)するか、該当フィールドを除外する処理を入れる。

6.CSRFトークンをコメントアウトしてしまう

フレームワークがデフォルトで提供しているCSRF(クロスサイトリクエストフォージェリ)対策機能を、「動かないから」「面倒だから」という理由で無効化している。

何が問題なのか:
CSRF攻撃は、ユーザーが知らないうちに、悪意あるサイトから正規サイトへリクエストを送らせる攻撃。例えば、罠サイトを開いただけで「退会処理」や「パスワード変更」が実行されてしまう。フレームワークのCSRF対策は、まさにこれを防ぐためにある。

どうすればいいのか:
フレームワークのCSRF対策機能は基本的に有効にしておく。動かない場合は、設定を見直すか、正しい実装方法を調べる。「とりあえずコメントアウト」は、セキュリティホールを自分で開けているようなもの。

7.変数名を連番にする(user1, user2, user3...)

const user1 = getUserById(1);
const user2 = getUserById(2);
const user3 = getUserById(3);

何が問題なのか:
これ自体がセキュリティ問題というわけではないが、コードの可読性が著しく低い。user1が何を表しているのか、コードを読んでも分からない。「現在のユーザー」なのか「対象のユーザー」なのか「比較元のユーザー」なのか、文脈を追わないと理解できない。結果として、バグや脆弱性を生みやすくなる。

どうすればいいのか:
変数名は「何を表しているか」が分かる名前にする。currentUsertargetUserloggedInUserなど、役割が明確な名前をつける。配列ならusersのように複数形にして、users[0]でアクセスする。

8.公開ディレクトリに機密ファイルを置いてしまう

アップロードされた本人確認書類(免許証、マイナンバーカードなど)の画像を、/public/uploads/license_001.jpg みたいに、誰でもアクセスできる場所に保存している。

何が問題なのか:
/public配下のファイルは、URL を知っていれば誰でもアクセスできる。ファイル名が連番なら、license_002.jpglicense_003.jpg と試すだけで、他人の本人確認書類を見ることができてしまう。個人情報保護法違反レベルの情報漏洩につながる。

どうすればいいのか:
機密ファイルは公開ディレクトリの外に保存し、アクセス時は必ず認証・認可を通す。例えば、/api/documents/123 のようなエンドポイントを作り、サーバー側で「このユーザーはこのファイルを見る権限があるか」を確認してから、ファイルを返す。ファイル名も推測されにくいランダムな文字列(UUID等)にする。

9.WebhookやAPIの署名検証をしない

決済サービスからの通知(Webhook)を受け取るエンドポイントで、「本当にその決済サービスからのリクエストか」を確認せずに、送られてきたデータをそのまま信用して処理している。

何が問題なのか:
悪意ある第三者が「入金完了」という偽の通知を送ることで、実際には払っていないのに商品やサービスを受け取れてしまう。決済サービスは通常、「このリクエストが本物だと証明する署名」を付けてくるので、それを検証しないと偽装リクエストを防げない。

どうすればいいのか:
Webhookを受け取るエンドポイントでは、必ず署名検証を実装する。各決済サービスのドキュメントに検証方法が書かれているので、それに従って実装する。検証に失敗したリクエストは無視するか、エラーを返す。

10.テスト用のAPIを本番環境に残してしまう

開発中に作った「テスト用にポイントを追加する」「デバッグ用にユーザーステータスを変更する」みたいなAPIが、本番環境でもアクセス可能になっている。

何が問題なのか:
これらのテスト用APIは、通常の業務フローを無視して直接データを操作できるため、悪用されると致命的。「簡単にコールできる設計」になっているため、認証や認可も緩いことが多い。

どうすればいいのか:
テスト用のコードは、環境変数やビルド設定で、本番環境では完全に無効化する。または、本番環境にデプロイする前にコードごと削除する。「念のため残しておく」は危険。

おわりに

ここに挙げた例は、どれも「高度な技術」ではなく、「基本的な考え方」の問題です。でも、実際の現場では意外とこういう実装に出会うことがあります。

大事なのは、「ユーザーは信頼できる入力をしてくれる」「URLのパラメータは誰も書き換えない」「フロントエンドで制御すれば十分」といった性善説や楽観的な前提を持たないことです。

「もし悪意ある人がこのシステムを使ったら?」「もしパラメータを書き換えられたら?」という視点を常に持つことが、セキュアなシステムを作る第一歩になります。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?