Vol.02 開発するなら知っておくべきセキュリティ設計の基本
- 友弘 山崎
- 3月10日
- 読了時間: 14分
更新日:4月14日

この記事であなたがやるべきこと
後述する「安全なシステムを作るためのセキュリティ設計のコツ」を理解して、
開発プロセスのどの段階で、どのようなセキュリティ対策を取り入れるべきかを把握し、
実装やテストに落とし込めるようになること
システム開発におけるセキュリティ設計の重要性
Webアプリケーションやシステムを開発するとき、どうしても機能やデザインに注力しがちです。「この機能を実装しよう」「このUIがかっこいい」と考えることは大切ですが、セキュリティ対策をおろそかにすると、あとで大きな代償を払うことになります。
セキュリティがザルなシステムは、ハッカーにとって格好の標的になります。おしゃれなカフェを開店したのに、ドアに鍵をかけずに「ご自由にどうぞ」状態では、いつの間にかレジの中身が消えているかもしれません。それと同じで、機能が素晴らしくても、セキュリティが不十分ではシステムの価値は大幅に下がってしまいます。
さらに問題なのは、後からセキュリティ対策を追加すると、修正コストが爆発的に増加することです。「最初にちょっと対策しておけばよかった…!」と後悔する前に、今からでも基本を押さえておきまし
ょう。
セキュリティを高める上で、すごく大事なマインド

セキュリティと利便性のトレードオフ
セキュリティとは常に利便性とトレードオフです。セキュリティを高めれば、必然的に利便性は低下します。人間は自然と楽な方に意識が傾くため、無意識のうちにセキュリティを犠牲にしがちです。
例えば、以下のような考えは危険信号です:
「面倒だからみんなに管理者権限を付与しておこう」
「パスワードを覚えるのが面倒だから共通のパスワードにしておこう」
セキュリティの「見えない価値」問題
セキュリティを高めたところで、誰からも積極的に評価されることはほとんどありません。一般的に評価されるのは目に見える成果ですが、セキュリティという「目に見えづらいもの」は評価されにくい性質があります。
だからこそ、自らを律して利便性を多少犠牲にしてでもセキュリティを高めるという強い意識が必要です。この意識がなければ、日々の業務の中でセキュリティレベルは徐々に低下していきます。
組織文化の重要性
個人の意識だけでセキュリティを長期的に高く保つことは困難です。抜本的にセキュリティを向上させるためには、組織としての文化の醸成が非常に重要になります。
セキュリティを重視する文化が根付いた組織では、セキュリティ対策が「面倒なこと」ではなく「当たり前のこと」として認識され、持続可能なセキュリティ体制を構築することができます。
開発者が知るべきセキュリティ設計の基本とは?

セキュリティ設計とは?
セキュリティ設計とは、システムやアプリケーションを安全に保つための対策を最初から考慮した設計プロセスのことです。家を建てるときに基礎工事や耐震設計が重要なように、システム開発においても安全性を確保するための設計が不可欠です。
セキュリティ設計の目的は以下の通りです:
不正アクセスやデータ漏えいを防ぎ、情報を安全に管理すること
外部からの攻撃に対して強固な防御を構築すること
初期段階での対策によって後の修正コストを削減すること
「セキュリティは後から追加すればいい」と考えると、以下の問題が発生します:
修正が難しくなる(既存の機能と衝突する可能性)
コストが増加する(設計変更や追加開発が必要になる)
リリースが遅れる(再テストや確認作業が増える)
家を建てた後に「やっぱり地下シェルターを作ろう!」と言うようなものです。設計段階で考えておけばスムーズなのに、後から気づくと余計な手間とコストがかかるのです。
セキュリティ設計の基本原則

