2021-06-25

Multimedia Security Topics

OWASP Sendai #48 で、マルチメディアのセキュリティをトピックスにお話させていただきました。

本セッションでは、ソフトウェアとハードウェアのセキュリティに注目し、どのような保護が行われているのか、また過去にどのような脆弱性があったかについて解説しています。

発表スライドだけでは、分かりづらい部分も多く、文章にてまとめさせていただきましたので、ご覧頂けますと幸いです。

1. DRM について

image.png

コロナ禍になり、現在盛り上がっているのが、オンライン配信です。
国や都道府県の指示で、無観客にせざるえない状況となった今、エンターテイメントを届けるにはライブ配信しか方法がありません。
ですので、今まさにお話ししている裏側ではたくさんの配信が行われています。
こういったオンライン配信では、現在問題となっていることがあります。

それは、映画泥棒ならぬ映像泥棒です。

image.png

有観客で会場にお客さんを入れていたときから少し話題になっていたのですが、いわゆる公演中に撮影や録画をする行為は当たり前ですが禁止されています。
これはオンライン配信でも同じです。
しかし、有観客の場合は、会場スタッフによる巡回などで、それらの行為を阻止することができたのですが、オンライン配信の場合はどうでしょうか?
配信ページをスクリーンショットで撮影したり、またはデスクトップキャプチャによる録画、最終的にはモニターをスマホのカメラで録画するなどして、簡単にできてしまいます。そして、これらを完全に阻止するのは不可能です。
もし完全に阻止するのであれば、CBT 試験のように、マウスやキーボードをトラッキングして、ウェブカメラもつけて監視しないといけなくなりますが、せっかく楽しんで視聴するのにそんなに面倒なことはやりたくないですよね?
このように完全に阻止することはできないのですが、かなり難しい方法を使わないとできなくさせることはできます。

その一つとして、DRM があります。

DRM

image.png

DRM は、Digital Rights Managementの略称で、日本語ではデジタル著作権管理と呼ばれます。
DRM はソフトウェア制御を使い、コンテンツ保護を行う仕組みであり、DRM 自体は技術ではありません。
また、似たようなものに DVD や Blu-ray のコピーガード(AACS)もありますが、こちらは広義的にいえば DRM の一つであると言えます。
DRM の歴史はかなり古く、1950 年代には概念的提案があったと言われています。
むかしはフラッシュメモリやハードディスクがなかった時代に、磁気テープを使って記録をしていました。
しかし、磁気テープは簡単に複製が可能で、これにより複製が横行し、開発者は莫大な投資を行なっても開発費用の回収は難しいのが現状でした。
これを防ごうと生まれたのが DRM の考え方でした。ソフトウェア制御により、暗号化を行い、コンテンツを保護をするという提案が 1970 年代に提唱されました。
ここから DRM の歴史はスタートしたのです。

2. DRM の種類

image.png

DRM といっても、たくさんの種類があります。
例えば、PDF の暗号化もその一つですし、電子書籍の暗号化もまた一つです。
今回は、マルチメディアに絞ってお話しさせていただこうと思っています。
今日、映像や音声の配信にはストリーミング方式が主流となっています。従来はファイルをダウンロードする方式が主流でしたが、コンテンツデリバリーネットワークの普及により、キャッシュ制御をより柔軟にしやすくするために、1 ファイルをそのままダウンロードする方式から、細切れにして送るストリーミング方式が採用されています。
また、ストリーミング方式のメリットとしては、クライアントは必要なデータだけ取得すればいいので、例えば 3 時間の長編映画があったとしても、始まりから 30 分後にシークして再生する場合、取得するデータは 30 分後の動画データだけでよくなります。全て取得する必要はなくなるため、取得から再生が高速になり、また不要なトラフィックを流さなくて良くなるので、配信側も視聴側もメリットが多いのです。

HLS と MPEG-DASH

スクリーンショット 2021-06-20 17.52.14.png

このストリーミング方式ですが、マルチメディアの世界では、Apple が開発した HTTP ベースの HTTP Live Streaming、通称 HLS と呼ばれるものと、MPEG が開発した同じく HTTP ベースの MPEG-DASH の 2 つがあります。
一般的にはどちらも使われることが多いのですが、最近は HLS が使われることは多いですね。m3u8 と呼ばれるマニフェストファイルの中に動画データが細かく刻まれており、プレーヤーはそれらをフェッチすることで再生を行います。
今回、HLS の詳しいお話しはしませんので、ご興味のある方は、私が過去に発表したスライドがありますので、そちらをご覧いただければと思っております。

さて、話を戻しますが、この HLS や DASH の暗号化方式としてはいくつか種類があります。

HLS-AES

image.png

まず最初に、とてもシンプルな方式があります。これが HLS-AES と呼ばれる方式です。
名前の通り、HLS のセグメントに AES-128 で暗号化を行います。
鍵情報はマニフェストに記載されており、動画再生時にプレーヤーは鍵情報から鍵を取得し、セグメントを復号して再生します。

このメリットは、HLS のセグメントをそのままダウンロードしても、VLC などのプレーヤーで再生ができません。
なので、知識がない人からすると良い対策であると言えます。
しかし、デメリットは、鍵の入手が非常に簡単であることです。実際に、マニフェストに鍵情報が書かれているのですが、ここから鍵を取得するのは安易であり、ウェブの知識が少しでもある人からすると、簡単に入手できて、復号されてしまいます。
つまりは諸刃の剣なのです。

この HLS-AES を対策するために、ソフトウェアだけではなく、ハードウェアの観点からも保護しようと生まれたのが、次に紹介する方式です。一般的に DRM と呼ばれているものは次の通りです。

FairPlay

image.png

まず最初に Apple が策定した FairPlay と呼ばれる保護システムをご紹介します。

この FairPlay は、かなり昔から存在しており、iTunes で購入した楽曲にも以前は FairPlay で音声ファイルが保護されていたり、App Store で配布されている IPA(iOS アプリの実行ファイル)にも FairPlay で保護されていたりしていました。

