根本的なセキュリティ対策とは何か?

(Last Updated On: )

セキュリティ対策において対策が「根本的」な対策であるかどうか?はあまり重要ではないです。セキュリティ対策において重要なのは対策が「効果的」であるかどうか、が重要だからです。

この基本を押さえた上で、ソフトウェアの「根本的な対策」とは何かを考えてみます。

セキュアプログラミング/セキュアコーディングにおける根本的対策

セキュアプログラミングの基本概念ではソフトウェアのセキュリティを大まかに

  • 入力の対策
  • 出力の対策
  • 処理の対策

の3つに分けて対策します。1

セキュアプログラミングのおける根本的な対策は、この3つで行います。

入力の対策

入力の対策がなぜ根本的になるのか?ソフトウェア誤作動の原因は”悪意のある入力”または”不正な入力”があるから2 3です。問題の原因を元から断つ、は根本的な対策であることに議論の余地はありません。

強いデータ型を持つ言語を例に考えると、入力対策が”根本的な対策”であることがよく理解ります。例えば、期待する入力が整数型である場合、その入力が整数型として正しいことをバリデーションし、整数型のデータ型変数に保存すれば言語がその入力が整数型として処理してくれることを保証してくれます。4 整数型のデータは”整数であることを保証できる”のでインジェクション攻撃に対して脆弱性になりません。5

静的なデータ型を持つ言語でも、セキュリティ的には最大の脅威であるテキスト型に対して、言語として対応することはできません。テキスト型に対する対策、つまりバリデーション、はプログラマに任されています。

参考:

問題の原因を元から断てる場合には「元から断つ」が根本的な対策になります。例えば、OWASPの文書では次のように書いています

Why we have dropped some important issues

Unvalidated input is a major challenge for any development team, and is at the root of many application security problems. In fact, many of the other items in the list recommend validating input as a part of the solution. We still strongly recommend creating a centralized input validation mechanism as a part of your web applications.

私訳:

何故、我われが幾つかの重要な課題を省略したか

バリデーション無しの入力はあらゆる開発チームにとって大きな挑戦であり、多くのアプリケーションセキュリティ問題の根源です。実際、リストの中(訳注:OWASP TOP 10リストのこと)では入力バリデーションを解決策の要素として、多くの項目のなかで推奨しています。我われは貴方が作るWebアプリケーションの機能として集中した入力バリデーションの仕組みを構築することを(OWASP TOP 10リストからは省略しましたが)今でも強く推奨します。

2007年度のOWASP TOP 10では、以前のOWASP TOP 10の第1位として記載されていたUnvalidated Inputがリストから省略されました。その事に関する注意事項が上記の記述です。詳しくは

をご覧ください。要点は、CWE/SANS TOP 25のように脆弱性データベースに登録された情報を基にTOP 10リストを作ったので、セキュアプログラミングで当たり前の入力バリデーションは省略したということです。CWE/SANS TOP 25でも入力バリデーションが最も重要な対策の1つである、と明記しています。

上記の文章からOWASPでは入力バリデーションを根本的な対策と捉えていることが解ります。OWASPのみでなく、SANS、MITRE、CERTも同様です。入力の対策は多くの脆弱性を根本的に廃除するセキュリティ対策です。

参考:

上の参考リンクの中でも記載していますが、入力処理は必ずしも全ての脆弱性を根本的に廃除する必要はありません。入力対策ではリスクを廃除できる物は廃除、緩和できる物は緩和、何もできない物(何もバリデーションできない入力はほとんど無い)はそのままにします。安全に出力を行う責任は出力コードが持ちます。

出力の対策

出力の対策が根本的な対策になることも明らかです。ソフトウェアの誤作動の原因の1つは”悪意のある入力”または”不正な入力”を想定しない出力があるからです。出力対策の不備もソフトウェア誤作動の原因なので根本的な対策であると解ります。

セキュアプログラミングでは出力のセキュリティ対策は出力コードに責任があります。CERT Top 10 Secure Coding Practicesでは出力対策のベストプラクティスを次のように紹介しています。