セキュリティ設計で大切なのは、複雑なテクニックではなく、シンプルな原則を守ることです。以下の3つの基本原則を開発に取り入れましょう。
1. 最小特権の原則
最小特権の原則とは、システムの利用者やプログラムに必要最低限の権限だけを与えることです。
例えば、以下のようなケースは避けるべきです:
新入社員にとりあえず管理者権限を付与する
データベースへのアクセスに常に書き込み権限を付与する
すべてのシステムコンポーネントに同じ権限を設定する
対策としては:
データベースアクセスは必要な操作(読み取りのみ、特定テーブルのみなど)に限定する
管理機能は管理者アカウントのみに制限する
API連携は必要な機能のみに限定する
「とりあえずフル権限」はセキュリティ事故の第一歩。常に「この操作に本当にこの権限が必要か?」と考えることが大切です。
2. デフォルトで安全にする
システムやアプリケーションは、初期状態でセキュアな設定にしておくべきです。「ユーザーが適切に設定するだろう」という期待は禁物です。
良い例:
管理画面のログインは、デフォルトでパスワード必須+多要素認証が有効
データの暗号化がデフォルトで有効
不要な機能やポートは初期状態で無効
悪い例:
デフォルトパスワードが「admin」「password」などの予測しやすいもの
管理者ページが認証なしでアクセス可能
機密データが平文で保存される初期設定
人間は忘れる生き物です。最初から安全な状態にしておけば、設定漏れによるセキュリティホールを防ぐことができます。
3. シンプルさを保つ
セキュリティ設計は「複雑であるほど安全」ではありません。むしろ、複雑すぎるシステムはエラーや設定ミスを招きやすくなります。
シンプルな設計のメリット:
テストやメンテナンスがしやすい
トラブル発生時に原因を特定しやすい
設定ミスが起こりにくい
複雑な設計の問題点:
アクセス制御が複雑すぎて、誰がどのデータを見られるのか不明確
設定が多すぎて間違いが生じやすい
障害発生時の切り分けが困難になる
「管理しやすく、誰が見てもルールが明確」な設計を心がけましょう。
よくあるセキュリティの脅威を知ろう

どれだけ頑丈なセキュリティ対策を施しても、敵の攻撃手法を知らなければ防ぎきれません。開発者として、代表的な攻撃手法を知っておくことは必須です。
1. SQLインジェクション
SQLインジェクションは、Webアプリケーションの入力欄に悪意のあるコードを仕込み、データベースを不正に操作する攻撃です。
攻撃例
例えば、ユーザーがログインする際に次のようなSQL文が使われるとします。
ここで、ユーザー名の入力欄に ' OR '1'='1 と入力されると、SQL文は次のように変化します。
この条件では、'1'='1' の部分が常に真になるため、パスワードなしでログインできてしまいます。
対策
プレースホルダー(バインド変数)を使う:ユーザー入力とSQL文を分離する
入力値を適切にエスケープ処理する:特殊文字を無害化する
アプリケーションの権限を最小限にする:DBアクセス用のアカウントに必要最低限の権限のみを付与
2. クロスサイトスクリプティング(XSS)
XSSは、悪意のあるスクリプトをWebページに埋め込み、別のユーザーのブラウザで実行させる攻撃です。
攻撃例
掲示板に次のようなコメントが投稿されたとします。
このコメントがそのままWebページに表示されると、閲覧者のブラウザでスクリプトが実行され、情報が盗まれる可能性があります。
対策
入力データをエスケープ処理する:<script> タグを <script> に変換するなど
Content-Security-Policy(CSP)を設定する:信頼できるソースからのスクリプトのみ実行を許可
HttpOnly属性のクッキーを使用する:JavaScriptからのクッキーアクセスを防止
3. バッファオーバーフロー
バッファオーバーフローは、プログラムの想定以上のデータを入力し、システムの動作を不正に変える攻撃です。
ただしモダンな言語では言語レベルで対策ができているので意識しないことがほとんどですが、知識としては知っておいてください。
攻撃例
C言語の次のようなコードを考えてみます。
10文字を超えるデータを入力すると、メモリの境界を越えてしまい、プログラムの挙動を変えることができます。
対策
安全な関数を使う:gets ではなく fgets など、バッファサイズを指定できる関数を使用
入力値の長さを明確に制限する:常に入力データの長さをチェック
アドレス空間配置のランダム化(ASLR)を有効にする:メモリアドレスの予測を困難にする
安全なシステムを作るためのセキュリティ設計のコツ

