これから開発を始める場合のセキュリティ

(Last Updated On: 2018年3月17日)

取り敢えず言語とプログラミングの基礎を学習し終えて、これから本格的にソフトウェア開発をしよう、という場合に困るのが「セキュリティ」です。今回は簡単に、これから本格的に開発を行う、という方向けに知っておくべき事を紹介します。

初めてTeratailに回答した内容を多少まとめて加筆したモノになっています。

https://teratail.com/questions/74317

ブログにしたので、Tratailの回答は単純にこのエントリを参照するように修正するかも知れません。

 

ISO 27000

体系的に情報セキュリティを学ぶなら、まず一度ISO 27000(国際情報セキュリティ標準)を読むと良いです。ISO 27000はISMS(情報セキュリティマネジメントシステム)認証の基盤となる標準規格です。日本でも5000ほどの組織が認証を取得しています。

ISO 27000はJIS規格化されています。 JIS規格の規格部分はオンライン参照できるようになっています!時々システム障害(過負荷?)で見れないこともありますが、誰でも気軽に参照できることは素晴らしいことだと思います。

「情報セキュリティ」をキーワードにして検索するとJIS Q 27002:2014(ISO/IEC 27002:2013)などが表示されます。

よく見落としがちなものが用語の定義です。ISO 27000では「セキュリティ対策」という曖昧な用語は直接定義していません。最も近い物が「Risk Treatment」です。

標準と基本概念から学ぶ正しいセキュリティの基礎知識

現在のISO 27000ではセキュアプログラミングを実施するように要求しています。

ISO 27000とセキュアプログラミング

 

セキュアプログラミング

ISO 27000で体系的なセキュリティの概要を学んだ次には、ISO 27000で要求されているセキュアコーディング/セキュアプログラミングの「基本概念」を理解してから取り組むのが近道です。セキュアコーディング/セキュアプログラミングと言えばCERTです。

CERT Top 10 Secure Coding Practices

OWASPは簡単にセキュアコーディングのチェックリストとして利用できるクイックリファレンスガイドを公開しています。

OWASP Secure Coding Practices – Quick Reference Guide

 

契約プログラミング(契約による設計)

セキュアコーディング/セキュアプログラミングを理解した次に、契約プログラミングの概念を理解すると良いでしょう。

エンジニア必須の概念 – 契約による設計と信頼境界線

セキュアプログラミング(防御的プログラミング)の歴史をざっと振り返る

契約プログラミングを行う場合、正しい信頼境界の概念が重要です。プログラム中には信頼できないデータが多数存在します。信頼境界を考える場合、コンテクストが重要になります。

 

信頼境界線とセキュリティ設計

https://blog.ohgaki.net/how-to-draw-and-protect-trust-boundaryシステム/ネットワークセキュリティ設計とソフトウェアセキュリティ設計では着目する「コンテクスト」が異なります。ソフトウェアセキュリティ設計では「データ」と「ソフトウェア」が重要です。

信頼境界線の引き方と防り方 – セキュリティの構造と設計

エンジニア必須の概念 – 契約による設計と信頼境界線

また契約プログラミングの論理的背景である、必要十分条件がよく理解されていないケースが散見されるので「正しくコードが動作する必要十分条件」の再確認もオススメします。

プログラム・コードが正しく動作する為の必要条件と十分条件

 

出力コンテクストとセキュリティ

コンテクストは出力のセキュリティ対策でも重要です。HTTPやHTML、SQLといったコンテクストも重要ですが、HTMLやSQLなど複雑な処理系の場合、HTML/SQLのどのコンテクストに出力しているのか、正確に把握する必要があります。

テキストインターフェース処理の基本

完全なSQLインジェクション対策

セキュアコーディングや契約プログラミング、信頼境界やコンテクストを理解したら、個別の脆弱性がどのように生まれるのか?自分で理解できるようになりますが、よくあるリスクの一覧と対策はガイドラインを参照するとよいでしょう。

 

よくある脆弱性の一覧と対策

