忘れられた入力処理と出力処理の責任

入力処理と出力処理はプログラムの基本処理です。当たり前の処理ですが、Webアプリケーションでは基本的な事が知られているようで知られてないと思います。

入力処理と出力処理の両方ともがデータに対する責任を持っています。データに対する責任といっても、その責任は異なります。このエントリはプログラムの基本機能、入力処理/ロジック処理/出力処理が持っている責任を紹介します。

脆弱性がないプログラムを作るには、コードからの視点、データからの視点、両方が必要です。ソフトウェアセキュリティの専門家は両方の視点からのセキュリティ対策を啓蒙しているのですが、上手く伝わっていないです。

このエントリはデータからの視点で見たデータセキュリティの話です。

“忘れられた入力処理と出力処理の責任” の続きを読む

入力バリデーションで許可した文字で発生するリスク

入力バリデーションでほぼ全てのインジェクションリスクを回避/防止できるケースは以前書いたブログで紹介しています。

今回は趣向を変えて、入力バリデーションで許可してしまった文字で発生するリスクをざっと紹介します。

※ ここで紹介する考え方は脆弱なブラックリスト型です。より安全な方法はホワイトリスト型の考え方です。参考: ほぼ全てのインジェクション攻撃を無効化/防止する入力バリデーション

“入力バリデーションで許可した文字で発生するリスク” の続きを読む

データのセキュリティ対策が無いセキュリティ対策?!

ソフトウェアのセキュリティ問題の多くは「ソフトウェアの誤作動」です。つまり、正しく動作するソフトウェアならセキュリティ問題の大半は発生しません。1

コンピュータープログラムが正しく動作するには「正しいコード」と「正しいデータ」の両方揃う事が必須条件です。これはプログラムの動作原理に基づく条件なので、誰にも変えることは出来ません。

“データのセキュリティ対策が無いセキュリティ対策?!” の続きを読む

正しく動作するソフトウェアの作り方

ソフトウェアを開発している時に困るのは、ソフトウェアが正しく動作しないケース、に対応する事です。

実用的なソフトウェア作るよりもプロトタイプを作る方が簡単であるのは、ソフトウェアが正しく動作しないケース、に対応する必要がないことが大きな理由です。ソフトウェアが正しく動作しないケースに対応するには、様々な例外的な状態(入力データとソフトウェアの内部状態)全てに対応する必要があります。

例外的な状態を定義するには”ダメな状態”を定義する必要があります。”ダメな状態”を漏れ無く定義するのは結構大変です。ソフトウェアバグの多くは”ダメな状態”を漏れ無く定義することに失敗した為に生まれています。

参考:データセキュリティの概念がないと「正しく動作するプログラム」は作れない。

RDBMSから学ぶデータセキュリティ

”雑”なソフトウェアセキュリティ対策とは?

“正しく動作するソフトウェアの作り方” の続きを読む

インジェクション攻撃は3種類ある

インジェクション攻撃、とは言ってもそのインジェクション対象によって影響が異なります。インジェクション攻撃の対象によって2種類、コードとデータ、に分類できます。Webシステムの場合、リクエストのインジェクションを別のインジェクション攻撃と考えた方が解りやすいので、大まかに分類して3種類に分類できます。

インジェクション脆弱性は絶対に避けなければならない脆弱性である、と認識されていると思います。しかし、3種類あるインジェクション攻撃のうちデータのインジェクションに対するリスク認識が極端に甘いように感じています。

※1 Webシステムを前提としていますが、大抵のシステムは「コード」と「データ」のインジェクションを考慮すれば十分である場合が多いです。

※2 そもそもコードを実行する機能そのものに”コード”を実行させるのは”正当な機能”です。eval( $_GET[‘code’] ) など、これらの機能の基礎的使い方間違いは考慮しません。ここでは本来コードではないデータを介するコードインジェクション、例えば eval( ’var = ‘. $myvar. ‘;’) など、及び、データその物で攻撃するデータインジェクションを取り上げています。

“インジェクション攻撃は3種類ある” の続きを読む

RDBMSから学ぶデータセキュリティ

RDBMSはデータセキュリティを学ぶには良い題材です。RDBMSはできる限り正しいデータを保存する仕組みがあるからです。RDBMSからどのようにデータのセキュリティを保証するのか紹介します。

