危険なコードを書くメカニズム

(Last Updated On: 2018/10/26)

世の中のソフトウェアには危険なコードが埋もれています。これがセキュリティ問題の原因になっています。なぜ危険なアプリケーションが書かれるのか?その仕組みを理解すると、対策が可能です。

危険性の知識と危険性の回避

情報セキュリティの話の前に一般論の危険性の知識と回避の問題を考えてみます。

知識が無い

大人は「道路に飛び出すと危険」だと常識として知っています。幼い子供は「道路に飛び出すと危険」だと知りません。車が危険だと知らないので飛び出します。

大人は「高いところから落ちると危険」だと常識として知っています。幼い子供は「高いところから落ちると危険」と知らないので、危険な段差がある場所でも十分な注意を払いません。

当たり前の事じゃないか「大人なら知っていて当然」と思うかも知れません。しかし、当然の常識でなければ対応できないです。

大雪で埋もれた車でエンジンをかけるのは非常に危険です。簡単に死にます。

大雪で福井県内では9日までに、雪に埋もれた車内で3人が死亡した。警察や消防によると、いずれも一酸化炭素(CO)中毒とみられる。日本自動車連盟(JAF)が行ったテストでは、車が雪に埋もれた状態でエンジンをかけると、車内のCO濃度は22分で検知器の上限値に達した。これは約3時間で死に至る危険値という。

https://www.fukuishimbun.co.jp/articles/-/292891

大人でも塩の致死量は30〜35gとされています。ふざけて塩の一気食いをすると簡単に死亡する可能性があります

塩化ナトリウム 3000~3500 食塩

https://ja.wikipedia.org/wiki/%E8%87%B4%E6%AD%BB%E9%87%8F

日常的に摂取されているアルコールも50cc〜140ccが致死量とされています。常識だと思いますが、急性アルコール中毒での死亡事故は後を絶ちません。中毒により危険な状態になった例は東京と大阪だけで毎年2万人程度います。

知識がないと、死亡するような重大な危険でも回避することは極めて困難になります。

知識があっても利用できない

大雪で埋もれた車でエンジンをかけると不完全燃焼が起き一酸化炭素が発生し危険である、という知識も理科の基礎知識があれば分かるはずです。一酸化炭素中毒は危険である、は一般的な教育を受けた大人の常識といって良いでしょう。

アルコールを摂取しすぎると急性アルコール中毒になる、これも大人なら常識として知っています。急性アルコール中毒になった方の大半が知っていたと思われます。

危険性があっても危険性があるモノを利用したり摂取したりすることに慣れてしまうと「まあ、大丈夫だろう」「何時ものこと」「周囲もやっていること」と解っていても危険を回避しない/できない、そういった事例は数えきれません。

「何時ものこと」「周囲もやっていること」は正常性バイアスとしてかなり強力です。急性アルコール中毒になる/させてしまう程のアルコールを摂取/摂取させるのは非合理席な行動です。「正常性バイアスによる誤謬」は人が非合理的な行動をする大きな原因の1つです。

知識はあっても利用しようと思わないと利用できません。基礎的な知識があっても使い方を知らないと利用は困難になります。知識がなければ尚更です。

知識があっても無視してしまう

危険だ、と解っていても危険性を無視してしまう事例も少くありません。正常性バイアスに似ていますが「身近な情報による誤謬」も不合理な判断をしてしまう大きな原因 です。

本文(「放射線って体に悪いの?」の「後からじわじわと影響がでる場合」)やミニ解説「被ばくによってガンで死亡するリスクについて」で解説したように、ICRP 勧告によるガンのリスクについての「公式の考え」では、

100 mSv の緩慢な被ばくで、生涯のガンによる死亡のリスクが 0.5 パーセント上乗せされる(ガンによる死亡率がもともと 25 パーセントだったとしたら、 25.5 パーセントになる)

とされている。ところが、ICRP の考えを説明するという文脈で、

100 mSv の緩慢な被ばくで、ガンの発生率が 0.5 パーセント上乗せされる(発生率がもともと 50 パーセントだったとしたら、 50.5 パーセントになる)

という記述が多くのところで見られた。 個人ブログやマスコミの報道ばかりか、文部科学省からの公式文書、学術会議の会長声明など、信頼すべきであるはずの機関からの文書にもこの記述があった。 もちろん、これは ICRP の「公式の考え」とはちがう。

http://www.gakushuin.ac.jp/~881791/housha/details/cancerRiskSupp.html

常識的に考えて、ある事象により「一定量のリスク」が増える、

  • 発生確率25% に 0.5%(一定量)のリスクが追加される

この場合、25%のリスクを発生させる事象の発生確率が25%から50%に変わっても、他の「一定量のリスク」は変わりません。

  • 発生確率50% に 0.5%(一定量)のリスクが追加される

