情報セキュリティスペシャリスト合格への軌跡(奇蹟?) その8:セキュリティ技術ー対策と実装(2)

暗号化やFWなどが、外的な悪意に対するセキュリティの確保だとすれば、内側の問題に対するセキュリティの確保も考えておかなければなりません。
要するに、内側からシステムを破壊するな、ということですが(北斗神拳みたいだ・・・)、内側からの破壊には大きく分けて二つのルートがあります。
一つは、ソフトウェア的に問題ある操作によってデータなどが破壊されてしまうケース。もう一つは、ハードウェア的な問題によって機能が損なわれるケースです。

前者の観点では、たとえば不正な文字列を混入することでサーバに本来想定していない(誤)動作を引き起こさせることがないようにしておく、ということを考えなければなりません。
ちなみに、不正な文字列が混入してしまう(あるいはされてしまう)のは、外部からの悪意あるアクセスだけではありません。むしろ内部の悪意無きアクセスに対しても有効となるようにしておく必要があるのです(つまり、間違った入力をすることによるサーバの誤動作を防ぐことができる)。
悪意がない(操作している人間はその操作に問題があるとは思っていない)ということは、実は一番の問題になります。なぜなら、そうした操作はシステムに通じている人の発想とは全く異なる発想でされることが多く、完全な盲点になりがちだからです。

いずれにしても、そのような形で問題が発生する可能性は常にあるのであり、情報セキュリティスペシャリストとしては「いかにこうした不具合の可能性を内在したままの、すなわち脆弱性を持った(リスクを持った、ではない)システムを安全に運用するか」が問われます(脆弱性をリスクにしない、ということ)。
こうした不具合のないシステムを作る、というのは実際問題現実的ではありません。だってたとえばデータベースサーバを操作するにはSQLは不可欠なのであり、SQLという実行命令をネットワーク上で実行させない、というのでは業務も滞ってしまいます。

従って、何らかの不都合なデータ(文字列など)が仮に入力されてしまったとしても、その不都合なデータを不都合でないデータに置き換える処理を想定しておかなければなりません。
この処理のことをサニタイジングと呼びます。