FairPlay の大きな特徴として、OS に統合されていることです。OS に DRM の仕組みが統合されることにより、キャプチャ防止や外部からの改変が行えないようにできます。

この FairPlay を HLS にも適用したのが FairPlay Streaming です。通称、FPS と呼ばれます。FairPlay Streaming は、HLS または CMAF のみサポートしています。

Widevine

image.png

一方で、Apple に続き、Google が策定したのが Widevine と呼ばれる保護システムです。Widevine は、HLS および MPEG-DASH、CMAF をサポートしています。

Widevine は、元々 Widevine Technologies という会社が提供していた DRM ですが、2010 年に Google に買収されています。現在は Alphabet 傘下にあります。

Widevine は、DRM の中では一番使われていると言っても過言ではないでしょう。

今日、Google Chrome の普及や Android スマートフォンの流行により、さまざまなデバイスで Widevine は使われるようになりました。

セキュリティレベル

Widevine の特徴として、セキュリティレベルと呼ばれる概念が存在します。このセキュリティレベルとは、再生端末がどれだけセキュリティ要件を満たせているかによって割り振られています。

このセキュリティレベルはハードウェアレベルで決まってくるのですが、セキュリティレベルによって視聴が制限されることになります。

セキュリティレベルは 3 段階あり、一番最強なのがレベル 1 です。その次がレベル 2 となり、一番最低はレベル 3 です。

レベル 1 では、全てのコンテンツ処理、暗号化、および制御を SoC の信頼できる実行環境(これを TEE と呼びます)で実行して、外部からの改ざんやメディアファイルのコピーを防ぐ必要があります。例えば、ARM プロセッサの場合は TrustZone と呼ばれる機能があり、これが TEE に当たります。

レベル 2 では、コンテンツの暗号化自体は TEE で行われますが、再生処理については TEE では実行されません。

レベル 3 では、TEE がない端末の場合や、デバイスの外で処理される場合に適用されます。ただ、レベル 3 であっても暗号化に対して適切な対策を行う必要はあります。

このセキュリティレベルですが、レベル 1 を満たしていないと HD 以上の品質を再生することはできません。また、レベル 1 を満たしている状態であっても、アプリ上で再生するかどうかを決めることができるので、ブラックリスト方式で、特定のデバイスは再生できない場合もあります。このブラックリスト方式の理由ですが、認証は通ったとしても、そのデバイスが完全に安全であるかどうかの保証まで Widevine は行わないので、中華製品の一部端末ではリジェクトされているケースがあるようです。

また、ここまでお話しして、Widevine をデバイスメーカーが取得するのは結構大変だと思われるかもしれませんが、ある程度の面倒なプロセスはあるものの、Widevine 自体は無料で取得することができるため、Widevine を取得していないメーカーは、何かしらの事情が抱えている可能性が高いと思います。

この Widevine ですが、Apple FairPlay と違って、Widevine 自体は完全に OS に統合されているわけではなく、また Widevine のレベル 3 の場合は SD 画質のコンテンツは再生できるので、完全に保護されていません。ここが大きな違いとなります。

ここまでが Widevine のお話しでした。

PlayReady

image.png

次に Microsoft 社が策定している PlayReady について解説していきます。PlayReady は、Widevine 同様に HLS および MPEG-DASH、CMAF、そして Microsoft 独自のフォーマットである Microsoft Smooth Streaming をサポートしています。

PlayReady は 2007 年に登場したもので、WMV(Windows Media Video)や WMA(Windows Media Audio)を保護するために誕生しました。

PlayReady は FairPlay 同様に OS に統合されているため、安全性が確保されています。キャプチャなどに関しても防止することが可能です。

OPL

PlayReady は、Widevine のようにセキュリティレベルが 2 つ存在します。1 つ目が OPL (Output Protection Levels)と言います。

OPL は、Microsoft のドキュメントによると 100、150、200、250、270、300、400、500 の 8 段階あり、100 が一番最高で、500 が一番最低のようです。

OPL は、デバイスの出力先によって細かく制御されています。例えば HDCP 非対応のディスプレイでコンテンツを再生する場合、OPL 270 以降となり、HD 再生はできません。

SL

2 つ目に、SL と呼ばれるセキュリティレベルがあります。SL は 3 種類あり、SL150、SL2000、SL3000 があります。

SL150 は、PlayReady の中では一番最低のセキュリティレベルです。デバッグ以外では利用してはいけないこととなっています。

SL2000 は、DRM をソフトウェアだけで処理を行うものです。

SL3000 は、DRM を Tee などで安全な実行環境で処理を行うものです。

この SL ですが、制約はデベロッパー側が決めて良いということになっており、最近だと SL3000 ではないと HD 以上の画質が再生できないサービスが増えています。

以上、FairPlay と Widevine と PlayReady、この 3 つがメジャーな方式です。これら以外にも多くの種類がありますが、今日 Netflix や Amazon Prime Video などの VOD サービスではこれらが使われています。

3. TEE について

セキュリティレベルで、出てきた TEE についてもう少し深ぼってみましょう。TEE とは、Trusted Execution Environment の略で、OS とは独立してクリティカルな処理が安全に実行できる機能のことです。

TEE は、近年の CPU に含まれており、Intel SGX や、AMD SEV、ARM TrustZone などが有名です。

TEE は、隔離実行を提供するのみであり、あくまでも TEE を使うプラットフォーム側で安全に機密情報を保有し、TEE を実行する際に安全性が確保できる必要があります。

TEE は隔離実行環境ですが、TEE 以外にも隔離実行機能はいくつかあります。これらを Hardware Isolated Execution Environment(HIEE)と呼びます。

TEE は HIEE の一種ですが、TEE がソフトウェアで実行されることに対し、Trusted Platform Module(TPM)は完全に CPU から独立した別チップで実行されます。

TPM の場合、あらかじめ備わっている機能しか実行できませんが、鍵生成や機密情報保存、乱数生成などを提供し、Trusted Boot や BitLocker などの機能と連携します。