と理解するのが論理的です。独立した事象のリスクは、当然ですが、他の事象によるリスクが変化しても変わりません。小学校の算数で習う程度の知識です。一歩引いて論理的に考えれば理解ることです。(他のリスクと連動してリスクが変化する、相関関係がある、とするには別途検証が必要です)

しかし、文部科学省からの公式文書、学術会議の会長声明など、信頼すべきであるはずの機関からの文書にもこの記述があった、のように信頼すべき/信頼できるとする情報源(よく知った権威ある身近な情報原)から誤った情報が発信されると思考停止状態になり「身近な情報を無条件に信じてしまう誤謬」(身近な情報による誤謬)が発生します。

適切な知識を持っていなくても、講師が言っていたから、上司/同僚が言っていたから、家族が言っていたから、と非論理的な説明であってもその非論理性を考える事なく不合理を受け入れる誤謬はよくあることです。基礎的な知識であっても知らなければ/覚えていなければ、簡単に誤った判断をしてしまいます

紹介した例には危険性はありませんが、投薬量などの計算でこのような間違いをすると命の危険がある場合もあります。

参考:誤謬と発生状況を解説した書籍

情報セキュリティ対策の現状

よくある危険を避けられない3つ誤謬の原因

  • 知識が無い
  • 知識があっても利用できない
  • 知識があっても無視する

は情報セキュリティ対策でもよくある問題です。

知識が無い

リスク管理の知識は「一般的な常識」ではありません。リスクの考え方、分析、設計、実装、検査方法などを普通は学校で習いません。大学の情報学科であってもリスク管理を学ぶことは一般的とは言えないと思います。(少なくとも私の年代は。プログラム実行の正しさを証明する講義がそれに最も近かった)

リスク管理の基本部分は情報セキュリティ管理と同じです。情報学科でもリスク管理/情報セキュリティ管理を学ぶ機会が十分にあるとは言い難いです。つまり、情報システムの教育を受けていてもリスク管理/情報セキュリティ管理の基礎知識でさえ習得していない状態が一般的です。

体系的リスク管理基礎知識の習得機会がないことも少なくないでしょう。反対に誤ったリスク管理の習慣や知識を習得する機会は多くあると思います。

知識があっても利用できない

「リスク管理にはまずリスク分析を行う」と知っている方は少なくないと思います。しかし、「リスク管理にはまずリスク分析を行う」を実践している方は多くないと思います。リスク分析を行っていても不十分であることも多いです。これは事例で分かります。

PS4が認識できない文字コードを受信した際に発生するとされ、PlayStation Messageアプリでそのメッセージを削除しても問題が残ってしまう

原因はPS4本体ではなくPSNのネットワーク側にあったと推測されます。

https://japanese.engadget.com/2018/10/17/ps4/

文字エンコーディングのバリデーションは基本的なリスク対策です。ですがPS4には問題がありました。このような文字エンコーディング処理の不具合はiPhoneでも度々見つかっています。

​​​​​​iPhone や Mac、Apple Watchに、特定の文字を表示するだけでアプリが落ちるバグが見つかりました。

表示しただけでクラッシュしてしまうため、メッセージやチャットなどで問題の文字を送りつけられた場合、いきなりアプリが落ちたうえに、再び起動しても即座に落ちるループに陥る危険があります。

https://japanese.engadget.com/2018/02/16/iphone-mac-2/

SonyやAppleといった大手がリスク分析を全く行っていない、とは考えられません。特にSonyの関連会社であるフェリカネットワークスではFelicaの開発に形式的検証手法を取り入れ10万行のVDMを記述し多くの問題を回避した実績もあります。形式的検証を導入(知識として所有)しています。形式的検証を知った上で未検証入力を残すとは思えません。

Sonyは組織としてリスク分析を知っている事になります。にも関わらず、未検証入力にる致命的なセキュリティ問題が起きました。全体にリスク分析/管理が適用できていない原因は「何時もの開発方法」「周囲もやっている開発方法」に正常性バイアスが働き、危険性が高いにも関わらず組織全体への導入が進んでいないと推測されます。

異常であるのに、今が正常であるとする認識してしまう正常性バイアスは強い認知バイアスです。ボトムアップで組織/集団を矯正するのはかなりの困難であると思われます。

参考:

知識があっても無視してしまう

◯◯の権威、とされる組織や人物から誤った情報が発信されると「身近な情報による誤謬」が容易に発生します。セキュリティ対策も同じです。

IPAは10年近く、コーディング基本原則の第1番目である「未検証入力を無くす(全ての入力をバリデーションする)」を誤って解説していました。入力と出力を取り違えた根本的な誤りがある解説では、ソフトウェア開発者が正しく理解できるはずがありません。