OWASP(Open Web Application Security Project)がよくある脆弱性トップ10とその対策をガイドラインとしてまとめています。

https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project

現在は今年リリース予定のOWASP TOP 10の2017年版のRCが参照できます。こちらは以前の物より改善されているので、現行版でなくRC版を参照すると良いと思います。

OWASP TOP 10で一番目の問題とされているのはInjectionです。私のブログでもほとんどのセキュリティ問題はインジェクションであると書いています。

ほとんどのセキュリティ問題はインジェクション問題 – インジェクションパターンとして理解すると簡単

2017年版RCのOWASP TOP 10のA1-Injectionの”How Do I Prevent Injection?”では、以下のような対策をするようにとしています。

How Do I Prevent Injection?

Preventing injection requires keeping untrusted data separate from commands and queries.

1. The preferred option is to use a safe API which avoids the use of the interpreter entirely or provides a parameterized interface. Be careful with APIs, such as stored procedures, that are parameterized, but can still introduce injection under the hood.

2. If a parameterized API is not available, you should carefully escape special characters using the specific escape syntax for that interpreter. OWASP’s Java Encoder and similar libraries provide such escaping routines.

3. Positive or “white list” input validation is also recommended, but is not a complete defense as many situations require special characters be allowed. If special characters are required, only approaches (1) and (2) above will make their use safe. OWASP’s ESAPI has an extensible library of white list input validation routines.

パラメーターと命令を分離するAPIを利用する。ただし、APIは安全とは限らないので必ず制限/仕様を正しく理解して利用する。APIで十分に安全化どうか、を確実に判断するには正しいエスケープ処理の知識が必要になることがほとんどです。

エスケープファースト、この順序は変えられない

パラメーターと命令を分離するAPIを利用できない場合は、注意深くエスケープする。

そもそもエスケープとは何なのか?

ホワイトリスト型の入力バリデーションもインジェクション対策として非常に効果的です。ただし、入力バリデーションのみで完全なセキュリティ対策を行うものではない、ことに注意してください。ISO 27000で要求されている入力バリデーションは以下のような物になります。

ISO 27000の入力データ妥当性確認

契約プログラミングを理解していれば自明ですが、最も効果的な入力バリデーションは「ソフトウェアが入力を受け付けた直後に行う入力バリデーション」です。MVCアーキテクチャーの場合、モデルやビューでのバリデーション遅すぎます。コントローラーでバリデーションするのが最適です。

2017年版RCのOWASP TOP 10のA7-Insufficient Attack Protectionは以下のような対策を求めています。

1. Detect Attacks. Did something occur that is impossible for legitimate users to cause (e.g., an input a legitimate client can’t generate)? Is the application being used in a
way that an ordinary user would never do (e.g., tempo
too high, atypical input, unusual usage patterns,
repeated requests)?
2. Respond to Attacks. Logs and notifications are critical to
timely response. Decide whether to automatically block
requests, IP addresses, or IP ranges. Consider disabling or
monitoring misbehaving user accounts.

攻撃を検出すること、検出した攻撃に対応することを求めています。これらの要求を満すには、厳格な入力バリデーションが必要です。推奨される入力バリデーションを実装していれば、

  • 不審な入力データを送信するユーザーをログアウトさせる/アカウントロックする

を簡単に実装できます。もう少し高度なネットワークファイアーウォールを利用したIPアドレスのブロックなどの実装も比較的簡単です。

連続するリクエストや普通でないアクセスパターンの検出と対策は入力バリデーションの機能として実装することも可能ですが、他の機能として実装しても構わないでしょう。

 

まとめ

セキュリティ設計もセキュアコーディングも何も信頼しないことから始める「ゼロトラスト」で考えると自然と安全なモノを作れるようになります。

セキュアプログラミングの7つ習慣

セキュリティは覚える事が沢山ありすぎて大変!と思うかも知れません。しかし、基礎/基本概念さえしっかり理解しておけば、自然と自分で適切な対策が解るようになります。

開発者はセキュリティ問題を自己解決できるのか?

 

 

投稿者: yohgaki