TEE は、Trusted OS と呼ばれる独自の OS が動いており、その上で Trusted Application (TA)が動きます。

ARM TrustZone

image.png

ARM TrustZone は最も広く使われている TEE であり、スマートフォンはもちろん、Nintendo Switch などのゲームデバイスでも活用されています。

TrustZone の歴史は古く 2003 年の ARMv6K から導入されており、1 つの隔離実行環境を起動時に作成します。

TrustZone の中でも今日一番使われている Cortex-A のアーキテクチャでは、Trusted OS では全ての特権が利用できます。元の OS からアクセスする際には、Secure Monitor Call(SMC)命令を使い、通信を行います。

ARM TrustZone の多くの機能はソフトウェアによって実装されています。

Intel SGX

image.png

Intel SGX(Software Guard Execution)は、Skylake 以降に導入された隔離実行機能です。SGX は、TrustZone と異なり、ほとんどがマイクロコードで実装されています。

SGX の場合、ユーザーが使える特権は Enclave と呼ばれる実行環境で、ユーザーレベルの Ring3 のみで、全ての特権は利用できません。

また、Enclave は最大 128MB のメモリ領域しか使えません。

AMD SEV

image.png

AMD SEV(Secure Encrypted Virtualization)は、EPYC シリーズで導入された隔離実行環境です。SEV は、仮想化を意識した TEE であり、クラウド上の仮想マシンで使われることを目的にしています。

SEV の大きな特徴として、TEE 用に専用のメモリ領域などを用意することはなく、VM の実行自体を秘匿化します。

つまり、VM のメモリと仮想ディスクの暗号を管理することで、ハイパーバイザーから覗き見できないようになっています。

SEV を使ったソフトウェアとして、Redhat の Enarx などがあります。

TEE の事例

TEE は、先程お話しした DRM でも鍵の管理に使われています。Android では Keymaster と呼ばれる鍵管理の仕組みがあり、これは ARM TrustZone を前提に実装されています。

iOS では、ARM TrustZone に似たものとして、Secure Enclave と呼ばれるセキュリティプロセッサがあり、Apple T2 チップの中にあります。

Secure Enclave では、Touch ID や Face ID のデータ管理や、FileVault によるディスク暗号化や FairPlay の鍵管理なども行っています。この Secure Enclave ですが、アプリ上からは一切アクセスすることはできず、iOS のバージョンとともにアップデートされるので、iOS のバージョンと SE のバージョンがミスマッチすると、認証ができなくなることがあります。

TEE の脆弱性

TEE は、CPU 内の隔離実行機能でありますが、物理的にコアを割り当てているわけではないため、脆弱性が多くあると言われています。

例えば、キャッシュ共有を悪用した Prime + Probe が Intel SGX で有効であることは知られており、ForeShadow と呼ばれる攻撃では、CPU の脆弱性として大きく騒がれた Spectre と同じく、キャッシュの共有と投機的実行を組み合わせることで攻撃が可能です。

また、Side Channel 攻撃には TEE は耐性がありません。このように、TEE も脆弱性はあり、リスクを少しでも減らすためには Root of Trust との連携が重要となってきます。

4. DRM の decrypt について

ここまで、DRM の簡単な説明をしてきました。

ここからはセキュリティ業界の方が聞いているということもあり、普段はあまりスポットが当たらない DRM の decrypt についてお話ししていきます。

ここでは具体的な手法まではお話ししませんが、オフェンシブセキュリティの観点から、攻撃者がどうやって DRM コンテンツを decrypt するのかお話ししていきます。

共通鍵暗号について

image.png

DRM では、暗号化と復号化の際に、使用する鍵が一緒である共通鍵暗号を使います。共通鍵暗号は、鍵が漏れてしまうと、簡単に復号できるため、鍵を漏らさずに配布することが重要となってきます。

また、共通鍵暗号の場合は処理速度がポイントとなってきます。

共通鍵暗号には、ブロック暗号とストリーム暗号の二種類あります。

ブロック暗号

ブロック暗号とは、平文を一定の大きさ(ブロック)にいくつかまとめて暗号化する手法です。暗号文は平文と同じサイズになります。

ブロックサイズよりも大きな平文を暗号化するためには暗号化モードと呼ばれるものを利用します。

ブロック暗号は区切って処理するため、処理負荷は大きくありません。

代表的な例として、AES による暗号が主流となっています。

ストリーム暗号

ブロック暗号にたいして、平文を小さな単位で順次処理する暗号化方式をストリーム暗号といいます。

平文と鍵の排他的論理和(XOR)をとって、暗号処理や復号処理をするのが特徴です。

ブロック暗号と比較して、細かい単位で処理するため、処理速度は早いですが、効率は悪いため、一長一短です。

ストリーム暗号は無線 LAN の暗号化などに使われています。

この 2 つの方法で、共通鍵暗号は暗号化されるのですが、出力結果が毎回同じですと、そこから推測されてしまう危険性があります。

IV

これを阻止するために IV(Initialization Vector)と呼ばれるものを使います。IV は、データを解読しにくくするためにランダムなビット列を、合間に挟むことで、出力結果を毎回変えて、推測されるのを防いでいます。

この IV ですが、ブロック暗号の場合は、平文と直前の暗号化したブロックを参照し、XOR した結果が次のブロックの暗号文となります。初めて暗号化するときに IV が使われます。

ストリーム暗号の場合は、擬似乱数生成器(Seed)で暗号文を作成しますが、Seed の偏りをなくすために IV が使われます。

ここまでが共通鍵暗号の仕組みでした。DRM では、この仕組みを使って、暗号化していくのですが、いくつか種類があります。

CBC

まず最初に CBC(Cipher Block Chaining)をお話しします。CBC は、ブロック暗号を用いた方式で、一番最初は IV で XOR し、その次に直前の暗号ブロックと平文ブロックを XOR し、次の暗号文となるのを最後まで繰り返します。

CBC は、直前のブロックを元に処理するため並列処理ができず、ブロックサイズに満たない場合はパディングでデータを埋める必要があります。

CTR