最初からセキュリティを考えよう
セキュリティは後付けではなく、開発の初期段階から考慮するべきです。
開発プロジェクトのスタート時に決めておくべきこと
ユーザー認証の方法(パスワード要件、多要素認証の有無など)
データの保存や通信に関する暗号化方針
権限管理の設計(ロールベースアクセス制御など)
チーム全体でセキュリティを意識するためのポイント
コードレビューではバグだけでなく、セキュリティの観点もチェック
認証や認可の処理に抜け穴がないか確認
ユーザー入力データの適切なバリデーションを実施
ログを適切に記録し、不正アクセスを検知できるようにする
リスク分析のアプローチ
開発初期に攻撃パターンをリストアップ
システムのどの部分が狙われやすいかを分析
優先度をつけて対策を検討
セキュアコーディングガイドラインを活用しよう
個人の経験だけに頼らず、確立されたガイドラインを参考にしましょう。
代表的なガイドライン
OWASP(Open Web Application Security Project) - Webアプリケーション向けの包括的ガイドライン
CWE(Common Weakness Enumeration) - ソフトウェアの脆弱性分類
ISO/IEC 27001 - 情報セキュリティマネジメントの国際規格
ガイドラインを活用するメリット
経験の有無に関わらず、一定水準のセキュアなコードを書ける
セキュリティの抜け漏れを防止できる
既知の脆弱性パターンを回避できる
チームでの共有方法
定期的な勉強会の開催
コードレビュー時のチェックリストとして活用
新メンバー向けの研修資料として整備
セキュリティテストを実施しよう
「完璧なコード」は存在しません。必ずテストを行い、脆弱性を発見・修正しましょう。
セキュリティテストの種類
解析方法 | 説明 |
静的解析(SAST) | ソースコードを実行せずに分析。コード内のバグや脆弱性を自動検出。 |
動的解析(DAST) | 実際にシステムを動かしながら問題を探す。実行中の挙動を確認し、実際の攻撃をシミュレーション。 |
ペネトレーションテスト
「ペネトレーションテスト」は、システムに対して擬似的に攻撃を行い、脆弱性を見つけるテストです。実際のハッカーの視点でシステムの弱点を発見できます。
内部チームだけでなく、外部の専門家に依頼することも検討
最新の攻撃手法に精通したプロによるテストが効果的
定期的に実施することで、新たな脆弱性を早期発見
自動化ツールの活用
静的解析ツール(SonarQube、Checkmarx等)
Webアプリケーションスキャナー(OWASP ZAP、Burp Suite等)
依存ライブラリの脆弱性チェックツール(OWASP Dependency Check等)
自動化ツールはあくまで補助であり、手動テストと組み合わせることが重要です。
セキュリティ設計に基づく安全なコードの書き方