7. 他のシステムに送信するデータを無害化する

コマンドシェル、リレーショナルデータベースや商用製品コンポーネントなどの複雑なシステムへの渡すデータは全て無害化する。攻撃者はこれらのコンポーネントに対してSQL、コマンドやその他のインジェクション攻撃を用い、本来利用してない機能を実行できることがある。これらは入力バリデーションの問題であるとは限らない。これは複雑なシステム機能の呼び出しがどのコンテクストで呼び出されたか入力バリデーションでは判別できないからである。これらの複雑なシステムを呼び出す側は出力コンテクストを判別できるので、データの無害化はサブシステムを呼び出す前の処理が責任を持つ

当たり前の事ですが、入力処理の時点ではデータがどのような出力に使われるか判りません。例えば、ユーザー名はデータベースにも、メール、HTML、JavaScript、XPATHクエリ、LDAPクエリ、IMAPクエリ、コマンド実行にも利用されるかも知れません。

出力のコンテクストが重要です。出力コンテクストによって、安全な出力が方法が異るからです。データベース、ブラウザなど、出力先だけでなく、出力のコンテクストが重要です6。これを理解していないとSQLインジェクション対策として「パラメーターへのインジェクションを防止するプリペアードクエリだけ使えば大丈夫」と誤解します。SQLシステムへのインジェクション攻撃を完全に防止するには、以下のような出力コンテクストを考慮した対策が必要です。

  • パラメーターの安全化(エスケープ、プリペアードクエリなどのAPI、バリデーション)
  • 識別子の安全化(エスケープ、バリデーション)
  • LIKEクエリの安全化(エスケープ、バリデーション)
  • 正規表現の安全化 (エスケープ、バリデーション)
  • XMLとXMLクエリの安全化 (エスケープ、バリデーション、APIの利用)
  • JSONデータの安全化 (エスケープ、バリデーション)
  • その他、全てのコンテクストの安全化

出力対策では出力先のコンテクスト7 8 9が非常に重要ですが、これを疎かにしているケースは少なくありません。

処理の対策

正しく処理を実行することも根本的なセキュリティ対策です。セキュリティ問題の多くはインジェクション問題ですが、データの不整合や認証/認可の不具合などインジェクション問題以外もセキュリティ問題です。

例えば、予約処理などではシリアライザブルなトランザクションを利用10しなければなりません。シリアライザブルなトランザクションを使わないと不整合が起き、セキュリティの三要素である完全性が損なわれます。

ソフトウェアはある目的を実現する為に構築されます。その目的を実現するには正しいロジック(処理)が必要で、問題の原因となっている部分を修正しなければなりません。

処理に問題があった場合も「問題の原因」となるので根本的な対策です。

結局、入力/出力/処理、全て根本的対策

入力の対策、出力の対策、処理の対策、それぞれが”原因”を廃除する根本的な対策となります。ソフトウェアセキュリティの目標は「全体としてソフトウェアの安全性を維持する」ことにあるので当然です。しかし、脆弱性の原因となっている出力や処理の対策が根本的な対策である、との誤解は少くありません。

なぜこのような誤解が生まれるのか?それはセキュリティ対策の目的の勘違いにあると考えられます。本来のITセキュリティ対策の目的は

  • ITシステムを許容可能な範囲内のリスクに管理し利用できるようにする

です。脆弱性の原因となっている出力や処理の対策が根本的な対策である、としている場合のITセキュリティ対策の目的は

  • 脆弱性の廃除である

としていると思われます。脆弱性の廃除はセキュリティ対策の1つですが、全てではなく、手段の1つにしか過ぎません。ISO 27000では一般に「セキュリティ対策」と言われている用語を「リスク対応」として、次のように定義11しています。

2.71
リスク対応
リスクを変化 (2.61)させる為のプロセス(2.54)