次に、CTR(CounTer)をお話しします。CTR もブロック暗号を用いますが、1 ずつインクリメントするカウンタを用意し、それを暗号化し、出力される暗号文と平文ブロックで XOR します。これにより、ブロック暗号をストリーム暗号として扱うことができ、パディングなどの処理が必要ないため、パフォーマンスもよく、並列処理で実行することもできます。

CTR では、カウンタにノンスと呼ばれる使い捨ての乱数を用いることで、結果を固定化しないように防いでいます。

DRM の暗号方式の種類

ここまで共通鍵暗号のお話しをしました。ここからは、DRM における暗号方式の種類についてお話しします。

DRM には、大きく分けて 3 種類暗号方式があります。

AES-128

まず最初に AES-128 です。これは名前の通り、AES-128 で暗号化し、暗号化モードとしては CBC または CTR どちらかを使います。これはシンプルで分かりやすいですね。

SAMPLE-AES

次に、SAMPLE-AES についてお話しします。この SAMPLE は見た目試供品みたいなイメージがありますが、データのブロックのことをサンプルといいます。SAMPLE-AES は、全体を暗号化するのではなく、一部を暗号化することにより、処理速度を高速化したり、負荷を軽減することが可能となります。例えば、動画の場合は I フレームだけ暗号化を行なったり、動画だけ暗号化したり、色々設定ができます。SAMPLE-AES は CBCS と呼ばれることもあります。SAMPLE-AES は、CBC を使い、暗号化を行なってきます。

MPEG-CENC

次に、MPEG-CENC(Common Encryotion Scheme)についてお話しします。MPEG-CENC は、MPEG が策定した共通暗号化方式です。CENC は、さまざまな DRM システムでも共通で使えるように策定されたものです。CENC は CBC や CTR について決まりがなく、どちらもで使って良いこととされています。

ここまでが DRM の暗号方式の種類についてのお話しでした。

FairPlay Streaming

image.png

さて、ここからは本題に入ります。FairPlay Streaming では、SAMPLE-AES を使い、暗号化します。

FairPlay Streaming のワークフローについて

FairPlay Streaming では、以下のワークフローで動作します。

  1. ユーザーはアプリを開き、FairPlay Streaming のコンテンツの再生を開始します。
  2. AVFoundation で再生開始の準備を行います。
  3. AVFoundation で、指定された URL から HLS のマニフェストファイルをフェッチし、解析を行います。
  4. 解析を行った後に、マニフェスト内にある #EXT-X-KEY タグがあるかどうか確認します。該当タグがあった場合には、セグメントを復号化するために AVFoundation はコンテンツキーの要求処理を開始します。
  5. コンテンツキーを取得するためにサーバ再生コンテキスト(SPC)メッセージの生成処理を開始します。
  6. SPC メッセージが生成された後に、アプリは SPC メッセージをキーサーバーへ送信します。
  7. キーサーバーは、Key Security Module(KSM)を使い、クライアントからのライセンス要求を受信して復号化のために必要なコンテンツキーを CKC メッセージにラップし、クライアントに送信します。
  8. 受信した CKC メッセージをもとに、AVFoundation はコンテンツを復号し、再生開始します。

これらのワークフローで、FairPlay Streaming は動作しますが、主な特徴として、キーサーバーから送られる CKC メッセージの中に、コンテンツキーの他に有効期限も入っているため、コンテンツキーは一定期限しか有効になりません。また、鍵の取扱については、カーネル上で行われるため、ユーザーランドからアクセスすることは不可能です。

これらのワークフローは、重複して取得しないように、キーサーバーに SPC メッセージを送るトランザクションは 1 回のリクエストのみ有効になります。つまり、2 回以上は送れないようになっています。

また、FairPlay Streaming は、AirPlay においても有効です。AirPlay の場合は、送信元端末が CKC メッセージを受信し、コンテンツキーを AirPlay デバイスに送信して、復号を行います。この時、AirPlay デバイスに送られる際に、FairPlay Streaming 同様の暗号化をかけて送るため、抜き取られる心配はありません。

FairPlay Streaming は、数々ある DRM の中でも、OS と密接に紐づいているため、Decrypt するのは困難です。

FairPlay Streaming の Crack について

しかし、いわゆる Jailbreak (脱獄) を行い、root 権限が取れるようになると、端末内部に保管しているコンテンツキーを取得することは可能にはなります。Jailbreak に対しての手立てはありません。

また、Jailbreak 以外にもいくつか手法があります。2020 年 5 月に公開された “Psychic Paper” と呼ばれる PoC では、iOS 13.4.1 以下の端末の場合、コンテンツキーを取得することが可能です。コード書名の脆弱性を利用し、XNU(Darwin Kernel)にある IOTaskHasEntitlement と呼ばれるプロセスに特定のエンタイトルメント(キー)があるかチェックするメソッドを使い、コンテンツキーを抽出するというものです。ここでは詳しく説明はしませんが、このように iOS の脆弱性を使うことで、コンテンツキーを取得する手法もあるため、完全ではありません。しかし、ほとんどのユーザーがここまでたどり着くのは不可能であると思いますので、FairPlay Streaming を実装するデベロッパーとしては無視しても問題はありません。しかし、完璧は存在しないことは忘れないでください。

https://twitter.com/s1guza/status/1255641164885131268

Widevine

Widevine は、MPEG-CENC を使い、暗号化されます。Widevine の場合は暗号化スキームに AES-128 CTR を使う必要があります。

Widevine には 2 種類あり、レガシーデバイス向けの Widevine Classic と、現在使われている Widevine Modular があります。Classic の方は、Android 5.1 まで使われていたもので、現在はほぼ使われていません。

Widevine を理解するのにあたり、追加で必要な知識があります。

CDM

まず、CDM についてです。CDM とは、Content Decrypt Module の略で、Widevine の処理を行うモジュールのことです。この CDM は、各ブラウザに組み込まれていますが、ソースコードは公開されていません。