以下にセキュアなコードを書くための具体的な方法を紹介します。
1. 入力バリデーションを厳守しよう
ユーザー入力は基本的に信頼せず、必ず検証しましょう。
ホワイトリスト方式とブラックリスト方式
方式 | 説明 | 推奨 |
ホワイトリスト方式 | 許可するパターンのみを指定し、それ以外を拒否 | ◎ |
ブラックリスト方式 | 禁止するパターンを指定し、それ以外を許可 | △ |
セキュリティ面では、ホワイトリスト方式が推奨されます。ブラックリスト方式では、新たな攻撃手法に対応できないことがあります。
コード例(JavaScriptでの入力バリデーション)
バリデーションのポイント
ユーザー入力は常に疑い、必ず検証する
ホワイトリスト方式で許可するデータを明確にする
正規表現や型チェックで入力内容を制御する
2. 認証と認可を正しく設定しよう
認証(本人確認)と認可(権限管理)は、セキュリティの重要な柱です。
認証と認可の違い
用語 | 説明 |
認証(Authentication) | ユーザーが本人であることを確認するプロセス |
認可(Authorization) | 認証されたユーザーの権限を管理するプロセス |
安全な認証・認可のポイント
強力なパスワードポリシーを導入(長さ、複雑さ、有効期限など)
多要素認証(MFA)を実装
パスワードはハッシュ化して保存(平文では絶対に保存しない)
アクセストークンの有効期限を適切に設定
コード例(PHPでの認証例)
3. データを暗号化して守ろう
機密データは必ず暗号化して保存・送信しましょう。
対称鍵と非対称鍵の違い
暗号化方式 | 説明 | 用途 |
対称鍵暗号化 | 暗号化と復号に同じ鍵を使用。処理が速い。 | セッションデータ、ファイル暗号化 |
非対称鍵暗号化 | 公開鍵と秘密鍵のペアを使用。鍵の共有が安全。 | ユーザー認証、デジタル署名 |
コード例(Pythonでの暗号化)
データを暗号化のポイント
機密データは平文で保存せず、必ず暗号化する
通信時はTLS/SSLを使用し、データを保護する
暗号鍵の管理を厳重に行う(鍵の漏洩は暗号化の意味をなくす)
4. セッション管理を強化しよう
Webアプリケーションでは、セッション管理が重要なセキュリティポイントです。
セッションセキュリティのポイント
セッションIDはランダムで予測困難なものを使用
定期的にセッションIDを再生成して、セッション固定攻撃を防止
セッションタイムアウトを設定し、自動ログアウトを実装
セッションデータは安全に保存(暗号化またはサーバーサイドでの保管)
コード例(PHPでのセッション管理)
5. エラーハンドリングとロギングを実装しよう
エラーは適切に処理し、詳細情報はユーザーに表示せず、ログに記録しましょう。
エラーメッセージの管理
ユーザーには簡潔なエラーメッセージのみ表示
詳細なエラー情報(スタックトレースなど)はログに記録
ログファイルは適切にアクセス制限し、機密情報漏洩を防ぐ
コード例(Pythonでのエラーハンドリングとロギング)
よくある疑問・注意点
Q: セキュリティ対策を強化すると使いやすさが損なわれる?
バランスが重要です。たとえば、毎回ログイン時に20桁のパスワードと複数の認証を求めると、ユーザーは面倒に感じるでしょう。しかし、生体認証やシングルサインオン(SSO)を導入すれば、セキュリティを確保しつつ利便性を向上できます。
Q: 小規模なサービスでもセキュリティ対策は必要?
規模に関係なく、基本的なセキュリティ対策は必須です。個人開発や小さなチームのプロジェクトでも、SQLインジェクションやXSSの対策を怠ると、攻撃者に狙われる可能性があります。特に、ユーザーの個人情報を扱う場合は注意が必要です。
Q: セキュリティテストはどのタイミングで行うべき?
開発の最後だけでなく、継続的に実施するのが理想です。コードを書いた直後の静的解析、アプリが動く状態での動的解析、そして本番環境を想定したペネトレーションテストを行いましょう。また、定期的なセキュリティ診断も重要です。
Q: セキュリティ対策は「完璧」にできる?
残念ながら、「100%安全なシステム」は存在しません。ハッカーは常に新しい手法を開発しているため、セキュリティ対策は「一度やれば終わり」ではなく、継続的なメンテナンスが必要です。定期的な脆弱性スキャンやセキュリティアップデートを欠かさず行いましょう。
今日から実践! 開発者向けセキュリティ設計チェックリスト
以下のチェックリストを使って、自分のプロジェクトのセキュリティレベルを確認しましょう。
設計フェーズ
セキュリティ要件を明確に定義している
最小特権の原則に基づいた権限設計をしている
デフォルトで安全な設定になっている
リスク分析を実施し、攻撃パターンを洗い出している
実装フェーズ
セキュアコーディングガイドラインに従っている
入力データを適切にバリデーションしている
認証・認可のメカニズムを正しく実装している
機密データを暗号化して保存している
セッション管理を適切に実装している
エラーメッセージに機密情報を含めていない
テストフェーズ
静的解析ツールを使用している
動的解析ツールを使用している
セキュリティに焦点を当てたコードレビューを実施している
ペネトレーションテストを実施している
運用フェーズ
セキュリティログを適切に記録・監視している
セキュリティアップデートを定期的に適用している
インシデント対応計画を策定している
定期的なセキュリティ診断を実施している
まとめ
セキュリティ設計は、システム開発の「あとで考える」要素ではなく、最初から組み込むべき重要な要素です。本記事で紹介した基本原則や実装方法を取り入れることで、より安全なシステムを効率的に構築できます。
セキュリティは「完璧」を目指すのではなく、継続的に改善していく姿勢が重要です。今日から少しずつでも対策を取り入れ、ユーザーと自社の大切な情報を守るシステム開発を心がけましょう。
日々進化するサイバー攻撃に対抗するには、知識のアップデートも欠かせません。開発者コミュニティや専門機関の情報を定期的にチェックし、最新のセキュリティ動向を把握することをおすすめします。