ノート 1
リスク対応には以下の項目を含める事ができる:

  •  リスクを発生させる活動を開始しない、または継続しないことを決断することによりリスクを回避する
  • 機会を獲得する為にリスクを選択または増加させる
  • リスクの原因を排除する
  • 発生の頻度を変える
  • 結果を変える
  • 他の組織(契約企業やリスクの資金的処理を含む 訳注:保険など)とリスクを共有し
  • 見聞のある選択によりリスクを抑える

ノート 2
否定的な結果をもたらす事象のリスク対応は、”リスク緩和策”、”リスク排除策”、”リスク防止策”、”リスク削減策”などと呼ばれる事がある
ノート 3
リスク対応は新しいリスクを生成したり、既存のリスクを変更することができる

ISO27000のリスク対応のノート2に記載されているように、「リスク排除策」(脆弱性の廃除)はセキュリティ対策の手段の1つに過ぎません。仮に廃除可能なリスクを全て廃除できたとしても、リスクは残ります。ソフトウェア開発者なら良く理解る話ですが、ライブラリやフレームワークの更新、アプリ自体の更新でいくらでも新しい脆弱性が入り込む余地があります。ソフトウェアセキュリティの課題はいわゆる攻撃可能な”脆弱性”だけではありません。否認防止の為のログシステム、データ整合性の信頼性なども重要なセキュリティ要素です。そしてシステム利用の上で最大の脅威である”利用者”から発生するリスクはソフトウェアだけでは廃除できません。

手段と目的の取り違えはよくある間違いですが、なかなか勘違いに気がつきません。目的の為の手段は目的を実現する為にも役立つからです。しかし、本来の目的を忘れて手段が目的化すると実現すべき状態を達成することが困難になります。

参考: セキュリティ対策の目的と手段 〜 根本的誤りの元 〜

セキュリティ専門家はどう考えているか?

ここで基本に戻りましょう。セキュリティ対策の評価はその効果で評価します。世界トップクラスのセキュリティ研究所などの評価は以下の通りです。

CERT Top 10 Secure Coding Practices  – ITセキュリティ研究の老舗中の老舗と言えるのがCERTです。セキュアプログラミング標準などを公開しています。セキュアプログラミング習慣、第一位は「入力をバリデーションする」(=入力の対策)

1. 入力をバリデーションする

全ての信頼できないデータソースからの入力をバリデーションする。適切な入力バリデーションは非常に多くのソフトウェア脆弱性を排除できる。ほぼ全ての外部データソースに用心が必要である。これらにはコマンドライン引数、ネットワークインターフェース、環境変数やユーザーが制御可能なファイルなどが含まれる。

CWE/SANS TOP 25 – CVEデータベースなどを管理しているMITREのプロジェクトの1つがCWEプロジェクトです。SANSはセキュリティ研究/教育の機関です。怪物的セキュリティ対策の第一位は「全ての入力の制御を確立し維持する」(=入力の対策)

怪物的なセキュリティ対策 #1

全ての入力の制御を確立し維持する
Establish and maintain control over all of your inputs.

OWASP Secure Coding Practices – Quick Reference Guide ー Webアプリケーションのセキュリティ対策をまとめたガイドなどを編集/公開している組織です。PCIDSSでもOWASPのガイドを参照するよう推奨しています。セキュアコーディング実践チェックリストの第一番目は「入力バリデーション」(=入力の対策)

セキュアコーディング実践チェックリスト

1. 入力バリデーション

  • 信頼するシステム全てが入力バリデーションを実施するよう指揮する

OWASP TOP 10(Webのセキュリティ脆弱性対策ガイド)の2004年度版では「未検証の入力」が第一位として記載されていました。以降の版からは省略されましたが、セキュアコーディングガイドでは一番目の要素として取り上げています。

ISO 27000では順位こそ付けていませんが、1つ前の版では具体的な入力バリデーション方法を記載し、実践することを要求していました。現在の版では、セキュアプログラミング/セキュアコーディングの標準やガイドが確立し普及しているので省略した、としています。OWASP TOP 10の2007年度版以降と同じような考えだと言えるでしょう。