ちなみに、CDM があるかどうか確認するのは簡単です。例えば、Google Chrome の場合は、アドレスバーに chrome://components/ を入力して、エンターを押してみてください。その後、リストが表示されると思いますが、その中に Widevine Content Decryption Module があったら、ちゃんと存在していることが確認できます。

この CDM ですが、Google Chrome の他に、Mozilla Firefox や、Microsoft Edge など、主要ブラウザは全て入っています。ちなみに、Chromium を使っている場合は入っていない場合があります。

CDM の役割としては、ライセンス要求を行うことや、復号キーを安全に保管することや、さらには復号したコンテンツを外部からアクセスできないようにしたり、ビデオをセキュリティが担保されている出力デバイスに出力したり、ほとんどの処理は CDM が担っていると言ってもいいでしょう。

EME

CDM は、Widevine の主な処理を担っていると説明しました。では、この CDM をプレーヤーから呼び出すにはどうすればいいでしょうか?CDM は実は定期的にアップデートされており、頻繁に変更が入っています。そのため、プレーヤーから CDM を呼び出すのはあまり現実的ではありません。

これを対処するために、Encrypted Media Extensions(EME)と呼ばれる抽象化レイヤーがあります。EME は、プレーヤーに対して、CDM と通信するための API が用意されているため、プレーヤーは EME の API を叩けば、CDM とやりとりすることができるのです。

この EME の中身は JavaScript API です。EME は、単純にやりとりを行うだけで、実際にビデオの処理などは CDM が行っています。EME は W3C 標準となっており、とても扱いやすいです。

Widevine のワークフローについて

image.png

Widevine では、以下のワークフローで動作します。

  1. ユーザーはアプリを開き、Widevine のコンテンツの再生を開始します。アプリは、MPEG-DASH のマニフェストファイルをフェッチして、解析します。その後、Widevine で暗号化されていることを確認し、初期セグメントにある InitData を抽出します。
  2. アプリは、Widevine を復号するために、CDM に InitData を送信します。
  3. CDM はアプリから InitData を取得し、InitData を含めたライセンス要求を作成して、これをアプリに送り返します。
  4. アプリはライセンス要求を受信すると、Widevine License Server にその要求を送信します。ライセンス要求は暗号化されているため、解読は不可能です。
  5. License Server は、要求を受信したあと、リクエストを復号化し、その中にある InitData から紐づくライセンスを検索します。該当するライセンスがあった場合、コンテンツを復号するキーと、ライセンスの有効期限などを含めたメッセージを暗号化し、アプリに送信します。
  6. アプリは、Widevine License Server から暗号化されたメッセージを受信し、それを EME を経由して、CDM に渡します。このメッセージも暗号化されているため、解読は不可能です。
  7. CDM は、デバイスレイヤーにある OEMCrypt モジュールを使い、復号処理を開始します。また、ここで復号したキーを使い、コンテンツの復号も行われます。
  8. コンテンツが復号されると、CDM はビットストリームを安全に送り、出力デバイスから画面や音声が出力されます。なお、この際に復号したデータはデバイスのどこにも保存されません。

ここまでが Widevine のワークフローでした。Widevine は、Google と契約することで CDM などを取得することはできます。なお、Widevine を契約する際にいくつかトレーニングを受ける必要があり、若干面倒ですが…。(コロナ以前はシンガポールにいって、トレーニング受けないといけなかったりしたんですが、今はオンラインになったのでだいぶん楽になりました…)

Widevine は、FairPlay と比べると、ワークフローが複雑であることがわかります。しかし、今日、DRM の脆弱性として一番多いのが Widevine です。

Widevine の Crack について

Widevine の代表的な脆弱性として、2019 年 1 月に発見された Widevine Level 3 の脆弱性が有名です。これは、WIdevine の AES-128 実装に問題があり、差分故障解析(DFA)と呼ばれる攻撃により、正しい暗号文と誤りを含む暗号文の差分をもとに、秘密鍵の候補を絞り込むことにより、暗号化されたメッセージを解読しようとするものです。

Widevine Level 3 は、冒頭にお話ししたとおり、TEE などに守られないレイヤーで処理が行われます。つまり、外部からの攻撃には非常に弱いのです。また、これらの脆弱性は Widevine の仕様上の問題であるため、修正される可能性はないと言われています。

しかし、Level 3 では、HD コンテンツは再生できないため、低解像度のビデオになってしまいます。たとえ復号できたとしても品質が悪いので、見れれば十分といった感じにはなってしまうでしょう。

ちなみに、これを応用したブラウザ拡張が GitHub 上に公開されていた時もあったのですが、米国のデジタルミレニアム著作権法(DMCA)に基づき削除されました。

Widevine は、このように脆弱性の危険性があります。しかし、Widevine はデベロッパー側から許容レベルを指定することができます。今回の場合、Level 3 が狙われましたが、Level 1 と Level 2 のみにしておくことで、こういった危険性から回避することはできます。

また、この脆弱性以外にも Widevine は仕様上解決できない問題がたくさんあります。例えばキャプチャ防止に関してです。

Widevine は、先程の説明で、CDM がビデオの処理も行なっていると説明しましたが、厳密には、復号した生データをビューワーに渡すところまで行っています。つまり、再生自体は CDM の管轄ではないのです。したがって、スクリーンショットは可能です。ただ、画面キャプチャに関しては、CDM が OS の API を叩き、キャプチャすると映像自体は真っ黒で録画されたりするのですが、音声はそのままキャプチャできてしまいます。スクリーンショットについては、Android 端末で、Google Chrome を開き、Widevine コンテンツを試しに再生してみてください。その後、スクリーンショットを撮ると、ちゃんと綺麗に映ってしまいます。この件についてですが、私も色々話しているのですが、なかなか解決するのは難しそうです。

このように Widevine 自体はかなり不完全です。なので、Widevine に合わせてアプリ側でも、映像を抜き取られないように実装する必要があります。

