$ :(){ :|:& };:

$ :(){ :|:& };:

なめこうどん

seccamp' 16 の応募用紙を晒す

今年もセキュリティ・キャンプの応募が始まったらしい

www.ipa.go.jp

懐かしい

応募用紙の公開については「課題の内容も異なるしあまり意味のあるものではないのではないか」という意見も少なからず存在するようだが

少なくとも自分が当時応募用紙を書いた時は色々な方が公開されていた過去の応募用紙からその雰囲気だったり内容の書き方だったりを参考にさせていただいた記憶もあり、実は受かった直後からあげようとしてずっとはてブの下書きに入ってたやつだったので出してみた。

あとは当時の原文ママで貼り付けただけなので怪文書です。(なんかところどころ間違ってる) 1年経ってある程度は成長したのかとポジティブに捉えていきたい。間違え探しだと思ってご笑納ください(?)

思ったこと

あくまで主観的な感想です

  • 技術力の優劣・知識の正確性や厳密性というよりは、熱意や やる気・どれだけ手を動かしたか/努力したか、を評価される

これは他の卒業生の方が口を揃えて仰っていることだが全面的に同意することである。

その上で意味不明な単語の羅列が出現してもとりあえずggってみるなり、数十行のアセンブリが貼っ付けられて「これから何か感じることを自由に書いてね」みたいなことを言われてもとりあえず何かしら手を動かしてみるなり、そして重要なのはそういった過程をそのまま応募用紙に記述することが大事かなぁと。 (あとこれには私のように知ったかぶりして微妙に変なことを書いてしまうという点でもちゃんと調べることは重要だという反省も含んでいる)

  • 躊躇してないで早めに取りかかったほうがいい

意外と必須問題のポエム制作に時間がかかった記憶がある。せっかく途中まで書いたのに...ということが起きないためにも

これは多分自分の性格の問題なので多くの方は問題ないと思うのだが、 ギリギリまで手を付けなかった結果、結局定期考査1日目が終わった夕方に、勉強をする友人に窘められながら締め切り10分前に提出をする羽目になり間に合うかどうかかなりヒヤヒヤだった上、いくつかの課題の回答がかなり雑になってしまった。 早め早めに課題に取りかかるということは別にこれに限ったことじゃないだろというツッコミが来そうだが一応書いておきます。

ちなみに応募する際の入力フォームですが(少なくとも去年まではそうでしたが)

60分程度でセッションが切断され、入力内容が無効となります。

ので頑張って書いたデータが消失する可能性が無きにしもあらずなのでご注意を


以下本編です

先程も述べましたが、少なくとも技術的な内容に関して間違っている部分があるのを確認しているので 内容の正誤についての責任は負えません 宜しくお願い致します。

応募用紙

問題一覧:

https://www.ipa.go.jp/files/000053055.pdf

必須問題

q1

今まで作ったもの・やったこと等自慢のコーナーでした。あまりにも長かったのと、他愛のないものがグダグダと書かれて居るだけだったので省略

q2

q2-1

あなたが経験した中で印象に残っている技術的な壁はなんでしょうか?

JavaScriptでのオブジェクト指向プログラミング手法

無論ながらJavaScriptにクラスという概念はないが、本当にオブジェクト指向プログラミングは可能なのかということ。 Webサイト等では可能だとの記述は散見されるが、それならデータ隠蔽や継承はどのように行われているのかということ。

q2-2

その壁を乗り越えるために取った解決法を具体的に教えてください。

8割は書籍を読むことで解決した、以下その書籍のリストである。

あとは "ひたすら書いてみること" である。

壁に対する答えを非常に簡単に述べると

そもそもオブジェクト指向の本質的な部分は、メッセージングとカプセル化にあり、この要件を満たす手法として「オブジェクト指向プログラミング」がある。 ゆえに Class = オブジェクト指向ではなく、実現手段にはいくつかの手段がある。 その点、JavaScriptは、プロトタイプベースのオブジェクト指向であり、クロージャーとプロトタイプチェインをうまく用いる形でオブジェクト指向プログラミングは可能である。 その中にもモジュールパターン系統とコンストラクタパターン等他にも複数のイディオムがあるが、本質的に実現していることは同じである。各々に細かな振る舞いの違いがあるため用途によってうまく使い分けを見極める。