プログラムが正しく動作する為には

  • 正しいコードであること
  • 正しい(妥当な)データであること

絶対条件です。どちらが欠けてもプログラムは正しく動作しません。

SQLiteは手軽で良いのですが、組み込み型であるためデータセキュリティを学ぶには機能的に問題があります。SQLiteにはデータ型を保証する機能もデータの内容を検証する機能もありません。1

利用するRDBMSはPostgreSQLを用い、データセキュリティに関連性の強い機能のみを対象とします。

“RDBMSから学ぶデータセキュリティ” の続きを読む

脆弱性を呼ばれた側の責任にする、は通用しない

脆弱性を呼ばれた側の責任にする、は常に通用する考え方ではありません。

  • ライブラリに脆弱性があるなら、ライブラリの脆弱性を直す(呼ばれた側の責任にする)
  • 外部アプリケーションに脆弱性があるなら、外部アプリケーションの脆弱性を直す(呼ばれた側の責任する)

は一見正しく見えます。しかし、通用しません。

理由は簡単で、セキュリティ上困った動作をするライブラリやプログラムであっても、それが仕様で脆弱性ではないことがあります。

そもそもライブラリやユーティリティプログラムは幅広い用途に利用できるよう、用途を限定しないよう汎用的に作ってある場合が多いです。こういった仕様の場合、脆弱性を呼ばれた側の責任にする、ではセキュリティ問題を作ってしまいます。

“脆弱性を呼ばれた側の責任にする、は通用しない” の続きを読む

今さら聞けない「コード」と「データ」の話

ビルドを繰り返して時間があったので、ついついとても長いデータの話を書いてしまいました。今さら聞けない「コード(機能)」と「データ」の話として、もっと単純化してみます。

当然の話なのですが、現実には当たり前ではなかったりします。

「データ」のセキュリティを考慮しないセキュリティ対策はあり得ないのですが、多くのプログラムは「コード(機能)」のセキュリティに偏重した構造と対策になっています。

安全なプログラムの作成には「コード(機能)」と「データ」のセキュリティを分けて考える必要があります。

“今さら聞けない「コード」と「データ」の話” の続きを読む

構造化設計とセキュアコーディング設計の世界観は二者択一なのか?

プログラミングの「世界観」

で構造化プログラミング/オブジェクト指向プログラミングの世界観(パラダイム)では、抽象化を行い問題を関数やオブジェクトの中に閉じ込める。つまり、プログラムの内部奥深くに”問題”を閉じ込めようとする。

セキュアコーディングの世界観では、”正しくないデータはどう処理しても正しく処理不可能である”プログラム原理と”失敗する物はできる限り早く失敗させる”Fail Fast原則に従い、できる限り問題となる”データ”を早い段階で廃除する、つまり問題を中に入れずに入り口で対策する、と紹介しました。1

一見すると相反するように見えますが、これら2つの世界観を持つ概念は二者択一ではありません。

“構造化設計とセキュアコーディング設計の世界観は二者択一なのか?” の続きを読む

”形式的検証”と”組み合わせ爆発”から学ぶ入力バリデーション

形式的検証とは

形式的検証(けいしきてきけんしょう)とは、ハードウェアおよびソフトウェアのシステムにおいて形式手法数学を利用し、何らかの形式仕様記述やプロパティに照らしてシステムが正しいことを証明したり、逆に正しくないことを証明することである

英語ではFormal Verificationとされ

formal verification is the act of proving or disproving the correctness of intended algorithms underlying a system with respect to a certain formal specification or property, using formal methods of mathematics.

と説明されています。形式手法として紹介されることも多いです。

参考: 形式検証入門 (PDF)

形式的検証は、記述として検証する方法から数学的にプログラムが正しく実行されることを検証する仕組みまで含みます。数学的な形式的検証では、可能な限り、全ての状態を検証できるようにしてプログラムが正しく実行できることの証明を試みます。

参考:ソフトウエアは硬い (日経XTECHの記事)

契約プログラミング(契約による設計 – Design by Contract, DbC)も形式的検証の1つの方法です。

形式検証の仕組みを知ると、厳格な入力バリデーションが無いと”組み合わせ爆発”により、誤作動(≒ セキュリティ問題)の確率も爆発的に増えることが解ります。