例えば、Android の場合は SecureFlag を使い、そもそもスクリーンショットを取れないようにすることもできます。これらを応用することで、完全にキャプチャできないようにすることは可能です。しかし、ネイティブアプリに限りますので、ブラウザの場合は効果がありません。こういったケースがありますので、Netflix をはじめとする大手 VOD サービスはモバイルブラウザでの視聴はできないようになっており、ディープリンクでアプリに飛ばすような実装になっています。

Widevine は、ちゃんと理解していないと、こんなにも多くの穴があることに気づかないでしょう。利用する際はご注意ください。

PlayReady

メジャーな DRM システムの中では、一番使われることが少ない、PlayReady ですが、実は Android でも一部使われていることもあったり、Internet Explorer で再生する場合は PlayReady しかサポートしないため、意外と使うケースは多いです。

この PlayReady ですが、もともと Microsoft Silverlight と呼ばれる動画再生用のプラグインの中に誕生したものでした。今は Silverlight は使われなくなりましたが、PlayReady の仕組みは残っており、現在も使われています。

PlayReady ですが、暗号化スイートは CTR と CBC 両方ともサポートしていますので、いずれかを使えば問題ありません。

PlayReady の大きな特徴として、アカウントティング機能があることです。これは Active Directory の概念とかなり似ていて、ここでもドメインコントローラーと呼ばれる概念があります。ドメインコントローラーにより、複数デバイスでライセンスを共有することが可能です。また、メータリングサーバと呼ばれる概念もあり、再生回数などをクライアント側で保存することもできます。この再生回数ですが、サーバ側に送信することができ、これによって視聴した回数分課金といったシステムを実装することができます。

PlayReady のワークフロー

image.png

PlayReady では、以下のワークフローで動作します。

  1. PlayReady の場合は、コンテンツを暗号化するところから始まります。まず、パッケージングされたコンテンツを暗号化し、コンテンツは、S3 などに配置されます。この時にライセンスキーと暗号化キーは、ライセンスサーバに送信され、ドメイン情報についてはドメインサーバに送信されます。
  2. アプリは、PlayReady のコンテンツを再生すると、マニフェストをフェッチし、PlayReady で暗号化されているか確認します。もし暗号化されている場合は EME を通して、PlayReady の CDM に情報を送信します。このフローは Widevine と同様です。CDM は、ライセンス要求を作成し、EME を通して、プレーヤー側に要求を渡します。プレーヤーはライセンス要求をライセンスサーバに送信します。この時に、KeyID と呼ばれるコンテンツごとに紐づいている一意の値(GUID)も送ります。
  3. ライセンスサーバは要求を受け取り、KeyID を使って、該当するライセンスを探します。もし該当するライセンスがあった場合、コンテンツの復号化を行うキーと、ライセンスの情報を暗号化し、アプリに送信されます。
  4. アプリは、ライセンスサーバーから、暗号化された要求を受け取り、これを EME 経由で CDM に渡します。
  5. CDM は、ハードウェアコンポーネントを使い、暗号化された要求を復号し、その中からコンテンツを復号するために必要なキーを抽出し、コンテンツを復号します。この際に、クライアントに復号したキーを保存するライセンスストアも提供されます。

このように、PlayReady のワークフローは Widevine とほぼ同じです。異なるのが、KeyID を送る部分と、ライセンスを取得するタイミングです。

PlayReady の場合は、プロアクティブと呼ばれる再生前にライセンスサーバにライセンス要求をする場合と、リアクティブと呼ばれる再生後にライセンス要求を行う 2 つパターンがあります。リアクティブの場合、すでにライセンスがライセンスストア内にあった場合はすぐに再生が開始されます。もし、ライセンスがなかった場合は上記のワークフローに則って、新規取得を開始します。

Widevine と比べて PlayReady の優位性

PlayReady は、Widevine と似ており、また、Microsoft Edge が Chromium 化した現在となってはあまりメリットはないのですが、OS と統合されているのは非常に強く、また Widevine の欠点であったキャプチャ防止などが PlayReady ではそのままでも実現することができます。

実際、Netflix は Microsoft Edge で視聴する際は、Widevine ではなく PlayReady を使用しています。Windows ユーザーをターゲットにする場合は、Widevine より PlayReady のほうがよりセキュアであることが分かります。

また、PlayReady の場合、Windows ランタイム API(WinRT)で処理されるため、最終的には NT カーネルで処理されることとなります。なので、外部から抜き取られる心配もありません。

ここまでが、DRM の実際のワークフローと decrypt について説明してきました。やはり、最終的にはハードウェアレベルでの対応をしなければいけないのは変わりなく、ソフトウェアだけで保護するのには限界があると私は感じております。

5. ハードウェアで守るためには

ここまで DRM のお話をしてきました。なぜ DRM の話をしたかというと、まず一つとしては、DRM はどの手法も完璧なものは存在しないことを理解してほしいのと、ハードウェアでの保護の重要性についてお伝えしたかったからです。

各 DRM は、TEE のような環境で動かすことを推奨しています。では、いくら安全な環境で処理したからといって、セキュリティは守られるのでしょうか?

今回は、Android を例に、ハードウェアで守るためにどのようなことを行っているかご紹介したいと思います。

Android のメディアサービスについて

Android では、これまで多くの脆弱性があり、その多くがマルチメディアに関するものでした。任意の動画ファイルをデコードしただけで、バッファオーバーフローにより、任意コード実行ができたりと、問題視されてきました。

これを Google はどう解決していったのでしょうか。

Google は、2019 年にリリースした Android 10 から、ソフトウェアコーデックを扱うサービスを、制約つきサンドボックスに移動しました。

これにより、さまざまなコンポーネントを特権では動作できないサンドボックスに分離することで、セキュリティを向上させることができました。

この制約つきサンドボックスでは、命令コールの制限や SELinux ドメインでプロセスは実行されます。命令コール制限には、Linux Kernel の機能である seccomp を使っています。

また、従来では OS の更新が必要であった MediaCodec や MediaExtractor などを、部分的にアップデートできるようになりました。これは Android 9 以前では、脆弱性に対処するためには OS ごとの更新が必要だったものを、部分的に更新できるようになりました。

Android の特権の歴史

image.png