10年近くも前の日経XTECHに「現状はエンジニアリング以前」とする記事があります。現状のソフトウェアエンジニアリングの実施状況もエンジニアリング以前の状況であると評価されても仕方ない状況にあります。

ソフトウェアエンジニアリングの分野では70年代から正しく動作するソフトウェア開発を行う為の手法が研究されています。コンピューターサイエンスでは50年代、60年代からコード(アルゴリズム)の正しさを証明する研究が行われています。こういった遺産とも言える古い知識で、論理的に妥当である手法や考え方が未だに今のソフトウェア開発に活かされていません。

先の放射能によるリスク増加の認識間違いのケースと同じく、科学者が論理的に妥当な論理や解説を行っていても、より身近に存在する組織や人物が「これが正しい手法/考え方です」と不合理な説明を行うと容易に「身近な情報による誤謬」を生じさせます。これが大きな原因になっていると考えられます。

2000年代には科学的な論理に裏打ちされたセキュアコーディング導入の機運が高まりました。しかし、残念ながらセキュアコーディング原則の1から10まで広く適切に適用されている、とは全く言えないのが現状です。

笑えない現状…

脆弱な情報システムであればあるほどセキュリティ業者にとっては好都合です。基礎的/科学的な論理に基づかない情報システムは脆弱になります。

現代の情報システムは

  • モノ(物と人)
  • ネットワーク
  • ソフトウェア

の3つの要素が1つのシステムとして機能しています。3つの要素のどれか1つでも欠けていると致命的なセキュリティ問題となります。

モノとネットワークのセキュリティ対策は、様々な問題があっても、概ね基礎的/科学的な論理に沿ったセキュリティ対策が正しい対策をして認知されています。

例えば、モノとネットワークのセキュリティ対策で

  • 「出入りする物/人/データの制限/検証」
  • 「信頼境界の設計と管理」
  • 「複数の信頼境界での多層防御」

が重要ではない、などと主張する人は居ません。ゼロトラスト(≒ ホワイトリスト)とフェイルファーストフェイルセーフの概念を誤解している人もほぼ居ないでしょう。

ソフトウェアはどうでしょうか?

出入りする物/人/データの制限/検証

 ソフトウェアの場合、出入りする「データ」の制限/検証が必要です。米カーネギーメロン大学(CERT)のコンピューターサイエンティストはセキュアコーディング原則としてまとめています。

セキュアコーディング原則1は入力対策です。

  • 「入力をバリデーションする」=「信頼境界を越える全ての入力データをバリデーションする」

これを正しく実装しているWebアプリケーションはほぼありません。注意)HTMLフォーム入力データのエラーだけをチェック、では穴だらけの入力データバリデーションです。

未検証入力不確実性を増やすだけです。HTTPは”汎用”プロトコルで広い用途に使えるように設計されています。HTMLフォームの入力データ”だけ”ではクエリ文字列、HTTPヘッダー、POSTに含まれた余計なデータは未検証のまま残ります。クエリ/ヘッダー/POSTに含まれるデータにはクッキー、配列、JSON、XMLなどの構造化データもあります。これらも未検証のままであることが大半です。

セキュアコーディング原則7(IPA版では2番目の原則)は出力対策です。

  • 「全ての出力を無害化する」=「信頼境界を越える全ての出力データが出力先に対して無害であることを保証する」

残念ながらアプリケーションそもそもセキュアなソフトウェアの大前提である「入力データの妥当性」をバリデーションせずに、いくら出力対策”だけ”を頑張っても全ての出力を無害化できません。

出力対策に力を入れている開発者は多く、出力対策だけで安全性を確保しようと努力している開発者も少くありません。それでも不十分と言える状態のコードになっているアプリケーションばかりです。語り尽くされている感のあるSQLインジェクションさえ、脆弱な対策が当たり前になっています。

信頼境界の設計と管理

「出入りする物/人/データの制限/検証」は必要な箇所全てで実施する必要があります。しかし、構造もなくやみくもに制限/検証をバラバラに実施しても効果的/効率的に管理できません。

効果的/効率的に不確実性(リスク)を管理するには”構造”が必要です。その基本構造が信頼境界の構造です。

複数の信頼境界での多層防御

  • 「出入りする物/人/データの制限/検証」
  • 「信頼境界の設計と管理」

これらを効率的/効果的に実施しようとすると、守る対象 – モノ/ネットワーク/ソフトウェア/システム、の種別に関わらず自然に複数の信頼境界を設定した多層防御になります。

ソフトウェア内の多層防御の基本構造は、ソフトウェアの基本構造に合わせて作ります。

入力 → 処理 → 出力 の構造は全てのプログラム・コードに共通する基本構造です。アプリケーション/ライブラリに関わらず基本構造は同じです。それぞれに実施すべき対策はセキュアコーディングの考え方では以下のようになります。

