セキュリティプログラミングとは、ソフトウェア開発において、脆弱性を作り込まないように安全な実装を行うことを意味します。目的は、外部からの攻撃や内部不正による情報漏えい、改ざん、サービス停止を防ぐことです。
■ セキュアコーディングの基準
セキュアコーディングのための主なポイントは以下の通りです。
・入力値の検証(バリデーション)
・バッファオーバーフロー対策
・エラーメッセージに機密情報を含めない
・安全な乱数生成(rand()ではなく暗号論的乱数)
これらを規定した代表的なガイドラインには以下があります。
| 基準 | 特徴 | 主な適用分野 |
| OWASP Secure Coding Practices | Webアプリ開発での安全な実装指針 | Webアプリケーション Web API |
| CERT Secure Coding Standard | 言語別の詳細な安全実装ルール | C/C++、Javaなどの組込みや業務アプリ |
| MISRA C / MISRA C++ | 安全性重視の組込みシステム向けルール | 自動車・産業機器 |
これらを中心に、プロジェクトの特徴を踏まえ、コーディング規約として整理します。
基準の沿ったプログラミングが実施されているかを確認するには、有識者によるコーディングレビューだけでは不十分であり、解析ツールを活用する必要があります。
■ OWASP Secure Coding Practiceの概要
チェックリスト形式でプログラミングのチェックポイントを規定しています。
| カテゴリ | 主なチェックポイント |
|---|---|
| 入力検証 | ・ホワイトリスト方式で入力を検証・正規表現や境界チェックを利用 ・信頼できない入力は常に疑う |
| 出力エンコーディング | ・HTML/JavaScript/CSSごとに適切なエスケープ ・テンプレートエンジン利用時もエスケープ確認 |
| 認証とパスワード管理 | ・強力なパスワードハッシュ(bcrypt, PBKDF2, Argon2) ・多要素認証の導入 ・資格情報を平文で保存しない |
| セッション管理 | ・セッションIDは推測困難に ・Secure/HttpOnly クッキーを使用 ・一定時間でセッションをタイムアウト |
| アクセス制御 | ・最小権限の原則 ・ロールベース認可 ・URLやパラメータで直接権限を操作させない |
| 暗号化 | ・AES, RSA, ECCなど強いアルゴリズムを使用 ・TLS1.2以上を利用・鍵は安全に生成・保管・廃棄 |
| エラーハンドリングとロギング | ・詳細なエラーは内部ログのみに記録・利用者には一般的なメッセージのみ返す ・機微情報をログに残さない |
| データ保護 | ・保存時は暗号化・転送時はTLSで暗号化 ・不要になったデータは安全に削除 |
| 通信セキュリティ | ・HTTPSを強制 ・API通信は認証+暗号化必須 ・証明書検証を適切に行う |
| システム構成 | ・不要サービスを停止 ・セキュリティパッチを適用・既定設定のまま運用しない |
| データベースセキュリティ | ・パラメータ化クエリを使用 ・動的SQLを避ける ・DBユーザは最小権限のみ付与 |
| ファイルとリソースアクセス | ・ファイルパスを検証し、ディレクトリトラバーサルを防ぐ ・一時ファイルの権限管理 ・外部リソースの読み込み制御 |
| メモリ管理 | ・C/C++でバッファオーバーフローを防止 ・ポインタ操作に注意 ・自動メモリ管理言語でもオブジェクト寿命を意識 |
| モバイル | ・秘密情報を安全に保存(Keychain, Keystore等) ・証明書ピンニング・逆コンパイル対策 |
| Webサービス | ・SOAP/REST API入力をスキーマで検証 ・強力な認証・認可を導入 ・不要なメソッド/エンドポイントは無効化 |
| 一般的なコーディング実践 | ・定数の利用でマジックナンバーを避ける ・コードレビューを徹底 ・セキュリティテストをCIに組み込む |
■ CERT Secure Coding Standardの概要
CとJavaによるプログラミングの所作について解説しています。
・C言語
| カテゴリ | 主な内容 | 例 |
|---|---|---|
| 環境依存 | OS・処理系に依存する動作を避ける | 改行コードや文字コードの違いに注意 |
| 整数型 | 整数のオーバーフロー/アンダーフローを防ぐ | 型変換、符号付き/符号なしの混在に注意 |
| 浮動小数点型 | 丸め誤差・精度問題に注意 | 比較時は誤差を考慮する |
| 文字列 | 終端文字やバッファ境界を考慮 | strcpyではなくstrncpyを利用 |
| 配列 | 境界チェックを徹底 | 範囲外アクセスを禁止 |
| ポインタ | NULLチェック・不正参照防止 | 解放済みポインタを使用しない |
| 動的メモリ管理 | メモリリーク・二重解放を防ぐ | free()の後はポインタをNULLにする |
| 構造体・共用体 | 境界や未使用領域の扱いに注意 | パディング領域を意識する |
| 式と演算子 | 副作用や未定義動作を避ける | インクリメントの多重使用を禁止 |
| 制御文 | 可読性を高め誤解を防ぐ | if文には必ずブロックを使う |
| 関数 | 引数や戻り値を正しく扱う | 引数の境界検証を徹底 |
| 入出力 | 入力検証・エラー処理を適切に行う | scanfの戻り値を確認する |
| エラー処理 | 戻り値チェック・例外処理を徹底 | 戻り値を無視しない |
| セキュリティ | バッファオーバーフローやSQLi等の脆弱性防止 | 入力サニタイズ、暗号APIの適切利用 |
| 移植性 | 環境差異に影響されない記述 | 固定幅整数型(int32_t等)の利用 |
| 可読性 | コメント・命名規則の徹底 | 一貫したスタイルガイドを適用 |
・Java言語
| カテゴリ | 主な内容 | 例 |
|---|---|---|
| 環境依存 | OS・処理系に依存する動作を避ける | 改行コードや文字コードの違いに注意 |
| 整数型 | 整数のオーバーフロー/アンダーフローを防ぐ | 型変換、符号付き/符号なしの混在に注意 |
| 浮動小数点型 | 丸め誤差・精度問題に注意 | 比較時は誤差を考慮する |
| 文字列 | 終端文字やバッファ境界を考慮 | strcpyではなくstrncpyを利用 |
| 配列 | 境界チェックを徹底 | 範囲外アクセスを禁止 |
| ポインタ | NULLチェック・不正参照防止 | 解放済みポインタを使用しない |
| 動的メモリ管理 | メモリリーク・二重解放を防ぐ | free()の後はポインタをNULLにする |
| 構造体・共用体 | 境界や未使用領域の扱いに注意 | パディング領域を意識する |
| 式と演算子 | 副作用や未定義動作を避ける | インクリメントの多重使用を禁止 |
| 制御文 | 可読性を高め誤解を防ぐ | if文には必ずブロックを使う |
| 関数 | 引数や戻り値を正しく扱う | 引数の境界検証を徹底 |
| 入出力 | 入力検証・エラー処理を適切に行う | scanfの戻り値を確認する |
| エラー処理 | 戻り値チェック・例外処理を徹底 | 戻り値を無視しない |
| セキュリティ | バッファオーバーフローやSQLi等の脆弱性防止 | 入力サニタイズ、暗号APIの適切利用 |
| 移植性 | 環境差異に影響されない記述 | 固定幅整数型(int32_t等)の利用 |
| 可読性 | コメント・命名規則の徹底 | 一貫したスタイルガイドを適用 |
■ MISRA-C/C++の概要
組み込みに特化し、C/C++によるプログラミングの所作について解説しています。
・C言語
| カテゴリ | 例 |
|---|---|
| 型安全性 | 暗黙の型変換を禁止(例:intからfloatへの暗黙変換) |
| ポインタ | NULLチェック必須、算術演算の制限 |
| 配列/文字列 | 境界チェック必須、バッファオーバーフロー防止 |
| 制御文 | goto禁止、switchでdefault必須 |
| 関数 | 再帰禁止、副作用のあるマクロ禁止 |
| 標準ライブラリ | 危険な関数(gets, strcpyなど)の禁止 |
・C++言語
| カテゴリ | 例 |
|---|---|
| クラス設計 | 多重継承制限、仮想継承の注意 |
| 例外処理 | 非推奨、使う場合は制約付き |
| テンプレート | 部分特殊化やSFINAEの乱用禁止 |
| キャスト | reinterpret_cast禁止、static_cast推奨 |
| STL | 使用制限あり(特にメモリ確保や例外関連) |
■ 静的解析(SAST: Static Application Security Testing)
プログラムを実行せずにソースコードやバイナリを解析し、脆弱性やバグを検出する手法です。
コードの全体を網羅的に解析できます。プログラミング段階など開発の早い段階で脆弱性を発見可能です。
代表的ツールとしては、以下があります。
・SonarQube(多言語対応、品質分析)
・Coverity(深いコード解析、産業系で利用)
・Fortify SCA
・CodeQL(GitHubが提供)
■ 動的解析(DAST: Dynamic Application Security Testing)
アプリケーションを実行し、動作中に脆弱性を検出する手法。実際の攻撃シナリオを模してテストします。実際の挙動を確認できます。実行に時間とテスト環境が必要となるため、結合テストやシステムテストにおいて実施します。
代表的ツールとしては、以下があります。
・OWASP ZAP(Webアプリの自動診断)
・Burp Suite(Webセキュリティ診断)
・AppScan
・Arachni
■ まとめ
セキュリティプログラミングは、脆弱性の発生を未然に防ぎ、安全なソフトウェアを作るための基本です。以下のように、セキュアコーディング規約の遵守、静的解析・動的解析の活用、そして運用時まで見据えた設計が不可欠です。
・設計段階での安全性考慮(入力検証、エラー処理、暗号化)
・実装時のコーディング規約遵守(OWASP、CERTなど)
・テスト工程での自動化(SAST、DAST、ペネトレーションテスト)
・リリース後の継続的改善(脆弱性対応、アップデート)
セキュリティは「後付け」ではなく、開発ライフサイクル全体に組み込む文化が必要です。