Android の特権の歴史が描かれている図をご覧ください。Android Q が 10、Android O/P が 8/9、Android N が 7、Android M が 6 を表しています。

Android 7.0 以前は、メディアの処理に関しては mediaserver が 1 つのプロセスで担っていました。Extractor だけ別で実行されていました。

これが Android 7.0 になり、再設計を行い、それぞれの処理がプロセスごとに分割されました。この時に初めて Extractor は制約つきサンドボックスに配置されました。

次に、Android 8.0 になり、さらに制約が増えることとなりました。個々のサービスはサンドボックスに実行されることになり、ハードウェア抽象化レイヤー(HAL)になりました。Android 9.0 では特に変更がないため、この図では一緒になっています。

そして、Android 10 です。ここでは MediaCodec からソフトウェアコーデックが分離され、システム側に戻りました。ここでは SELinux ポリシーと seccomp のポリシーが大幅に強化され、今まではソフトウェアコーデックは、ハードウェアアクセラレーションのためのコーデックを扱うデバイスドライバー(OpenMAX-IL)にアクセスできていたのが、アクセスが禁止されることになりました。特にこの取り組みは効果が絶大であり、従来ソフトウェアコーデックは、信頼できないソースからビットストリームを解析するのにあたり、さまざまなライブラリを使っています。これが脆弱性の温床であり、偽装された動画ファイルをソフトウェアコーデックがデコード処理を行う際に、バッファオーバーフローなどを起こし、任意コード実行などができていました。これを制約つきサンドボックスで制限し、かつデバイスドライバーへのアクセスも制限することで、脆弱性をかなり軽減することができました。

このように、ハードウェアで処理を行う場合、行動を制限することにより、セキュリティを確保しています。

私はこのアプローチはとても素晴らしいと考えており、このアイデアを他の部分でも転用できないかと考えていました。

6. Unikernel を用いたセキュリティサンドボックスの構築について

私は業務でも趣味でも FFmpeg をよく使っています。FFmpeg はコマンドラインで動画や音声をエンコードしたり、フィルター機能をつけたりできる優秀はソフトウェアです。

FFmpeg と Libav の関係性について

image.png
image.png

FFmpeg は、2011 年 3 月に開発体制の対立から、Libav と呼ばれるソフトウェアに一度分裂しました。この Libav では、FFmpeg の代わりに AVConv と呼ばれるコマンドラインツールを提供しています。当時、Debian が Libav を採用したため、大きな騒ぎとなりました。

しかし、2015 年 7 月に Debian が FFmpeg に戻ると発表しました。戻した理由としては、FFmpeg のほうが開発が早く、脆弱性への対応も早かったためです。これにより、FFmpeg に戻る風潮が高まり、Libav は 2018 年にリリースして以来、リリースは止まっており、Git の last commit も 2019 年で止まっています。

事実上、FFmpeg に戻ったのですが、Libav で追加されたコードはまだ FFmpeg には反映されていません。

さて、なぜここで Libav の話をしたかというと、私は uppercase で Libav を書きましたが、 lowercase の libav が存在するからです。

libav について

スクリーンショット 2021-06-20 17.59.25.png

この libav は、FFmpeg におけるライブラリを示します。具体的には、コーデックライブラリである libavcodec、コンテナライブラリである libavformat、フィルターライブラリである libavformat などをまとめて libav と言います。Libav の元ネタはここから来ているのですが、今日、そのままリブエイブイと言われて、よく使うのはライブラリのほうです。実際、Libav は開発が停止しているので、基本的にはライブラリだと思っていただいて問題ありません。

話を戻しますと、FFmpeg には libav と呼ばれるライブラリ群があります。このライブラリ群は至る所で使われています。

先程お話しした Android でも使われていますし、動画プレーヤーとして有名な VLC Media Player も使われていますし、その他 Unity Asset Store で配布している動画再生プレーヤーなんかも使われています。むしろ、libav が使われていないケースを探すほうが大変なくらい使われています。

この理由として、libav はさまざまなフォーマットをサポートしています。そのため、基本的には対応していないフォーマットはほとんどありません。

FFmpeg のライセンスについて

スクリーンショット 2021-06-20 17.59.52.png

ただ、注意いただきたいのが libavcodec にあるコーデック実装の中には非公式なものが数多く存在しているという部分です。これは、動画や音声ファイルから解析したり、コーデックを提供している DLL などを解析し、そこから符号化処理を逆算して、実装しているものが多く、ライセンスとしてグレーゾーンな部分が数多くあります。

また、FFmpeg 全体は LGPL 2.1 でライセンスされており、これは libav も含みます。そのため、そのまま商用利用する際はソースコード開示が必要となるため、注意が必要です。その他、MPEG 関連の技術を使う場合は MPEG LA にライセンス料を払う必要も出てきます。ちなみに libav を使う際にビルド方法などを細かく指定することで、GPL に抵触しないやり方もあるので、興味のある方は各自で調べてください。また、libav をラップしたものとして、VLC Media Player で使われている libvlc があるのですが、こちらは商用ライセンスもあります。こちらは宣伝なのですが、興味ある人がいたら僕に連絡ください。

FFmpeg の脆弱性について

スクリーンショット 2021-06-20 17.58.10.png

さて、この FFmpeg ですが、脆弱性が山ほどあります。なぜこんなにあるかと申しますと、FFmpeg にはメンテナンスされていないものが数多くあり、先程説明したとおりグレーゾーンなものが該当します。そのため、頻繁に CVE が発行されているのですが、libav を使って開発する側の立場としては、セキュリティを意識しつつも、libav を使って便利なソフトウェアを開発するメリットも数多くあります。

この 2 つのバランスを維持しながら運用していくにはとても大変です。

そこで私が提唱するのが、Unikernel を用いたセキュリティサンドボックス上で動作させるというアプローチです。

まず、これをお話しするのにあたり、Unikernel についてご説明していきたいと思います。

Unikernel

image.png

Unikernel とは、ライブラリベースの OS を使用し、仮想環境上で動作させるために構築された単一アプリケーション用の軽量実行環境です。