なぜか日本のセキュリティ専門家と言われている人の中には違うことを言う方も居ますが、世界トップのセキュリティ専門家がセキュアプログラミングやセキュリティガイドで、ソフトウェアのセキュリティ対策として第一位は”入力の処理”(入力バリデーション)だとしています。

まとめ

標準セキュリティの考え方に基づいた「根本的」12なセキュリティ対策を考えてみました。目的と手段を取り違えていては、達成できる物も達成できなくなります。

  • ソフトウェアセキュリティにおいて、入力/出力/処理対策のどれが”根本的”であるかどうか、分類する事に意味はない
  • 入力/出力/処理、それぞれの対策がリスクの原因を廃除する根本的な対策となる
  • 脆弱性の廃除はセキュリティ対策の”目的”ではない。セキュリティ対策の”手段”の1つでしかない
  • 手段と目的の取り違えは、自覚が難しい場合が多い
  • ITセキュリティの目的は「ITシステム利用のリスクを許容範囲内に管理して利用する」である

参考:実は標準の方が簡単で明解 – セキュリティ対策の評価方法

目的と手段の勘違いが多く見られます。この他に信頼境界線とリスク分析に対する勘違いも多いと思います。近いうちに勘違いが多いと思われる、ソフトウェアセキュリティにおける信頼境界線の書き方とリスク分析について書きたいと思います。


  1. 実際のセキュアプログラミング標準ではもっと細かく分類しますが、大別するとこの3つになります。 
  2.  ほとんどのセキュリティ問題はインジェクション問題 – インジェクションパターンとして理解すると簡単 
  3.  ほぼ全てのインジェクション攻撃を無効化/防止する入力バリデーション 〜 ただし出力対策も必須です 〜 
  4. 多くの場合、整数型であるだけをバリデーションするだけでは不十分です。”期待する入力”の多くは整数型の全ての範囲ではなく、限定された範囲です。”範囲”をバリデーションすることも重要なセキュリティ対策です。 
  5. 整数だからと言って、完全にインジェクション攻撃のリスクがない訳ではありません。整数オーバーフローによる攻撃は整数でも可能になります。安全だ、と盲信するのではなく、残ったリスク(残存リスク)がないか常に考慮する必要があります。 
  6.  テキストインターフェース処理の基本 
  7. 正規表現をサポートするデータベースの場合は正規表現のエスケープも必須のセキュリティ対策。参考:正規表現を使ったDoS – ReDoS 
  8. XMLをサポートするデータベースの場合、XML、XPathクエリなどのエスケープやバリデーション対策が欠かせない。参考:XPathクエリ(2) 
  9. JSONをサポートするDBの場合、エスケープが欠かせない。参考:JSONのエスケープ 
  10. 不整合が起きてはならない場合、シリアライザブル 
  11.  標準と基本概念から学ぶ正しいセキュリティの基礎知識 
  12.  “根本的”かどうかという考え方は標準セキュリティには無いですが、この考え方を好意的に考えると”残存リスク”あるかどうか?と言い換えとも捉えれます。しかし、対策が”根本的”かどうか考える思考は”特定の問題を廃除したか?”という、セキュリティ対策では避けるべきブラックリスト型の思考(特定の問題を廃除したかという思考、思考停止を生みやすい思考)で考えることになり、漏れに繋がりやすくなります。プリペアードクエリだけでよしとしたSQLの出力対策の失敗が良い実例です。実際の失敗からも”根本的かどうか?”と考えることは、セキュリティ対策にとっては有害と言って構わないでしょう。”残存リスク”の有無で考えると、残ったリスクを適切に対応するとする標準セキュリティのプロセスにも合致し、リスクの見逃しが少くなります。(特定の問題にフォーカスしないので見逃しが少なくなる)標準セキュリティは多くのセキュリティ専門家によって、仕組みとして安全なITシステムを作りやすいように考えられています。下手に独自の概念や手法を取り入れない方が間違いがありません。 

投稿者: yohgaki