7PKという用語を聞いた事がある開発者も多いと思います。7PKは業界標準のソフトウェアセキュリティ分類です。まだの方はこれを機会に是非覚えてください。CERT Top 10 Secure Coding Practicesと同じく開発者全員に必修の用語と概念と言えます。何故なら、CERT Top 10 Secure Coding Practicesも7PKも知らないのならISO 27000(ISMS)、NIST SP800-171に対応するアプリケーションは作れないからです。
※ 7PKやCERTセキュアコーディング原則を知らなくても、セキュアなソフトウェアを作ることも可能かも知れません。しかし、それはかなり遠回りになるでしょう。
7PK 〜 Seven pernicious kingdoms: a taxonomy of software security errors 〜
7PKとは2005年に公開された論文です。Seven pernicious kingdomsを略して7PKと呼ばれています。10年以上前に公開された論文でCWEでも言及されているので、ソフトウェアセキュリティ専門家にとっては馴染みのある論文と言えるでしょう。
Seven pernicious kingdoms: a taxonomy of software security errors
直訳すると「7つの悪質な王国たち : ソフトウェアセキュリティエラーの分類」となります。(意訳するなら”王国”は”領域”とするのが良いと思います。理解り易く意訳すると「悪質な7つの領域: ソフトウェアセキュリティ問題の分類」あたりでしょうか)
”王国たち”(kingdoms)とは、プログラム/コードはプログラマによって専制支配された”王国”のような存在であることから”王国たち”としていると考えられます。 実際、プログラム/コードは、プログラマが望まない誤作動/不正動作を含め、プログラマが命令した通りにしか動きません。
この論文では悪質なソフトウェア問題の原因を7つに分類しています。以下がその7つの悪質なセキュリティ問題の原因です。
- Input validation and representation (入力バリデーションと表現)
- API abuse (APIの乱用)
- Security features (セキュリティ機能)
- Time and state (時間と状態)
- Errors (エラー)
- Code quality (コード品質)
- Encapsulation (カプセル化)
- Environment (環境) – これは7つの領域/王国+1の脆弱性として追加されている8つ目
これらの問題が非常に悪質なセキュリティ問題の原因である、としています。
7つにした理由は、人が容易に理解/記憶できるモノの数が7つ、プラスマイナス2であることからある程度無理矢理に7つにしたとしています。
IEEE Explorerの論文要約から、これら7つの悪質なセキュリティ問題の原因を紹介します。割と文芸的な英語表現が使われているので、解りやすいように意訳し適当に省略しています。オリジナルの要約はIEEE Explorerから、詳しくは論文を参照ください。
Input validation and representation (入力バリデーションと表現)
メタ文字、異なるエンコーディング、数値表現などは入力バリデーションと表現の問題を発生させる。開発者が単純に一切の入力バリデーション実施を忘れてしまう事も少くない。もし入力バリデーションを実施すると決めたなら、ホワイトリスト型を使いなさい、ブラックリストでなく。
過度に入力を信頼することが大きな問題を生み出す。 バッファーオーバーフロー、XSS、SQLインジェクション、キャッシュ汚染など、スクリプトキディ(攻撃用ツールを使えるだけのレベルの低い攻撃者)が大喜びするほぼ全てのレベルの低い攻撃に利用される。
訳注: フェイルファーストとゼロトラスト、入力データは3種類しかないこと、 入力バリデーションには3種類のバリデーションが在ること、を理解すると、正しく効率的な入力バリデーション実装を理解できる。一番目なので、最大の害悪は不適切/不十分な入力バリデーションにある、としていると解る。妥当な入力以外ではプログラムは正しく動作しない。妥当な入力であることを保証するバリデーションはセキュアなプログラム処理の大前提(CWE-20)である。CERT Top 10 Secure Coding Practices, CWE/SANS Top 25, OWASP Secure Coding Quick Reference Guideなどでも第一に実施すべき対策としている。
備考:
スクリプトキディ(攻撃用ツールを使えるだけのレベルの低い攻撃者)が大喜びするほぼ全てのレベルの低い攻撃に利用される
これを太字にしたのは私です。原文の記述方法から皮肉を感じとれたからです。スクリプトキディだけでなく、セキュリティ業者も大喜びするのが入力バリデーションが不適切/不十分/無いソフトウェアです。 Webサイトのセキュリティチェックを行うセキュリティ業者にとっても、入力バリデーションが無いソフトウェアほど有り難い物はありません。(=容易に問題を見つけられる)
アプリケーションでは入力バリデーションが必須ですが、ライブラリやAPIは必ずしも入力バリデーションを必要としない点には留意してください。詳しい理由は契約プログラミングを参考にしてください。IPAを除く、マトモなセキュリティガイドライン全てが入力バリデーションを第一の対策としていう理由は組み合わせ爆発にあります。最適なバリデーション構造は論理的に導き出すことが可能です。
API abuse (APIの乱用/誤用)
APIはコーラー(Caller – 呼び出し側)とコーリー(Callee – 呼び出される側)の契約である。最も多いAPIの乱用はコーラーがコーリーの契約を守らない形で起きる。例えば、もしプログラムがchroot()を呼び、後に実行されるchdir()に失敗すると、安全にアクティブなルートディレクトリを設定する契約に違反することになる。(訳注: chroot()はディレクトリを指定する文字列を引数に取る)別のAPI乱用の良い例はコーリー(呼び出されたAPI)が信頼できるDNS情報をコーラーに返す、と期待することである。この場合、コーラーはコーリーAPIが特定の動作することを期待して乱用している。本当に出来の悪い人たちは、コーラーとコーリー契約を反転して違反することまでやってしまう。例えば、SecureRandomのサブクラスを作り、(訳注: 名前が示唆する)ルールに従わずそれほどランダムでない値を返す、といった具合に。APIの乱用は非常に多く見られる。
訳注: APIの乱用/誤用をより良く理解する為には契約プログラミングが参考になる。アプリケーションとライブラリの責任の違いを理解することも重要である。「SQLインジェクション対策にはプレイスホルダ/プリペアードクエリだけ使っていればOK」とする考え方もAPIの乱用/誤用の一種と言える。プログラムの基本構造は入力処理→ロジック処理→出力処理であり、この3つの全てでセキュアな処理が行われないと十分な安全性は維持できない。
Security features (セキュリティ機能)
ソフトウェアセキュリティとはセキュリティソフトウェアではない。欠かせないセキュリティ機能として頼れるモノではあるが、全ての暗号機能は魔法のようなあなたのコードを安全にする為に役立たない。ネットワークトラフィックを保護する為にSSLを使うと決めたとしよう。しかし、開発者は簡単にセキュリティを滅茶苦茶にできる。残念ながら、これは何時でも何処でも起きている。セキュリティ機能を分解/結合させたとき、開発者は認証、アクセス制御、機密性、暗号、権限管理やCISSP試験で必要とされる全ての要素、これらの課題について考慮しなければならない。これらのモノを全て正しく実装することは難しい。
訳注: 何かのセキュリティ機能を使えばソフトウェアセキュリティが達成される、といった事はないということ。2005年当時は”SSLを使っているので安全!!”とする誤ったキャンペーンが多かった為、このような表現になったと思われる。現在なら”WAFを導入すれば安全!!”という誤解の方が例として適切と思われる。残念ながら、基礎の基礎である入力バリデーション(CWE-20)を解説せず、WAF導入を勧めているIPAの「安全なWebアプリの作り方」は安全ではない、ということになる。 参考: 4種類の信頼境界
Time and state (時間と状態)
分散コンピューティングとは時間と状態であり、一つ以上のコンポーネントと通信し、何らかの時間が必要とされる方法で状態を共有することである。時間と状態に対して悪さをすることは、この地球上で手付かずの状態で放置されてる最大の攻撃箇所である。
ほとんどのプログラマはマルチプロセス/マルチスレッドで時間と状態の厳格な管理が必要なプログラムであっても、シングルプロセス/シングルスレッドのようにコーディングしている。
訳注: シングルプロセス/シングルスレッドであっても状態の乱用による問題は、認証関連の問題をはじめ、様々なコードで頻繁に発生している。時間と状態の問題はマルチプロセス/マルチスレッドに限らない。
Errors (エラー)
ソフトウェアを壊したい? ゴミデータをプログラムに投げ付け、どんなエラーが起きるか見てみればよい。 エラーはプログラムに関する”多すぎる情報”を与えるだけでなく、在りと在らゆる不整合な状態の原因である。更に悪い事に、モダンなオブジェクト指向システムは”例外”により絶滅したgotoを再導入した、悲しいかな。
エラー処理はプログラムに於ける契約を体現するものであり、ある意味、エラーはAPIのもう一つの機能と言える。しかしながら、エラー処理はそれ自体が特別な”王国”であり、エラー処理に関連するセキュリティ的欠陥は在って当たり前である。APIの乱用と同じく、2つの方法で滅茶苦茶にできる。一つはエラー処理を全く行わない/いい加減にエラー処理すること、もう一つは多すぎる情報を与えることによって。
訳注: 原文には「放射性物質のように誰も取扱たくなくなる様にして」といった文言もあります。これには、エラー処理をしたくない/エラー処理を回避するためのサニタイズもアンチプラクティスである、といった意味も含まれていると考えられる。不正なデータ変換/除去するサニタイズは基本的にアンチプラクティスです。普通は行ってはならない。エラーと例外の取り扱いはブログにしています。
Code quality (コード品質)
セキュリティのサブセットは信頼性である。もし開発者が自分のシステムの全てのポジティブ/ネガティブなセキュリティリスクを把握/対応できるなら、セキュリティは単なる信頼性の問題である。低品質なコードは予測不可能な動作を生み、使い勝手を悪くする。攻撃者にとっては、低品質なコードはシステムに対して予測しない動作をさせる為のツールとなる。
訳注: 「もし開発者が自分のシステムの全てのポジティブ/ネガティブなセキュリティリスクを把握/対応できるなら、セキュリティは単なる信頼性の問題である」、これはインジェクション問題などの不正命令実行系、認証・認可などの権限系、環境などの設定系、人や外部サービスなどリソース系といった各種セキュリティ問題を完全に排除できたなら、セキュリティ問題として残るのは信頼性問題であることを意味している。信頼性はISO 27000で要求される主要セキュリティ要素の一つとして定義されている。
Encapsulation (カプセル化)
カプセル化とは、モノの周りに強い境界を引き、それらのモノの間にバリアを作ることである。例えば、Webブラウザであれば、JavaScriptなどによって自由にHDDにアクセスできなくさたりする事をいう。現在のソフトウェアで幾つかの最も重要な境界の一つはクラスとそれらのメソッドである。信頼モデルは非常に注意深く正確で周到な境界管理が必要である。別の言葉で表すと、俺のコード/データに手を出すな!
訳注: カプセル化が重要で、カプセル化したモノには不用意に手を出してはならないと言う事。大前提として”カプセル化”を行うがある。言うまでも無く、カプセル化は重要である。カプセル化には入力バリデーションが欠かせず、ソフトウェアセキュリティに於て最も重要なカプセル化は”アプリケーションのカプセル化”である。契約プログラミングが参考になる。セキュリティ問題をライブラリ等にカプセル化するだけ、ではマトモなセキュリティ対策にはならない。誤ったカプセル化の利用方法(≒エラー処理をライブラリ/コンポーネント任せるAPIの乱用)も重大なセキュリティ問題の原因となっている。iPhoneなどで時々に発生する壊れた文字エンコーディングによるDoS攻撃はその良い例である。
Environment (環境)
動かないと思ったら、他のマシンへの接続がダメだった、情け容赦ない世界だよね。ソフトウェアの外の世界と繋がることは重要である。”王国”(ソフトウェア/アプリケーション)とは”外の王国”から中に入ってくるモノで出来上がっていて、全ての”外の王国”から入っている来るモノは君の作るソフトウェアにとって致命的影響を与える。
訳注: 外部からの入力/外部の状態が害悪であり、 入力と状態をバリデーションしないとプログラムは絶対に正しく動作しない、というプログラミングの基礎の基礎を実施しないとならないことを指している。契約プログラミングの概念が参考になる。”外部”とは必ずしも”別のプログラム”とは限らず、プログラム内で利用しているモジュール/ライブラリ等も含む。これは”APIの乱用”が含まれていることから明らかである。CERT Top 10 Secure Coding Practicesでも”複雑なAPIは外部システムと同様に扱う”としている。
まとめ
7PKは全てのセキュリティ問題を網羅する物ではありませんが、セキュアなソフトウェアを構築する上で欠かせない重要な要素です。7PK自体は単なる論文ですが、CWEのエントリとして随分前から含まれています。
ISO 27000(ISMS)はセキュアプログラミング技術の導入を要求しています。CWEはISO 27000のいう所の”体系的にまとめられたセキュアプログラミング技術”の一つです。 ISO 27000とある程度の互換性を持っているNIST SP800-171も同様です。GDPRは、基本的にはISMSの実施を前提としており、CERTのセキュアコーディング同様、7PKの概念も必要な基礎知識だと言えるでしょう。
MITREは2018年1月のCWEの大幅更新でセキュアプログラミング/セキュアコーディング対応を強化しました。MITREはセキュアプログラミング/セキュアコーディングの基礎概念を蔑ろにしてたのではなく、当然ですがかなり前から重要視していました。このことはCWE-20を最大のセキュリティ対策としているCWE/SANS Top 25 Monster Mitigationsから判ります。
残念ながら少なくない開発者が7PKやCWE-20、セキュアコーディングの重要性や概念を誤解しています。誤解はまだよい方でそもそも知らない事も多いです。日本に於てはITセキュリティを推進すべきIPAでさえ、出鱈目なCWE解釈に基づく「安全なWebサイトの作り方」を今でも公開しています。(※ 出鱈目であったIPAの「セキュアプログラミング講座」は2016年に一度改訂され、恐らく2017年の改訂でマトモになっています)
日本のITセキュリティは10年は遅れている、と時々耳にしますが公的なITセキュリティ機関であるIPAのITセキュリティ対策ガイドラインは本当に10年は遅れています。そして、その遅れは今も広がり続けています、「安全でないWebサイトの作り方」によって。
CWE/SANS Top 25の策定にはIPAの方の名前もあり、IPAの方全てがソフトウェアセキュリティの基礎の基礎を理解していない、とは思っていませんが基礎の基礎を無視したセキュリティガイドが長年公開されています。これで良いのでしょうか、IPAは?
MITRE/CWEがセキュアコーディング/セキュアプログラミング概念対応を今になって強化 している理由
そもそもCWEは脆弱性カタログとしての意味合いが強く、”セキュリティ対策の基礎概念”をまとめるカタログとしては作られていませんでした。この辺りはCERTのセキュアコーディングなどでカバーできるはず、CWE/SANS Top 25を長年公開しているので、少なくとも入力バリデーションの重要性くらいは理解されるだろう、という想定があったと思われます。
しかし、米国政府関連でNIST SP800-171の必須化が行われるにも関わらず、セキュアコーディング/セキュアプログラミングの基礎概念でさえ理解されていない現状があり、それに対応する為に本来は不必要と思われるCWEのセキュアコーディング/セキュアプログラミング対応を強化したと思われます。
OWASP TOP 10:2017でもセキュアコーディング/セキュアプログラミング対策が強化された
MITRE/CWEを策定している人達とOWASPのガイドラインを策定している人達がかぶっているので当然と言えますが、OWASP TOP 10もセキュアコーディングの基礎の基礎対策を強化する内容に変更されました。2017年版OWASP TOP 10に対応するには、セキュアコーディングの基礎の基礎であるバリデーションを厳格に実施することが前提条件となります。
MITREと同様にOWASPもセキュアコーディング/セキュアプログラミングは個別の脆弱性対策とは別途にセキュアコーディング/セキュアプログラミングを啓蒙することで対応できる、その方が余計な誤解を生みづらい、と考えている節があります。
プログラミングの基礎の基礎が無視されている原因??
フェイルファーストやコンピュータは数値でさえ正しく取り扱えない、といった基礎知識はプログラミング学習の初期で習うはずです。にも関わらず何故、基本中の基本と言える対策がなおざりにされてしまったのか?理解できません。
最近では流石に聞かなくなりましたが、数年前まで「入力データのバリデーションはセキュリティ対策ではない/重要ではない/アプリ仕様でセキュリティではない」とする出鱈目な議論を耳にすることがありました。
様々な原因/理由があると思いますが、IPAの出鱈目な「安全なWebアプリの作り方」、「セキュアプログラミング講座」の責任は大きいかも知れません。