ライブラリベースの OS とは、OS 機能をライブラリとして実装することにより、アプリケーションはユーザー空間とカーネル空間との情報のやり取りなしでハードウェアに直接アクセスすることが可能になります。

しかし、ハードウェアにアクセスするためには、ライブラリベースの OS に対し、ドライバを書かないといけなくなるため、負担が大きいです。

これを解決するために、仮想環境上で動作する技術が Unikernel となります。

Unikernel では、ハイパーバイザーが提供する仮想デバイス用のデバイスドライバを、ライブラリベースの OS に実装することで、Unikernel では、実際の入出力の制御をハイパーバイザーに任せることができます。

Midori

image.png

Unikernel を語るのにあたり、忘れてはいけないものがあります。それは、Microsoft Research が昔研究開発をしていた「Singularity」と呼ばれるプロジェクトです。

Singularity プロジェクトは、10 年以上にわたり、研究開発が進められており、その成果が Midori と呼ばれる OS の開発に貢献してきました。

しかし、Midori は 1 度もリリースされることなく、プロジェクトは実質解散されたと言われていましたが、この Midori には、アプリケーションサンドボックスの機構が存在しており、これが Unikernel の仕組みとかなり類似する部分が多いのです。

Midori は、元プロジェクトメンバーだった Joe Duffy 氏が 2015 年 11 月に自身のブログで、プロジェクトの内容に語っているので、興味のある方は Joe 氏のブログをご覧ください。

Midori の知見は、次世代 Windows へと取り込まれていると推測されるので、今後新しい Windows には、アプリケーションサンドボックスの仕組みが提供されるかもしれません。

MirageOS

image.png

Unikernel の代表的な実装例として、MirageOS があります。MirageOS は、2009 年にRCUK (現在は UKRI) Horizon Digital Economy Researchから資金提供を受けて始まった Unikernel を構築するためのライブラリベースの OS です。現在は英ケンブリッジ大学の OCaml Labs、Robur、Tarides、IBM Research、Docker などに所属するメンバーをコアチームとし、英ケンブリッジ大学、IBM Research、ARM、Google、Citrix などに所属するメンバーがコントリビューターとして継続的に開発に携わっています。

これらは、ハードウェア上にハイパーバイザーが動作し、その上にアプリケーション本体と必要とするランタイムのみをパッキングした Unikernel が動作するという構造となっており、仮想環境で動かせるようにコードがコンパイルされます。その結果、ユーザー空間とカーネル空間のやり取りがなくなり、直接ハイパーバイザーにアクセスできるため、仮想マシンで OS を動かすよりもパフォーマンスが向上されると言われています。

さて、ここまで Unikernel のお話しをしてきましたが、Unikernel を実際に動かしてみる話をしていきたいと思います。

Unikernel を動かす際にセキュリティに気をつけて行かないといけません。外部から攻撃される一因を少しでも減らすために必要最低限のアクセスに止めることは大事です。先程お話しした Android の Media サービスでは、各サービスのアクセス権限を必要最低限に絞ることで、リスクを減らすことができました。Unikernel を動作する上でも同じことが言えます。

これらを意識しながら、動かしやすい環境を提供してくれるソフトウェアとして Solo5 と呼ばれるものがあります。

Solo5

Solo5 は、OS レイヤーとプラットフォームレイヤーを仲介するソフトウェアです。Solo5 が、OS レイヤーと接する共通 API を提供することにより、OS レイヤー自体はプラットフォームを気にせずに動かすことができます。

image.png

また、Solo5 が使えるプラットフォームレイヤーとして、主に 2 つあります。

1 つ目が hvt (Hardware Virtualized Tender)です。hvt は、Linux の場合は KVM、BSD の場合は vmm を使います。

2 つ目が spt (Sandboxed Process Tender) です。spt は、Android 同様に seccomp ポリシーを使います。

hvt と spt の大きな違いとして、hvt は KVM などと API のやり取りを行い、仮想マシンとして動かすものに対し、spt はシステムコールを制限することにより、Linux 上の 1 プロセスとして動作することができます。ただ、パフォーマンス面では、hvt の方が良いです。

このように Unikernel は手頃に実行することができます。また、Unikernel を動かすアプローチは、サンドボックスを重視しており、セキュリティ面の心配する必要がありません。

Unikernel を使った応用研究

私はこの Unikernel を使い、先程の libav で実装されたアプリケーションを動かす研究を行っています。もし、不正な動画データをデコードする際に、バッファオーバーフローが起きたとしても、Unikernel によってホスト側は守られているため、ホスト側がダメージを受ける心配はありません。

image.png

また、この Unikernel ですが、現在は IoT デバイスで動かす取り組みが活発となっています。もともと、IoT デバイスは、リソースが少ない中で、インターネットと通信するため、セキュリティが非常に大事になってきます。その中で、Unikernel を使うことで、IoT のセキュリティを担保することができるのではないかと言われており、その研究が進んでいます。

マルチメディアの世界では、IoT とかなり結びついている部分が多いです。例えば監視カメラや、車のドライブレコーダー、最近では体温測定するサーモグラフィーなど、多くの部分で関わっています。ただ、マルチメディアは、攻撃者からしてみると、侵入するために非常に扱いやすい入り口となっており、動画や音声ファイルをアップロードすれば、意図した挙動を引き起こしてしまうことができます。これらを防ぐために、私は Unikernel を用いた研究を今後行っていきます。

今はソフトウェアコーデックを動かすところまでしか行えていないですが、最終的には CUDA や、ハードウェアコーデックもサポートできると面白いと思っています。

7. 最後に

本日は、マルチメディアのセキュリティというトピックスで、ソフトウェアとハードウェアの両方の視点からご紹介していきました。

特に Unikernel を使った取り組みについて、企業とは関係なく、私個人で進めていたプロジェクトですが、近々、色々な人と一緒に共同で行っていきたいと思っています。

皆さんもご興味ある方がいたらぜひ私に連絡してください。一緒に面白い取り組みを行っていきましょう。