サニタイジングの代表が、エスケープ処理です。
ある処理体系において特別な意味を持つ文字を別の書き方で置き換えるのがエスケープ処理で、たとえばC言語やシェルスクリプトで特別な意味を持つ「”(ダブルクオーテーション”」をダブルクオーテーションとして(つまり特別な意味のある記号としてではなく)用いるには、「\”」(特別な意味を持つ文字の前にバックスラッシュ(Windows環境下なら¥)を置く)とさせます。
HTMLなら、タグを入れる<>をどうやって表すか、ですね。実際に<>を入れてソースを確認すれば、<>はそれぞれ<と>といった文字列に置き換わっていることが分かります。これは、クロスサイトスクリプティングの対策となります。

ちなみに、午前に関しては用語の意味などは丸憶えしてしまったほうが手っ取り早いかも。
午後は・・・これらに関する知識、つまりセキュアプログラミングの知識がおぼつかないなら、このジャンルの問いを選択しない、という方法で回避できます。
私はプログラミングなんてホントにCの初歩の初歩しか知らず、少しHTMLが分かる程度でしかないので、午後の問題は全てプログラミングに関するモノは選択しませんでした。
この方法は自分の苦手を(ある程度)放置できるということがメリットになりますが、反面、それ以外のジャンル(セキュリティ対策や運用など)は落とせない、というデメリットも。
どちらがいいかは人によりますが、プログラミングとかは一夜漬けはムリでしょうし、概念的な判断や俯瞰的思考ができるなら、そちらにかけるのも一つの方法だと思います(どっちにしたって午後の問題は選択式で、選択した問題以外は解いても得点になりませんが)。
午後はIもIIも選択式ですが、セキュアプログラミングに関する問題と全体の運用に関する問題とにバランスよく分かれている(らしい)ので。

閑話休題。

データベース操作言語のSQLでコレと同様の問題が発生することがあります。
悪意あるSQLを入力されることでルート権限を奪われたり、データの書き換えや消去が行われたりしてしまいます(SQLは命令文なので)。こうした攻撃をSQLインジェクションと呼びますが、SQLを実行する際、データ入力部分に悪意あるコード(この場合はSQL)を入れることで、元々のSQLにこの悪意あるSQLが追加されて実行されてしまう、という所に問題があるわけです。
(Where以下の条件付けで、検索文字列を指定する代わりに接続詞+SQLを入力することで入力された悪意あるSQLが実行されてしまう)

SQLインジェクションを回避するには、プレースホルダー(指定場所)を利用します。
つまり、検索文字列の指定など、後からユーザが指定する部分にたとえば「?」という文字をあらかじめ入れておき、この?に関しては後からユーザの指定文字列などを代入するようにします。
こうすると、?を含めて構成されたSQLは、実行こそできないモノのそのSQLの構造をあらかじめ指定することが可能となり、?の部分に仮に悪意あるSQLを入力したとしても、大本のSQLの構造に変化が生じない、というわけです。
このように、あらかじめSQLの構造を指定しておき、変数部分を?などで代用させて埋め込んでおくプレースホルダーの方法を、静的プレースホルダーと呼びます。
プレースホルダーが静的=固定されている、というわけですね。

これに対して、このプレースホルダー部分の処理をWEBアプリケーションで動的に実行するものを動的プレースホルダーと呼びます。プレースホルダーへの変数代入操作をデータベースで行うのではなくWEBアプリで行いますが、アプリは代入が行われた後にSQLの構造解析を行うため、SQLインジェクションの可能性は残ります。
要するに、使うなら静的プレースホルダーの方がセキュリティは固い、ということです。

もし何らかの制約でプレースホルダーが使用できない場合は、先に見たエスケープ処理で対応することになりますが、エスケープ処理が完璧に行えればセキュリティホールはゼロにできます。
が、それの言い回しはすなわち、エスケープ処理を完璧にすることはまず不可能だ、ということの裏返しでもあります。

システムを操作する過程で入力の不都合を発生させないようにするこれらの方法に比して、内側のセキュリティにはよりプリミティブなものも考えておかなければいけません。

何を言っているのかというと、こうやってシステム化されていけば行くほどシステム停止におけるダメージが大きくなっていくので、如何にこのダメージを少なくするのか、ということを内側のセキュリティとして考えておかなければならない、ということです。一言で言えば、システムの信頼性をどのように確保するか、ということもここで併せて考えておく必要がある、ということです。

信頼性設計の基本は、RASISです。

  • R(Reliability)・・・信頼性
    普通は平均故障間隔(MTBF)で評価します。MTBF=1/故障率で表すことができます。
  • A(Availability)・・・可用性
    普通は稼働率で評価します。使いたいときに使えるかどうか、という視点ですね。稼働率A=MTBF/MTBF+MTTRで表します。
    MTBFは故障が起こるまでの間隔=正常に動いている時間。MTTRは平均修理時間、つまり修理にかかる=止まっている時間。この二つを合計すれば単位時間になり、そのうちのきちんと動いていた時間が稼働していた時間=稼働率になるわけです。
  • S(Serviceability)・・・保守性
    平均修理時間(MTTR)で表します。直しやすさ、ということですね。MTTR=1/修理率という式で表せます。
  • I(Integrity)・・・保全性
    データが故意・過失によって破壊される可能性のことです。破壊されないようにすることはもちろんですが、破壊されても元に戻せるような仕組みを整えておくことも重要です。
  • S(Security)・・・安全性自然災害やクラッカーなどの攻撃から情報を守れる度合いです。いわゆるセキュリティですね。

ものすごくおおざっぱに考えれば、「トラブルが起こらないようにすること」と「トラブルが起こってもすぐ戻せること」の二つがポイントになるわけですが、前者は「耐障害設計」として事前に考えておく必要があります。
耐障害設計としては、

  • フォールトアヴォイダンス・・・障害(フォールト)をあらかじめ避ける(アヴォイダンス)ように、たとえば高品質なモノを導入するなど。要するに安物買いの銭失い、という考え方(後述の私的事例参照・・・orz)。導入コストが高くつくことが難点。
  • フォールトトレランス・・・障害(フォールト)の発生は不可避なので、障害によってダメージを受ける部分を限定的にすることで障害を受け入れ(トレランス)、全体としては正常な動作を確保しようという考え方。
    • フェールセーフ・・・故障の被害を最小限にとどめること。データバックアップを用意したり、サブの処理システムを準備しておくなどが該当。メインシステムからサブシステムに切り替えて処理を継続させることは特に「フェールオーバー」と言う。
    • フェールソフト・・・故障によって中核的機能が損なわれないようにすること。処理量が増えすぎたらユーザ側のシステムを落として基幹システムの処理を確保する、など。

区別がつきにくいのですが、ポケスタには「セーフ(政府)は保身に走って機能停止、ソフトはよたよたしながらも処理を継続」と覚えるようにありましたが、言い得て妙ですね(笑)

そのほかには

  • フールプルーフ・・・うっかりミス(フール)によってデータやシステムが破壊されないように予防する(プルーフ)。入力可能範囲を制限したり、オンラインヘルプを使ったりする。
  • フォールトマスキング・・・故障が発生しても(フォールト)他のシステムへはそれを隠蔽し(マスキング)、自律回復を行う。

などがあります。フェールソフトとフェールセーフの違いは覚えておいた方がいいです。

これだけやっても障害は起こりうるモノ。起こってしまった障害に対する備えは絶対に必要です。
要するに、バックアップを取れ、ということですね。もちろん、闇雲にバックアップを取ればいいわけではありません。何のデータをどの頻度でバックアップするのか(あるいはしないのか)は、きちんと計画を立てておく必要があります。

  • フルバックアップ・・・ストレージ内のあらゆるデータをバックアップ。一番簡単なバックアップでデータの漏れもありませんが、バックアップにもレストアにも時間がかかります。
  • 差分バックアップ・・・フルバックアップ以後に変更された分をバックアップするやりかた。日にちが経過するごとにバックアップの容量は増えていくことに注意。
  • 増分バックアップ・・・フルバックアップ取得後、前日との変更分だけをバックアップするやり方。バックアップの容量は前日からの変更分だけなので、基本的にほぼ定量となる。

差分、増分ともバックアップにかかる時間はフルバックアップよりも短くて済みますが、リストア時にはフルバックアップよりも時間、手順が多く架かることに注意しましょう。フルバックアップは一つのバックアップファイルをリストアすれば元通りになりますが、差分、増分はフルバックアップ以後の変更データを差分、増分ごとに一つずつリストアしなければならないからです。
用途に応じてどのバックアップ方法が好ましいかをあらかじめ考えなければなりません。

また、バックアップを何処に保管するか、という問題もあります。
元データが保存されているシステムのそばにバックアップデータが置いてあるのでは意味がありませんよね?
起こりうるリスクを考えた上で、何処にバックアップを置くか、また何に(どのメディアに)バックアップを用意するか、いつまでバックアップを保存するか、廃棄する際にはどのように処理するか、などを考えなければなりません。
特に近年はクラウドコンピューティングがもてはやされていますので、リモートバックアップやデータセンターなど絡めた問題が増えてくるのかも。

小規模システムやSOHOなどで普及しているNAS(Network Attached Storage)や、SAN(Storage Area Network)などもバックアップ(やファイル共有)の仕組みとして押さえておきましょう。

ネットワークを前提としたシステムでは、機器構成やネットワーク構成が頻繁に変更されることがあります。こうした変更は、きちんと管理台帳を作って管理することが重要です。管理されていないPCがネットワーク上につながっていると、それがセキュリティホールになるかも知れないからです。
また、ネットワークシステムを適切に監視するためにSyslogなどのログ取得システムをうまく活用することも必要です。なお、ログを取る際に絶対的に重要なのが、ログに記録される内容の時刻データ。これが狂っていると、いつ障害が発生したのかが分からなくなってしまいます。
NTPなどを使ってネットワーク上の機器の時刻を適切にそろえておくようにします。

また、ネットワークにつながることが前提になっているPCやサーバのOSには、できるだけセキュアなものを使いましょう(Trusted OS)。一般に流通している用語としてはセキュアOSがありますが、Trusted OSの機能限定版がセキュアOS、という理解で十分かと。
代表的なところではSE-Linuxがありますが、個々のOSについて問われることはまずない(はずな)ので、サポートの切れるOS(たとえば投稿時点ではWindowsXPのサポート期限切れが問題になっている)を使い続けるのは止めましょう、程度の理解で十分だと思います。

エスケープ処理などは普段Windowsを使っているだけだとあまり目にすることはないかも知れません(Linuxだとシェルスクリプトでお目にかかることが結構ある)。しかしバックアップに関する事や、フォールトアヴォイダンスに関することなどは身近な事例で考えることが可能だと思います。
たとえば私は自作PCを使っていますが、かつてメインメモリはバルク品を使っていました。しかしある時、購入したパーツで作ったシステムがどうしても途中でOSのフリーズを引き起こしてしまい、手間暇かけてありとあらゆるパーツをチェックした結果、購入した「バルクの」メインメモリが不良品だったことが判明しました。
これなんか、値段につられてバルク品を買っていたが故に発生した事例ですが、フォールトアヴォイダンスの観点から考えれば、そもそも購入品の選定の仕方が間違っているわけですね。
きちんと動作確認が取れ、保証がはっきりしている製品を導入することで、こうした不具合という無駄な手順を回避できるようにしておく、それがフォールトをアヴォイダンスするということなわけですから(笑)

セキュアなプログラムは組めなくても、その理念や発想を理解しておくことはできます(野球はできなくても審判はできる、というヤツですね)。後者をきちんと押さえておくだけで、午後の問題の運用・管理寄りにメモリが振られた問題にもずいぶんと有利に対処できると思います。
身の回りで目にすることはあまりないことが多いですが、ここはそういうものとわりきって勉強し、乗り切りましょう!

boota

いろんなモノに、いろんな意味で、ヲタ。なのかも?

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)