- Authors

- Name
- Youngju Kim
- @fjvbn20031
セキュリティ:脅威と防御
オペレーティングシステムのセキュリティは、システムのリソースを不正アクセス、悪意ある変更、破壊から保護することを目標とします。この記事では、セキュリティ脅威の種類、攻撃技法、暗号化の基礎、認証方法、そしてシステムレベルの防御メカニズムを解説します。
1. セキュリティの概要
セキュリティの3要素(CIA Triad)
機密性
(Confidentiality)
╱ ╲
╱ セキュリティ╲
╱ 目標 ╲
╱ ╲
可用性 ─────────── 完全性
(Availability) (Integrity)
| 要素 | 説明 | 脅威の例 |
|---|---|---|
| 機密性 | 認可されたユーザーのみ情報にアクセス | 盗聴、データ漏洩 |
| 完全性 | 認可された方法でのみ情報を変更 | データ改ざん、偽造 |
| 可用性 | 認可されたユーザーが必要時にアクセス可能 | DoS攻撃、ランサムウェア |
セキュリティ脅威の階層
┌──────────────────────────────────────┐
│ 攻撃サーフェス │
│ │
│ 物理的: サーバー直接アクセス、USB │
│ │ │
│ ネットワーク: リモート攻撃、 │
│ │ パケットスニッフィング │
│ │ │
│ OS: 権限昇格、カーネルエクスプロイト│
│ │ │
│ アプリケーション: コードインジェクション│
│ │ │
│ ソーシャルエンジニアリング: │
│ フィッシング、スピアフィッシング │
└──────────────────────────────────────┘
2. プログラム脅威(Program Threats)
マルウェア(Malware)の分類
┌────────────────────────────────────────────────┐
│ マルウェア分類 │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ウイルス │ │ ワーム │ │トロイの │ │
│ │ │ │ │ │木馬 │ │
│ │宿主必要 │ │自己伝播 │ │偽装 │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ランサム │ │スパイ │ │ルートキット│ │
│ │ウェア │ │ウェア │ │ │ │
│ │ファイル │ │情報収集 │ │隠蔽 │ │
│ │暗号化 │ │ │ │ │ │
│ └─────────┘ └─────────┘ └─────────┘ │
└────────────────────────────────────────────────┘
コードインジェクション(Code Injection)
外部入力を通じて悪意あるコードを実行する攻撃です。
// SQL 인젝션 예시 - 취약한 코드
void login(const char *username, const char *password) {
char query[512];
// 위험: 사용자 입력을 직접 쿼리에 삽입
sprintf(query, "SELECT * FROM users WHERE name='%s' AND pass='%s'",
username, password);
execute_query(query);
}
// 공격 입력:
// username: admin' --
// password: (아무 값)
// 생성되는 쿼리:
// SELECT * FROM users WHERE name='admin' --' AND pass='...'
// -- 이후는 주석 처리되어 비밀번호 검증 우회
// 방어: 준비된 문장(Prepared Statement) 사용
void login_safe(const char *username, const char *password) {
// 매개변수화된 쿼리 - 입력이 데이터로만 처리됨
prepare_statement("SELECT * FROM users WHERE name=? AND pass=?");
bind_parameter(1, username);
bind_parameter(2, password);
execute_prepared();
}
バッファオーバーフロー(Buffer Overflow)
最も古典的でありながら依然として危険な攻撃技法です。
// 취약한 코드 예시
void vulnerable_function(const char *input) {
char buffer[64];
// 위험: 입력 길이를 확인하지 않음
strcpy(buffer, input); // 64바이트 이상 입력 시 오버플로
}
スタック構造(オーバーフロー前):
┌──────────────────┐ 高いアドレス
│ リターンアドレス │
├──────────────────┤
│ 前のフレーム │
│ ポインタ │
├──────────────────┤
│ buffer[64] │
│ (64バイト) │
├──────────────────┤ 低いアドレス
スタック構造(オーバーフロー後):
┌──────────────────┐ 高いアドレス
│ 悪意あるコード │ ← リターンアドレスが上書き!
│ アドレス │
├──────────────────┤
│ AAAAAAAAAAAAAAAA │ ← 上書き
├──────────────────┤
│ AAAAAAAAAAAAAAAA │ ← 攻撃データ
│ (64バイト以上) │
├──────────────────┤ 低いアドレス
// 방어: 안전한 문자열 함수 사용
void safe_function(const char *input) {
char buffer[64];
// 길이를 제한하는 안전한 복사
strncpy(buffer, input, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';
}
3. システムおよびネットワーク脅威
ワーム(Worm)
ネットワークを通じて自動的に伝播する自己複製プログラムです。
感染ホストA
│
├── ネットワークスキャン(脆弱なホスト探索)
│
├── ホストB感染(脆弱性悪用)
│ ├── ホストD感染
│ └── ホストE感染
│
└── ホストC感染(脆弱性悪用)
├── ホストF感染
└── ...
指数的伝播 → 短時間で大規模感染
ポートスキャン
攻撃者 対象サーバー
│ │
├── SYN → ポート 22 ────────────→│
│←──────────── SYN-ACK ─────────│ ポート22: オープン(SSH)
│ │
├── SYN → ポート 23 ────────────→│
│←──────────── RST ─────────────│ ポート23: クローズ
│ │
├── SYN → ポート 80 ────────────→│
│←──────────── SYN-ACK ─────────│ ポート80: オープン(HTTP)
...
DoS(Denial of Service)攻撃
通常のリクエスト:
クライアント → [正常なリクエスト] → サーバー → [正常な応答]
DoS攻撃:
攻撃者 → [大量のリクエスト] → サーバー(過負荷)→ 正常なユーザーがアクセス不可
DDoS(分散DoS):
ボットネットホスト1 ─→ ┐
ボットネットホスト2 ─→ ├→ サーバー(過負荷)
ボットネットホスト3 ─→ ┤
... ─→ ┘
SYN Flood攻撃:
攻撃者がSYNパケットのみ大量送信、SYN-ACK応答無視
→ サーバーの接続待ちキュー枯渇
4. 暗号化(Cryptography)
対称鍵暗号化
1つの鍵で暗号化と復号化の両方を行います。
送信者 受信者
┌──────┐ ┌──────────┐ ┌──────┐
│平文 │─→ │暗号化 │─→ │暗号文│─→ ... ─→ ┌──────────┐─→ ┌──────┐
│Hello │ │(秘密鍵) │ │X7k9p│ │復号化 │ │Hello │
└──────┘ └──────────┘ └──────┘ │(同じ鍵) │ └──────┘
└──────────┘
アルゴリズム: AES (128/192/256ビット), ChaCha20
問題: 鍵交換 - どうやって安全に鍵を共有するか?
非対称鍵暗号化(公開鍵暗号化)
公開鍵と秘密鍵のペアを使用します。
受信者の鍵ペア:
┌──────────┐ ┌──────────┐
│ 公開鍵 │ │ 秘密鍵 │
│ (公開) │ │ (非公開) │
└──────────┘ └──────────┘
暗号化:
送信者: 平文 + 受信者公開鍵 → 暗号文
復号化:
受信者: 暗号文 + 受信者秘密鍵 → 平文
デジタル署名:
署名者: ハッシュ + 署名者秘密鍵 → 署名
検証者: 署名 + 署名者公開鍵 → ハッシュ確認
アルゴリズム: RSA, ECC(楕円曲線暗号)
ハッシュ関数
任意の長さの入力を固定長の出力に変換します。
入力 SHA-256ハッシュ
"Hello" → 185f8db32271fe25f561a6fc938b2e26
4306ec304eda518007d1764826381969
"Hello!" → 334d016f755cd6dc58c53a86e183882f
8ec14f52fb05345887c8a5edd42c87b7
特性:
- 一方向: ハッシュから原本の復元不可
- 衝突耐性: 同じハッシュを生成する異なる入力を見つけにくい
- 雪崩効果: 入力1ビットの変更でハッシュが大きく変化
用途: パスワード保存、完全性検証、デジタル署名
アルゴリズム: SHA-256, SHA-3, bcrypt(パスワード用)
// 비밀번호 해싱 예시 (의사 코드)
#include <openssl/sha.h>
#include <string.h>
#include <stdio.h>
void hash_password(const char *password, const char *salt,
unsigned char *hash_out) {
char salted[256];
// 솔트(salt)를 추가하여 레인보우 테이블 공격 방지
snprintf(salted, sizeof(salted), "%s%s", salt, password);
SHA256((unsigned char *)salted, strlen(salted), hash_out);
}
int verify_password(const char *input, const char *salt,
const unsigned char *stored_hash) {
unsigned char computed[SHA256_DIGEST_LENGTH];
hash_password(input, salt, computed);
return memcmp(computed, stored_hash, SHA256_DIGEST_LENGTH) == 0;
}
5. ユーザー認証(User Authentication)
認証方法の分類
┌─────────────────────────────────────────────┐
│ 認証要素(Factor) │
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ 知識ベース│ │ 所有ベース│ │ 生体ベース│ │
│ │(知っている│ │(持っている│ │(自分自身の│ │
│ │ もの) │ │ もの) │ │ 特性) │ │
│ │ │ │ │ │ │ │
│ │ パスワード│ │セキュリティ│ │ 指紋 │ │
│ │ PIN │ │トークン │ │ 虹彩 │ │
│ │ 秘密の質問│ │スマートカード│ │ 顔認識 │ │
│ │ │ │ OTP │ │ │ │
│ └───────────┘ └───────────┘ └───────────┘ │
│ │
│ 多要素認証(MFA): │
│ 2つ以上の要素を組み合わせてセキュリティ強化 │
└─────────────────────────────────────────────┘
パスワードセキュリティ
脆弱なパスワード保存:
┌──────────────────────────────────┐
│ usersテーブル │
│ username │ password │
│ admin │ admin123 ← 平文!│
│ user1 │ password1 ← 危険!│
└──────────────────────────────────┘
安全なパスワード保存:
┌──────────────────────────────────────────────┐
│ usersテーブル │
│ username │ salt │ hashed_password │
│ admin │ x7k2m9 │ a3f2e8...(ハッシュ値)│
│ user1 │ p4q8n1 │ b7d1c5...(ハッシュ値)│
└──────────────────────────────────────────────┘
→ ソルト + 低速ハッシュ(bcrypt, Argon2)
6. セキュリティ防御(Security Defenses)
ファイアウォール(Firewall)
外部ネットワーク(インターネット)
│
┌────┴─────────────────┐
│ ファイアウォール │
│ │
│ ルール例: │
│ 許可: TCP 80 (HTTP) │
│ 許可: TCP 443 │
│ 遮断: TCP 23 │
│ 遮断: その他全ポート │
└────┬─────────────────┘
│
内部ネットワーク(LAN)
侵入検知システム(IDS)
ネットワークトラフィック
│
▼
┌─────────────────────┐
│ IDSエンジン │
│ │
│ シグネチャベース: │
│ 既知の攻撃パターン │
│ マッチング │
│ │
│ 異常検知ベース: │
│ 正常パターン学習後 │
│ 異常行動を検知 │
│ │
│ マッチ時 → アラート│
└─────────────────────┘
ASLR(Address Space Layout Randomization)
バッファオーバーフロー攻撃を困難にする技法です。
ASLRなし(固定アドレス): ASLR適用(ランダムアドレス):
┌──────────────────┐ ┌──────────────────┐
│ 0x08048000 コード│ │ 0x55a3b000 コード│ ← 毎回異なるアドレス
│ ... │ │ ... │
│ 0xBFFF0000 スタック│ │ 0x7FFD2000 スタック│ ← 毎回異なるアドレス
└──────────────────┘ └──────────────────┘
攻撃者がアドレスを予測可能 攻撃者がアドレスを予測不可能
その他の防御技法
┌─────────────────────────────────────────┐
│ セキュリティ防御技法 │
│ │
│ スタックカナリ(Stack Canary): │
│ リターンアドレスの前に監視値を置いて │
│ オーバーフロー時の変更を検知 │
│ │
│ DEP(Data Execution Prevention): │
│ スタック/ヒープ領域でのコード実行禁止 │
│ W^X: 書き込み可能 XOR 実行可能 │
│ │
│ CFI(Control Flow Integrity): │
│ プログラムの制御フローが予想経路のみ │
│ をたどるよう強制 │
└─────────────────────────────────────────┘
7. まとめ
- プログラム脅威: マルウェア(ウイルス、ワーム、ランサムウェア)、コードインジェクション、バッファオーバーフロー
- ネットワーク脅威: ポートスキャン、DoS/DDoS攻撃、中間者攻撃
- 暗号化: 対称鍵(AES)、非対称鍵(RSA)、ハッシュ(SHA-256)
- 認証: 知識/所有/生体ベース、多要素認証(MFA)
- 防御: ファイアウォール、IDS/IPS、ASLR、DEP、スタックカナリ、CFI
クイズ:セキュリティ
Q1. バッファオーバーフロー攻撃を防御する技法を3つ説明してください。
A1. (1) ASLR:メモリアドレスをランダムに配置し、攻撃者が目標アドレスを予測しにくくします。 (2) スタックカナリ:リターンアドレスの前に監視値を置いて、オーバーフロー時の変更を検知します。 (3) DEP(Data Execution Prevention):スタックやヒープ領域でのコード実行を禁止し、注入されたコードが実行されないようにします。
Q2. 対称鍵暗号化と非対称鍵暗号化の違いは?
A2. 対称鍵は1つの鍵で暗号化と復号化の両方を行うため高速ですが、鍵を安全に交換する問題があります。非対称鍵は公開鍵と秘密鍵のペアを使用して鍵交換問題を解決しますが、演算が遅いです。実際にはハイブリッド方式で、非対称鍵で対称鍵を交換した後、対称鍵でデータを暗号化します。
Q3. パスワード保存時にソルト(salt)を使用する理由は?
A3. 同じパスワードでもユーザーごとに異なるソルトを追加すればハッシュ値が異なります。これによりレインボーテーブル(事前計算されたハッシュ辞書)攻撃を無力化し、同じパスワードを使用するユーザーをハッシュ値だけで識別できなくします。