“”形式的検証”と”組み合わせ爆発”から学ぶ入力バリデーション” の続きを読む

「脆弱性を局所的に潰す」はアンチプラクティス

本物の「セキュアコーディング」(セキュアプログラミング)を知ればもう議論など必要ない、と思っています。本物の「セキュアコーディング」を「知ろうとしない」と幾らでもアンチプラクティスを作ってしまいます。

議論は終り、と思っていたのですがそうも行かないようなので紹介します。セキュアコーディングの概念を全く知ろうとしないで、セキュリティを作るのは「ただの無駄」です。多数のアンチプラクティス/間違いが含まれるスライドの中から(一々指摘するとキリがない)

  • 「脆弱性を局所的に潰す」

これ”だけ”だとアンチプラクティスです。

※ 契約プログラミングが流行らない理由はこいうアンチプラクティスも原因でしょう。特定の良いこと”だけ”を積み重ねても良い結果にならない、ことは合成の誤謬として知られています。

“「脆弱性を局所的に潰す」はアンチプラクティス” の続きを読む

セキュリティを論理的に構築する方法

セキュリティの原理、原則、ベストプラクティスに自分でコメントを追加しました。以前、論理的にセキュリティ対策を検証する方法論理的なセキュリティ対策の評価方法は書いたのですが、論理的にセキュリティを構築する方法は書いていないことを思い出しました。追加したコメント欠陥だらけのソフトウェアセキュリティ構造を紹介したブログをベースにセキュリティを論理的に構築する方法を紹介します。

このエントリの解説はCERT、つまり米カーネギーメロン大学、の資料をベースにしています。

“セキュリティを論理的に構築する方法” の続きを読む

セキュリティの原理、原則、ベストプラクティス

「セキュリティの」と付けていますが、どの分野でも共通することだと思います。

何事でも論理的に何かのガイドライン/ルールを作る場合、まず変えることのできない

  • 原理 – 事物・事象が依拠する根本法則

を見つけ、その原理から導き出される

  • 原則 – 多くの場合に共通に適用される基本的なきまり・法則

を作り、さらに特定の条件下の具体的な事例として

を作ります。原理、原則、ベストプラクティスを理解していないと様々な問題がおきます。これらの基本的関係は

原理 > 原則 > ベストプラクティス

です。しかし、適用範囲の広さは

原理 < 原則 < ベストプラクティス

です。例えば、ベストプラクティスは”例外的”に原則に反した方法が”最善の方法”となる場合も少なくないからです。よく混乱や誤解の元になりますが、条件を絞った場合(例外的なケース)のベストプラクティスも在ります。

例外的なケース(一般的で無いモノ=例外的な物)をベストプラクティスにすることには異論もありますが、結構狭い条件でしかベストプラクティスにならないモノが”ベストプラクティス”と呼ばれていることは多いです。1

“セキュリティの原理、原則、ベストプラクティス” の続きを読む

出力対策の3原則 + 1原則

ソフトウェアの不具合/脆弱性を無くすためには、出力先に対して無害であることを保障する出力対策が重要です。どんな出力でも3つの方法で無害化できます。

このブログでは基本として、セキュアコーディングの概念に基き説明しています。先ずはよくある入力対策と出力対策の区別がついていない誤りから紹介します。

参考:IPAは基礎的誤りを明示し、正しい原則を開発者に啓蒙すべき

“出力対策の3原則 + 1原則” の続きを読む

まだ誰も知らない脆弱性/攻撃に備える方法

セキュリティを考えると全ての入力データはアプリケーションがバリデーションすべきで、長さ/形式は厳格にバリデーションすべきです。1

厳格なバリデーションは開発者が意識/把握していない各種インジェクション脆弱性にも対応できること、インジェクション攻撃が持たらす被害が致命的であることが、その理由です。

適切なバリデーションは最強のセキュリティ対策の1つ2です。強いデータ型は弱いバリデーションの一種ですが、それでもセキュリティ対策として高い評価を得ています。にも関わらず強いバリデーションである厳格なデータバリデーションはコンピューターサイエンティストのセキュリティ専門家3以外にはあまり評価されていないように感じます。

今回は低レベルのライブラリにもコードインジェクション脆弱性のリスクがあること、その対策としてバリデーションが如何に効果的であるか紹介します。