アプリケーションの場合、処理の中は「機能」による分割(構造化)されているはずです。これにプログラムの基本構造と多層防御を適用すると以下のようになります。

単純に多層防御が不十分、であるならまだ良いのですが「フェイルセーフ対策」を「最高のセキュリティ対策」と勘違いしているケースも少くありません。フェイルセーフは万が一の対策なので、最高の対策でも頼っても良い対策でもありません。

悪気はないのだろうが…

2000年代にはコンピューターサイエンティストにより考案された科学的なセキュアコーディングが提唱され、導入する機運が高まりました。しかし、セキュリティ業者を含むソフトウェア開発関係者によりアンチセキュアコーディングと言える対策が啓蒙されました。セキュリティ業者によるセキュリティ業者の為のセキュリティ対策が行われている!?のが多かれ少なかれ現状です。

セキュリティ標準の考え方では、セキュリティ対策(≒リスク対策)はリスクを変化されるモノ全てです。

個別に「セキュリティ対策」としてリスク削減効果があっても、非論理的/非科学的な考え方や構造では、何時まで経っても脆弱な構造/コードは無くなりません。

  • ブラックリスト対策もホワイトリスト対策と変わらない
  • 入力バリデーションはセキュリティ対策ではない、重要ではない
  • 信頼境界線は意味がない、意味があっても重要ではない
  • 文字エンコーディングを正しく処理する責任はライブラリにある
  • 入力対策は重要でなく、出力対策こそが最重要かつ完全な対策である
  • 出力対策だけで十分な対策が可能である  
  • 構造など無くてもセキュリティ問題は単なるバグとして修正すればよい 
  • リスク分析など必要ない、分っている脆弱性に対応するだけでよい
  • フェイルセーフ対策だけで十分な対策になる(できるだけ遅く対策する)

こういった意見に悪気はないのでしょうが、全て脆弱なモノを作ってしまう脆弱な考え方です。

セキュリティの概念が根本的な部分で間違っていて、基本的な部分から脆弱なモノを作ってしまう考え方/方法論を開発者に啓蒙し、効果が低いブラックリスト型のセキュリティ対策をサービスとして提供する。悪気が無くてもマッチポンプによるビジネスになっています。

基本を見誤らないために

国際情報セキュリティ標準のISO 27000に適合した概念を基本とします。国際情報セキュリティ標準に準拠しないシステムで問題が起きた場合、開発者の責任が大きく問われるリスクがあります。

情報システムセキュリティ対策の目的は

  • 情報システムを許容可能なリスクの範囲内で利用可能にする

です。

この目的を達成する為にリスク分析が必要です。情報システムのリスク分析の目的は

  • 情報システムが正しく動作することを(可能な限り)確実にする

です。

これらの目的を達成するには論理的/科学的な基礎的概念/手法が必要です。色々ありますが、現在の情報システムセキュリティ対策の現状を考慮するとポイントは以下のようなリストになると思います。

  • フェイルファースト – 失敗するモノはできる限り早く失敗させる
  • ゼロトラスト – 検証なしに何も信頼しない。信頼は検証の範囲内
  • ホワイトリスト型の思考/セキュリティで設計/実装する
  • 分割と統治(Divide and Conquer)で適切なセキュリティ構造を作る
  • ベストプラクティスのリスク分析とリスク対応を行う(ISOに従ったリスク管理)
  • 簡易でも構わないので論理検証を行う(p ⇒ q、q ⇒ p、前提条件)
  • セキュアコーディングの基本原則を実践する
  • 契約プログラミング/契約による設計を理解する(できれば実践)
  • 形式的検証の論理と方法論を理解する(できれば実践)
  • アプリケーション(専用)とライブラリ(汎用)の責任の違いを理解する
  • 目的と手段を取り違えない

目的と手段を取り違えない、は最後に挙げましたがとても重要です。不合理なセキュリティ対策を「最適のセキュリティ対策」と勘違いしてしまう理由は幾つもありますが、目的と手段の取り違えも大きな原因です。

例えば、「プリペアードクエリ/プレイスホルダを使えば万全!」とする勘違いは、単なるSQLインジェクション対策の手段に過ぎないにも関わらず「プリペアードクエリ/プレイスホルダを使う」が目的化した為に、穴だらけの対策(手段)にも関わらず「目的は達成できた」だから「万全!」とおかしな結論になってしまいます。

本来の目的、

  • 情報システムを許容可能なリスクの範囲内で利用可能にする
  • 情報システムが正しく動作することを(可能な限り)確実にする

を達成していないにも関わらず。。

情報セキュリティ対策に対する誤謬は日本に限った事ではなく、全世界に広がっていると言えます。公開されているOSSのWebアプリケーションを見れば分かります。これが正常性バイアスや身近な情報による誤謬の解消を困難にしていると思われます。

参考:

Facebook Comments
Pocket