また、もしJavaScriptでクラスベースのオブジェクト指向プログラミングをしたいのならば、TypeScrpt等のaltJSを用いると可能である。 大規模プロジェクトで生のJS書くことはめったになくこれらのaltJSを用いることが多い。

あとは、JavaScriptの次の規格であるECMAScript 2015(ES6)では、Class記法が導入される予定である(やはり内部ではプロトタイプベースのものとして処理されている) 現段階ではまだブラウザによって実装の程度がまちまちなため、ES6の記法でコードを書くにはBabel(旧6to5)等でのトランスパイルが必要になる。

無論、オブジェクト指向プログラミングに拘る理由もなく、関数型プログラミングという選択肢もなくはない。 ただ、これも生のJSでやろうとするとかなり中途半端なことになってしまうと思われる。特に、Array.prototype.reduce()のはとても関数型とは言いがたい実装になっていたりする。これも、PureScript等のaltJSに頼るしかない。

これは余談であるが、altJSの中には他の言語をJSに変換するものも多くあり、ClojureScript (Clojure => JavaScript)、ghcjs(Haskell => JavaScript)等はたまに書いてる人を目撃することもある。 他のaltJSはこちらを参照していただきたい。(https://github.com/jashkenas/coffeescript/wiki/list-of-languages-that-compile-to-js)

かつ、良くなかった点は書籍を見て考え方を理解した私はそれで満足してしまったことだ。

書籍を眺めて、ほうほう、こういうことかと理解したつもりになっていても、それは所詮机上の空論である。 私は、完璧に理解してからでしかコードを書きたくなかったし、かと言って写経もあまり好きではない人間だったが、それが習得を完全に遅らせていたと今ならわかる。 未だにどうしても完璧なコードを書きたいきらいがあるが、とりあえずなんでもいいから実践することで本質を理解し自分のものにしていくということも、このことを通して重要なことだと感じた。

q2-3

その壁を今経験しているであろう初心者にアドバイスをするとしたら、あなたはどんなアドバイスをしますか?

JavaScriptを理解する上でO'REILLYのサイ本を読むことは欠かせない。他の言語とは少し違うパラダイムも多いのでまずはその言語仕様をある程度理解する必要がある。その上で、その特性を活かしたイディオムを理解するほうが良いと考える。 ただ、オブジェクト指向に関して言えば、今からならネット上にある古き慣習よりも、Babel等のトランスパイラを用いてES6のclass記法を使う方が遥かに無難である。また、現在の書籍はES5以前のものがほとんどだが、ネット上にはES6の記事もかなり出ている上、他にもES6の方が優れている部分が多いので(継承のextends、ブロックスコープのconstとletやアロー演算子、デフォルト引数など)できればES6の習得が望ましい。

また、パラダイムや概念を理解することももちろん重要ではあるが、写経でも良いのでとりあえず書いてみることが良いと思う。実際に手を動かすことで得るものも多い。

q3

q3-1

あなたが今年のセキュリティ・キャンプで受講したいと思っている講義は何ですか?(複数可)また、そこで、どのようなことを学びたいですか?なぜそれを学びたいのですか?

受講したいと思うものが多すぎるため、最も興味のある講座を挙げさせていただくと、 6-Aの次世代プラットフォームのセキュリティモデル考察*1 である。

近年のフロントエンドの動向は凄まじく速く、新しい技術が本当に次々と生まれ、1ヶ月前まで人気を博していたライブラリがオワコン(コンテンツの寿命が終わった、つまり使い物にならなくなった。)と呼ばれ消えていくサイクルを高速に繰り返している。 しかし、その中で相対的にセキュリティは確実に疎かになっているように私も強く感じる。 特に最近はフロントエンドのバックエンドに対する相対的な重みは増す一方であるにもかかわらず、その発展速度からセキュアなコーディングをする手法は体系的にまとめらることがない現状である。さらにサードパーティ的なプラグインを使うことは開発においてほぼ必須であるため、更に状況は悪いように思える。

その上で、自分もOSSや自分のプロジェクトでこういったことに関わる身として知っておかなければならないと考えるから、ということが興味の理由である。

q3-2

あなたがセキュリティ・キャンプでやりたいことは何ですか?身につけたいものは何ですか?(複数可)自由に答えてください。

私は今まで書籍やネット等でほぼ独学的にセキュリティに関する勉強をしてきた。 その中で、先日行われた日本情報オリンピック(JOI)の予選でCTFの日本チームで活躍している方と話す機会があった。 結果は自明なのが、自分の知識の体系性のなさ、厚みのなさを本当に強く実感した。 その上で、現場で活躍されているプロの方々から直々に学べるというセキュリティ・キャンプは心から参加したいものである。

私はセキュリティ・キャンプで体系的な知識を得ること、そしてその知識をただ得るだけでなく活かす・貢献する方法を考えることが目標である。

また先日大きな衝撃を受けたのはNHKで放映されているプロフェッショナル 仕事の流儀での名和 利男さんの特集である。 サイバーセキュリティに関する第一人者の方の特集ということで、テレビはいつもほとんど見ないのだが何気なくで視聴した。 名和さんのサイバーセキュリティという職に対する極めてストイックな姿勢にも感動を覚えたが、何より背筋が凍るような衝動を感じたのは現在のサイバー犯罪の実情だった。 これだけ日本の中枢機関が体外的な脅威に晒されている状態にあることをなぜ知らなかったのかと強く感じた、ということも理由の一つに挙げられる

選択問題

q3

RAMは主記憶装置、HDDやSSDなどは補助記憶装置と呼ばれます。一般にCPUは主記憶装置上のプログラムしか実行できません。ではなぜ、私たちは普段から補助記憶装置に書き込んだプログラムを実行できているのでしょうか?パソコンの電源を入れてからのストーリーを考えてみてください。

設問のとおり、通常のコンピューターはメインメモリ上のプログラムしか実行することができない仕組みになっている。しかし、メインメモリは揮発性である上容量も比較的小さいため、補助記憶装置にプログラムを書き込んで置くのである。 そして、補助記憶装置に書き込んであるプログラムは適宜プログラムローダーによってメインメモリに書きだされ、実行される仕組みになっている

しかし、この働きを助けるプログラムローダー自身も無論プログラムでメインメモリ上にあるはずである。しかし、電源を入れた直後に揮発性のメインメモリ上には何もないはずである。さらに言えばOSも補助記憶装置に保存しておくことが一般的であり、OS自身も存在しないはずである。

これを解決しているのがブートローダーである。

まず1次ブートローダー(これをブートローダという呼び方をしない場合もある)は不揮発性のROM内に保存されていることが多い。コンピューターの電源を入れると、CPUは外部からの指示なしにこの領域にあるプログラムである1次ブートローダーを実行するように元々設計されている。この流れをPower On Slef Test(POST)と呼ぶ。 一般的な1次ブートローダーには次のようなものある。

そして呼びだされた1次ブートローダーはブートできる各種デバイスから最も優先順位の高いもののブートセクタ(パーティッションのある記憶媒体ならMBR)から2次ブートローダー(カーネルローダーとも)を読み込む。これは、補助記憶装置から段階的にOSをメインメモリに読み込んでいき、最後にOSを実行する仕組みになっている。 2次ブートローダーには次のようなものがある

これで、晴れてプログラムローダーも読み込まれ私達は補助記憶装置に書き込んだプログラムを実行することができるのである。

q5

PCなどに搭載されているOSは「汎用OS」と呼ばれますが、それに対して、家電やAV機器などの「組込みシステム」に搭載されているOSは「組込みOS」と呼ばれます。組込みOSと汎用OSの違い、「OSが無い」や「ベアメタル」という環境、そもそもOSとは何なのか?など、あなた自身はどう考えているのかを、あなた自身の言葉で自由に説明してください。(「正しい答え」を聞いているわけではありません。あなた自身の考えを教えてください)

先に結論を言ってしまうと、OSに関して共通して言えることは、計算機上の重要資源であるCPU,Memory,I/Oを抽象化、管理するものである。しかし、OSの用途や目的によっては資源の管理に対する関心やアプローチ、程度が違ったり、またこの他に別の機能を追加する形になっていたりするのである。 それを以下OSを幾つかに分けて論じていきたい。

  • 汎用OS

汎用OSとは、Windows,Mac OS,Linuxなど、その名の通り汎用的な利用を想定したOSのことである。 一般的に「OS」という言葉を使うとき汎用OSを指すことが多いように感じる。

これらの特徴は不特定多数の人間による応用アプリケーションを通しての操作を期待している、ということである。 仮に、先述したOSの基本的な機能だけを有したコンピューターがあっても、現代で汎用的に使ってもらうことはまずありえない。 現代の汎用OSはこれらの機能の上に、ファイラ等のシステム・アプリケーションをGUIとして提供しているのである。 そしてこの上に任意のアプリケーションを動かすことができる仕組みになっているのである。

このように、カーネルとシステムを機能を合わせたものを「汎用OS」と呼ぶことが多いように感じる。

そして、この「汎用的な利用に対応しなければならない」ことが汎用OSの特徴を大きく影響している。

まず、主役である応用アプリケーションを任意のデバイスで動かすための、抽象化した共通API(若しくはABI)が必須である。 資源の保護や抽象化も必須である。 CPUやメモリを不正に獲得するプログラムがあったとしても適切に資源を配分していく必要がある。このためにCPUに関していえばTSSのような機能は欠かせない。 また、メモリで言えアプリケーション同士でメモリ資源が衝突を起こさないように仮想メモリの機能も必要である。

  • 組み込みOS(専用OS)

組み込みOS不特定多数の利用を心配しなくてよく、 かつ、何をするかの用途も明確に決まっており、その用途に必要なもののみを搭載しそれらのみを特化させた機能を持っているということが最大の特徴(汎用OSは、各ユーザーが自分好みのことを行うために多くの機能が搭載されているわけであり、そういったものはいらない訳である。)

TSSによるCPU資源の配分機能、仮想記憶方式(ページングやセグメント方式等)でのメモリ保護ははっきりいてそこまで重要ではない場合が多いと考える。 CPUやメモリ等を無限に食い尽くすようなプログラムはそもそも動かさないだろうし、万一おきたとしてもその対策は最小限でいいはずである。 また共通API(ABI)も必要なのか。他者が利用するならあれば便利だろうが、汎用OSのように綿密に定義する必要はないし絶対に必要な条件ではないだろう。

むしろ、制御プログラムをマルチタスクで動作させ少ないハードウェア資源で効率的に動作しコストを削減するといったことに関心があるように感じる。 例えば、組み込みOSはRTOSの特徴を持つ場合が多い。主要な機能である資源管理において、時間資源の優先度に基づく配分と実行時間の予測可能性を提供することに特化している。汎用OSに比べてリアルタイム性を重視しているということだ。

逆にその他に関しては汎用OSに比べて遥かに簡素な機能でOSの基本要件であるCPU、メモリ、I/Oの管理をしているわけだ。

  • 一部の組み込みOS

一部の組み込みシステムではWindows Embedded等が搭載されていることもある。これらのOSはあくまで「組み込みOS」ではあるが、不特定多数の多岐に渡る使われ方を想定しているため、インターフェースは抽象化されている必要である。

だが、「最終的な」用途は不特定多数からの利用ではないため、資源管理に対する関心は組み込みOSに近い部分も多い。

  • その他

また、独自ハードウェアなど、そもそもこういったOSの機能すらも必要としない場合もあるだろう。その場合はそれで十分なのである。プログラムで各デバイスを直接指示すればいいわけであり、OSはコンピューターを動かすための必要条件ではない。

また、最近ではベアメタル呼ばれるものがある。 これには、2つの意味があり、1つは上記のようなOSがないコンピューターのことである。 また、コンピューターの仮想化の分野でもベアメタルという言葉が使われる分野がある。 ホスト型の仮想環境は、ホストOS上に仮想化ソフトウェアを起動させ、更にその上でゲストOSを実行する形になる。ゲストOSからハードウェアにアクセスするためにはホストOSを経由しなければならないためオーバーヘッドが生じるが、ハイパーバイザー型のベアメタル呼ばれる仮想環境は、ホストOSを必要としないため、ゲストOSがハードウェアを直接制御できる形式になり速度低下を抑える事ができるのである。 コンピューターの資源を管理するための機能をもつものが2つあっても非効率なだけであるのは明らかである。ただ、ABIは抽象化する必要があるためハイパーバーザーと呼ばれるものがユーザー・アプリケーションとホストOSの間を仲介する。

q6

IDとパスワードを入力してユーザの認証を行うWebアプリがあります。あなたがこのアプリに対してセキュリティテストを行う場合、まず、どのようなテストをしますか? なぜそのテストを選択したのか、その背景や技術的根拠と共に記載してください。アプリの内部で使われている技術やシステム構成に、前提を置いても構いません。

以下の脆弱性は特にフォーム等からユーザーの入力を求める際に主に発生するものである

  • SQLインジェクションの可否 FORM等で入力されたデータをエスケープせずにそのままSQLのクエリの一部として渡している時等に、意図しないSQL文を発行させデータベースを不正操作する脆弱性

    以下にその非常に簡単な例を示す

    PHPにおいて $email = $_POST['email']; $password = $_POST['password'];

    とPOSTデータを受け取り

    $sqlreq = "SELECT * FROM users WHERE email = '$email' AND password = '$password'";

    SQLリクエストを発行させたとする。

    このとき、あるユーザー名に対して、passwordに例えば ' OR 1=1-- と指定すると クエリ全体は真を返してしまう。

    これらに対してサニタイジングやバインドバインドメカニズムが適用されているか。

  • XSSの可否 フォームの値をエスケープなしでHTML中に出力したとき、もし、フォームの値に次のパターンのような文字列を指定した時、任意のJavaScriptの実行できる脆弱性

    主なパターンは以下のとおり

    • シングルクォートを使用した場合'><script>alert('hogehoge')</script>
    • ダブルクォートを使用した場合"><script>alert("hogehoge")</script>
    • imgタグのsrc属性にJavaScriptを使った場合"><img src="javascript:alert('hogehoge')">
    • IE限定でスタイルシートの柔軟性によるXSSが生じる場合" style="left:expression( alert('test') )"
    • JavaScriptに入力データが動的に埋め込まれている場合'+alert('hogehoge')+'
    • XMLHttpRequest(XHR)によってJSONをやりとりしている場合

    これらに対して正しく入力チェックやサニタイジングが行われているか。 また特にXMLHttpRequest(XHR)によってJSONをやりとりしている場合はレスポンスヘッダにX-Content-Type-Options: nosniffをつけているか、XHRからのリクエストのみに対応するようにしているかどうか

    またサニタイジングも独自のものではなく信頼性のあるもの(PHPであればhtmlspecialchars)等を利用しているかどうか

以下の脆弱性は特にID、パスワードを扱うことから発生するものである

  • CSRFの可否 悪意のあるWebサーバーが、訪れたユーザーの外部Webアプリの認証データや識別データを利用しそのWebアプリに対してユーザーの意図しない不正な操作を行うこと つまり、Webアプリ側がなんらかの値(セッションやページトークンで)認証することで、外部から誘導されたの不正なHTTPリクエストを拒否しているかどうか。

    • 認証やセッション管理の弱点の有無
      • Session Hijack(セッションハイジャック)の可否 セッションの生成に問題があるとき、推測または総当りで有効なセッションを奪取
      • Session Replay セッションの有効期限の指定がなかったり長過ぎたりした場合、漏洩時(例えばXSSや盗聴)にそのセッションIDを利用される。
      • Session Fixation ログイン前と後でセッションIDが変化しない場合

      これらの特徴があるかどうか。またHTTPSのCoockieにはSecure属性が指定されているかどうか

    • HTTPヘッダインジェクションの有無 HTTPヘッダにおける特殊文字である改行コードを悪用し、本来通信内容に含まれないヘッダを挿入する。 例えばSet-coockie属性を挿入し任意のCoockieを指定しSession Hijackに繋がる
  • 機密情報のhiddenでのhtmlへの埋め込みの有無 ユーザー登録などの際の確認画面にて、 セッション変数やハッシュを利用せずIDやパスワード等をそのまま表示するとユーザー側にテンポラリファイルととして機密情報が残ってしまうことがあるため。

  • 暗号方式の有無 脆弱性の見つかった暗号方式や通信を用いてるかどうか。

以下の脆弱性は一般的なWebアプリに共通して当てはまるもののうち、特に留意する必要のあるもの

  • OSコマンドインジェクションの可否 ユーザーから入力を受け取るとき、

    • Perlのexec(),system,...
    • PHPのexec(),passthru(),proc_open(),shell_exec(),system()
    • Pythonのos.system(),os.popen()
    • Rubyのexec(),system(),`` 等にエスケープせずに文字列を渡してしまう場合、文字列にシェル文字を含むことによって任意のシェルコマンドを実行させる脆弱性。 シェル文字とは、シェルにおいて特殊な意味を持つ* ? {} [] <> () ~ & | \ $ ; ' \ " \n \t ` スペース 等の文字である。

    これらに対して、正しくサニタイズされているか。 またサニタイジングも独自のものではなく信頼性のあるもの(PHPであればescapeshellarg)等を利用しているかどうか

  • エラー処理 サーバー側でのエラーは内部のOSやフレームワークの情報につながり、攻撃への手がかりになることがある。データベース(もしくはデータベースドライバ)が返すSQL関係のエラーメッセージも同様である。 これらに対して、エラーハンドリングが正しく行われているかどうか。

  • 脆弱性の見つかったソフトウェアやプラグイン等、また更新されていないWebサーバーソフトウェア(Apache等)や言語の利用の有無

  • Forceful Browsing (強制的ブラウズ) 作業用フォルダなどの意図しない消去忘れ(./git等)

  • Path Traversalの有無 Webブラウザからはドキュメントルートより上にはアクセスできないが、Webアプリケーションは通常どこでもアクセスできることを利用し、例えばWebアプリケーションがクエリからファイルを読み出すような仕様のとき、それに../../../../etc/passwordのようなパラメーターを投げることでファイルに不正にアクセスできる可能性がある。

  • クライアント側のコメント HTMLやJavaScriptのコメントからサーバーの仕様を推測できるようなコメントがあるかどうか。

このような項目全てを手動で行うことは非常に手間がかかるため、実際のテストは脆弱性検出ツールを用いることは多いと思われる。

主な、Webアプリケーションに対する脆弱性検出ツールは次の通り

  • OWASP ZAP
  • Paros
  • Ratproxy 
  • Metasploit(実際にexploitを打ってみて脆弱性の挙動の確認等)

他にもツールは多く存在する。 ただ、自動ツールでは、複雑な手順だったり、特殊な攻撃パターンである脆弱性は検知できない場合もあるので、手動での検査と一長一短の関係にあると考える。

q11

2015 年に発行された CVE の内、あなたが興味を持った”サーバに存在した”脆弱性について1つ提示してください。その脆弱性を悪用した攻撃を検知する方法について詳細に記述してください。また、興味を持った理由を記述してください。 CVE番号:CVE-2015-◯◯◯◯

CVE-2016-3714 - Insufficient shell characters filtering leads to(potentially remote) code execution (シェル文字列の不十分なフィルタリングによる(潜在的なリモート)コード実行の脆弱性) http://www.imagemagick.org/discourse-server/viewtopic.php?f=4&t=29588 https://www.cve.mitre.org/cgi-bin/cvename.cgi?name=2016-3714

拡張子「svg」「mvg」ファイルのアップロードにより、サーバ上でのコマンドシェルの実行(OSコマンドインジェクション)が遠隔で可能となる 例えば、ウェブサーバーにアップロードされた画像ファイルがImageMagickを用いて自動処理されている場合などが想定される。

  • 脆弱性の原理

    ImageMagick ではdelegateと呼ばれる外部ライブラリによるファイルの処理が可能であり、入力ファイル名や出力ファイル名など実際のパラメータの値と、設定ファイル delegates.xml で指定されたコマンド文字列によって実行あされる。既定の delegate のコマンドの1つが、以下の HTTPS要求の処理に利用されている。

    <delegate decode=”https” command=””curl” -s -k -o “%o” “https:%M””/>

    ImageMagickはcommandの部分のコマンドを実行する。%Mには入力ファイル名が渡される。しかし%Mを置換する際にshellの特殊文字エスケープを実施していないので、 例えば

    convert 'https://pbs.twimg.com/profile_images/552044402504253441/FhMNjVRe.png"|ls "-l' taiyoslime.png を実行すると

    "curl" -s -k -o "taiyoslime.png" "https://pbs.twimg.com/profile_images/552044402504253441/FhMNjVRe.png"|ls "-l" が実行され、lsも実行されることとなる。

    そして、ImageMagickはこの処理を画像ファイルの中に隠すことができる。

    ImageMagickにはSVGとMVG(ImageMagick独自画像フォーマット)のcoderがあり、これらは外部のURLやファイルを参照できる。 例えば以下のMVGファイルは外部URL https://hogehoge.com/hoge を含む。

    push graphic-context viewbox 0 0 1024 720 fill 'url(https://hogehoge.com/hoge)' pop graphic-context

    この外部URL参照に対してもdelegateが実行される。この例ではHTTPS formatだとみなされ、HTTPSdelegate commandが実行され、任意のプロセスが起動出来てしまう

    さらに、ImageMagickはそのファイルがどのフォーマットのファイルかについて

    • マジックバイト
    • format: filename形式のprefix
    • 拡張子

    の優先順位でチェックする。SVGやMVGはマジックバイトがチェックされるので、拡張子でpngなどを指定していたとしても、中身がSVG/MVGならばSVG/MVGと解釈されてしまう。

    そのため、MVGファイルをアップロードしconvertでファイルを処理しようとするとMVGのcoderが実行され、URLを参照している部分でコードを実行可能ということになる。

    今回の脆弱性の根本的原因は、delegateの機能で外部コマンドを呼び出す時にsystem関数を利用していたが、shellの特殊文字エスケープを実施していなかったことにあると考える。 また、他に発見された以下のImageMagick脆弱性についてだが、すべてこれに起因するものになっている。

    • CVE-2016-3715: ephemeral:/ プロトコルを利用した遠隔からのファイルの削除
    • CVE-2016-3716: msl:/擬似プロトコルを利用した遠隔からのファイルの移動
    • CVE-2016-3717: label:@プロトコルを利用した遠隔からのファイル内容の閲覧
    • CVE-2016-3718: SSRF(Server Side Request Forgery)

    これら含めた全てのPoCが公開済みである。(https://github.com/ImageTragick/PoCs) metasploitでもこの脆弱性へのexploitに既に対応している(https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/unix/fileformat/imagemagick_delegate.rb

  • 攻撃を検知する方法 OSコマンドインジェクション一般に言えることだが、上の脆弱性全てに言えることはconvertの引数にshell文字* ? {} [] <> () ~ & | \ $ ; ' " \n \t スペース が含まれているかどうかに尽きる。 もしくは、サーバーのlogに、自分が実行した覚えのないコマンドが実行されいているかどうかで攻撃されたかどうかの検出可能はである。

  • 対策

    • 引数のシェル文字の無効化・サニタイズ
    • policy.xmlへのcoderの指定を追加する
    • 最新版7.0.1がこれらの脆弱性の修正版としてリリースされたが、一部の脆弱性が依然として解決されていないため利用は推奨されない。
  • 影響範囲

    CERT/CCによれば主要ディストリビューションの多くが影響を受ける。

    ImageMagickプラグインとして利用している主なアプリケーションとしては

    等がある。

    更に、C,C++,Go,Java,Python,Ruby,PHP,Perl 等のAPIを提供している(http://www.imagemagick.org/script/api.php)ため、それらを使用しているプログラムも影響される

  • 興味を持った理由

    実は、共通問題1で回答したTwitterBotのサーバーサイドのプログラムに、画像処理の機能としてnode.jsのnode-imagemagickモジュールを利用していたのである。 日頃どこかで脆弱性が見つかったというニュースを耳にしても、自分の今使っている無数の「今のところ安全と言われている」ソフトウェアを眺めながらどこか遠い存在のような気がしていたし、ましてやImageMagickで言えばサーバーサイドの画像処理では鉄板のような存在でありこれだけ使われているソフトウェアに脆弱性があるなんて夢にも思わなかった。 それが、今制作しているソフトが危機に晒されてる状態にあるのである。(実際exploitを打ってみたところOSコマンドインジェクションが可能であった。) 新鮮な体験であるとともに、ソフトウェアのセキュリティの奥深さ、信頼性の脆さに気付かされた。

*1:HTMLとJavaScript技術を用いたセキュリティの講義だった