“まだ誰も知らない脆弱性/攻撃に備える方法” の続きを読む

実は知られていない?リスク対策の原則?

ISO 31000(リスクマネジメント標準規格)はa)からk)まで、11のリスク管理の原則を定めています。

ITエンジニアであればISO 27000(情報セキュリティマネジメント標準規格)を一度は読んだことがあると思います。少なくとも名前くらいは知っていると思います。リスク管理の基礎/基本を理解していればISO 27000だけでも十分ですが、ちょっと自信がない、体系的には学んだ事がない方はISO 31000も参考にすると良いです。

情報セキュリティマネジメントはリスクマネジメントの一分野です。一般論としてのリスク管理の基礎知識は役立ちます。

リスク対策の原則が知られていない?ことも、間違ったセキュアコーディング理解の原因かもしれません。間違いだらけのセキュアコーディング解説も紹介します。

“実は知られていない?リスク対策の原則?” の続きを読む

4種類の信頼境界とセキュリティ構造 – 構造設計なしのセキュリティ対策?

セキュリティ対策には設計図があります。少なくともアーキテクチャー図があります。しかし、何故かソフトウェアの場合は設計図もアーキテクチャー図も書けないセキュリティ対策が当たり前になっています。国際情報セキュリティ標準やセキュリティガイドラインを普通に理解すれば解ること、セキュリティ対策の基礎の基礎にも関わらず、です。

これは一般開発者の問題というより、セキュリティ専門家やセキュリティに詳しい開発者の問題でしょう。セキュリティ問題は十分に複雑な問題であることに異論はないと思います。複雑な問題を解くにはアーキテクチャー(構造化)と適切な設計が重要です。設計どころかアーキテクチャーさえないのは明らかに問題でしょう。設計となると細かな仕様が必要となります。ここではアーキテクチャーだけでも十分なのでこれだけを考慮します。

重要な事なので最初に書いておきます。セキュリティアーキテクチャー作る、は信頼境界線を書くことです。信頼境界の中に入れたモノ(入力やその他のモノ)であっても、普通は”何をしても安全なモノ”ではありません。安全性の為に更に詳細な入力検証が必要だったり、特定の権限を持つモノだけ許可したりするモノ、条件付きで信頼境界の中に入れるモノが普通にあります。また、信頼境界から出る時(出力)のセキュリティ対策は入力対策とは独立した対策です。これはよくある誤解なので注意しましょう。

信頼境界は”防衛線”です。”防衛線”での防御はITセキュリティ対策に限らず、全てのセキュリティ対策共通した防御策です。”防衛線”の”中に在るモノ”は”信頼できるモノ”であることを可能な限り保証します。”防衛線”を越えて”入るモノ”と”出るモノ”は可能な限り安全性を保証します。これが全てのセキュリティ対策共通の基本です。

※ 信頼境界を越えて検証されたモノ(物/人/データなど)が「全面的に信頼できると誤解される」ことがよくあります。検証されたモノであっても、検証された範囲/内容までしか信頼できません。全面的に信頼できるモノはほぼ無い、とゼロトラストで考える必要があります。

“4種類の信頼境界とセキュリティ構造 – 構造設計なしのセキュリティ対策?” の続きを読む

ゼロトラストをより細かく分解する

セキュリティを維持する為にはゼロトラスト、何も信頼しない所から始めて信頼できることを検証する、作業が必要です。ゼロトラストは信頼できるモノと信頼できないモノに分ける作業ですが、より細かく考える必要があります。

※ より細かく考える、とはいっても「細かい事だけ」では合成の誤謬にハマります。全体と詳細、両方をバランスよく「ゼロトラスト」することが大切です。

“ゼロトラストをより細かく分解する” の続きを読む

Python 2.7.14から学ぶセキュリティの基本

Python 2.7.14が2017/9/16にリリースされました。Pythonの開発はバージョン3系に移行しており、2系はセキュリティ修正のみのリリースになっています。とは言ってもモジュールの変更を見るとバグフィックスやドキュメント修正も含まれているようです。

Python 2.7.14のリリースはソフトウェアセキュリティの基本を学ぶには良い題材になります。

“Python 2.7.14から学ぶセキュリティの基本” の続きを読む