セキュリティマイスターコラム 第10回

つながる時代のものづくりxセキュリティを実現する人材が育まれるセキュリティ勉強会(後編)

富士通グループの現場エンジニアがセキュリティを学ぶ「セキュリティマイスター勉強会」という勉強会があります。オープンソースカンファレンスやSECCONなどの業界横断の取り組みで得た知見や、仕事で得た知見を皆で持ち寄って、実機にて学ぶ場です。

この実機にて学ぶ場を「セキュリティマイスター道場」として一般公開することにしました。第一回目を2018年3月23日「みなとみらいInnovation & Future Center Camping studio」で行ないました。今回は、2回に分けて「セキュリティマイスター道場」でどんなことを行なっているのかレポートします。

後編は、LinuxカーネルにおけるMeltdown脆弱性の解決策とセキュリティコンテスト「SECCON」2017決勝サーバ壱の問題紹介とその背景、バイナリかるたをご紹介します。

[写真]

Linuxカーネルにおけるmeltdownの対策

Meltdown脆弱性に関して、Linuxカーネルがどのような対策をしたのかの解説です。

「つながる時代」に重要度を増すセキュリティバイデザイン

Meltdownは Intel製プロセッサーに起きるバグで、本来実行されないはずの命令が実行され、かつユーザープログラムから本来アクセスできないカーネル空間メモリのデータが参照可能になるという脆弱性です。結果としてカーネル空間で守られているはずの秘密情報や他のユーザー情報が読めるという深刻な問題を引き起こします。

Meltdownに対応するためにLinuxに導入されたのが、Kernel Page Table Isolation(KPTI)です。
コンピューター上のプログラムは、広大な仮想アドレス空間上で動作しています。プログラムが仮想アドレスを使って呼び出すメモリの実際の格納場所である、物理アドレスへ変換するのがページテーブルです。Linuxでは、このページテーブルが、1プロセスごとに1つ用意されており、テーブルの上半分はカーネルが使用するエリア、下半分はユーザー空間が定義されています。また、カーネル用テーブルは、Ring0の特権状態のみ読み書き可能で、ユーザー空間用はRingによらず読み書き可能です。

KPTIは1プロセスに対して以下の2つのページテーブルを管理し、カーネル部分を分離しているのが特徴です。

  1. カーネル空間実行用テーブル
    従来と同じで、上半分はカーネルが使用するエリア、下半分はユーザー空間が定義されています。
  2. ユーザー空間実行用テーブル
    ユーザー空間と、syscall発行に必要な最小限のカーネルページだけ含みます。
    つまり、カーネルページがマップされていないので、Meltdown できません。

さらに、Ring0の特権モードのままユーザー空間のプログラムを実行することを防ぐために、KPTIでは Non executable (NX) ビットを使用しカーネルを実行中にユーザーメモリ空間にNXビットを立てることにしました。これによって、Ring0の特権モードのままユーザー空間のプログラムを実行することができなくなります。仮に特権昇格脆弱性を使って特権状態を奪取しても、NXビットの付いているユーザー空間ではコード実行が出来なくなります。
そうすると、特権昇格脆弱性を使って任意のコードを実行するためには何らかの方法でカーネル空間内に攻撃コードを注入しなければならず、任意の攻撃コードを実行するための難易度が桁違いに上がります。

KPTIのパフォーマンス問題をどう解決したか?

しかし、この対策では、パフォーマンスに課題が残ります。
Intelプロセッサーでは物理メモリアドレスにたどり着くまでに、テーブルを4回参照するので時間がかかるため、Translation Lookaside Buffer (TLB)というページテーブル専用のキャッシュを用意し、高速性を保っています。

KPTIを適用すると、同じプロセスでもユーザー空間を実行している時とカーネル空間を実行している時でページテーブルが異なり、従来はプロセス切り替え時のみ破棄されていたTLBは、KPTIでは、2つのページテーブル間を遷移する度に破棄が必要となり、動作が遅くなるのです。

この問題を解決してくれるものとして、Intelのhaswell以降のCPUに導入されたPCID(process context id)があります。PCIDはTLBにID情報を与え、実行中のIDと異なるTLBを無視する仕組みなのでKPTIでTLBを破棄する必要がなくなります。
PCIDを使えば、TLBを破棄する必要がなくなるので、一見素晴らしいように思えます。しかし、PCIDは最大4096IDしか使用できません。KPTIでは1プロセスに2つのPCIDを使うため最大2048プロセス分しかないことになります。数百万のプロセスを動かすことができるLinuxでは、確実にPCIDの枯渇が起きます。
結論としては、LinuxではPCIDの利用を最大6プロセスに限定し、常にCPUのL1キャッシュに乗り続けるようにデータ構造を工夫することでパフォーマンス問題を解決しました。現在のLinux搭載システムの多くはマルチコアになっており、一つ一つのコアにはあまり多くのプロセスが動いていないため、この方法でも速度に与える影響は深刻にならないのではないかという判断です。

本来このような面倒な問題は下位レイヤーが解決してくれるのですが、一番下にあるカーネルの問題を解決するためには自分自身で何とかする必要もでてくるのです。ここがカーネルの難しく面白いところです。

富士通研究所
Linuxカーネル開発者 小崎 資広

[写真]

セキュリティの現場で役立つスキル。即興プログラミングとバイナリを読む力

SECCON2017決勝サーバ壱の問題出題の意図

セキュリティとプログラミングは無関係と思いがちですが、セキュリティの現場では即興的にプログラムを作ることもありますし、コードを読み解く力も必要です。

そこで、難解プログラミング言語のひとつである「Brainf*ck言語」を使ったコードゴルフ問題を作成して、SECCON2017国際決勝大会に出題しました。
Brainf*ck言語はコンパイラがなるべく小さくなるように考案されたもので、実行可能命令は「><+-.,[]」の8つしかありません。これだけでは当然セキュリティの問題になりませんので、隠し命令を追加し、セキュリティホールを用意しました。

課題は「より短く『Hello, World!』を出力するコードを書く」他、バイナリやサーバ内に隠されている3つのフラグ文字列を探すというものです。
単に短いコードを書くだけではなく、バイナリ解析を行う事で隠し命令を見つけ、それを手掛かりにフラグ文字列を見つけ、それを使って本来のBrainf*ck言語では実現できない最短コードの作成や任意のメモリを読み書きし、侵入プログラムがかけるという仕掛けです。
読み出したメモリに「Hello, World!」を含む文字列があるので、これを活用すると9バイトのコードが最短になるのですが、9バイトで書いたチームが勝利ではなく、サーバを攻撃してスコアを高く表示させるというのもアリとしました。結果、各チーム間のスコア書き換え合戦となり、サーバがエラーを出してしまい、競技終了予定時刻より2時間も前に競技終了になるというハプニングもありました。

実作業でパッと理解できる力を育成する「バイナリかるた」を実施

最後に「バイナリかるた」大会が実施されました。スクリーンに映し出されるバイナリダンプを見て、それがどのようなフォーマットであるかを判断して札を取るゲームです。バイナリデータを見て、パッとそれが何かを判断できるスキルを養成するためにつくられたゲームです。

[写真]並べられた取り札

実際の解析現場ではファイルに対して適切な対処をする必要があります。たとえばARMのLinuxの実行ファイルに対してx86の逆アセンブラを実行しても全く意味がありません。
ファイルダンプを見て、それがx86のLinux実行ファイルなのか、あるいはARMのLinux実行ファイルなのか、画像ならそれがPNGなのかJPEGなのかBMPなのかをパっと判断するスキルが求められます。
このようなスキルを自然と学ぶために作られたのがバイナリかるたです。最後に判断のコツを伝授しました。

[写真]スクリーンに映しだされた問題。見分けかたのポイントを解説する坂井セキュリティマイスター

[写真]スクリーンを見て、該当するフォーマットの名前が書かれた取り札をとります

一般向けに開催した第一回のセキュリティマイター道場。参加者から「低レイヤーの勉強ができる場は珍しいので良かった」、「『低レイヤー技術を知ることは大事』という言葉が印象的」と好評のうちに終了しました。

[写真]後半の「グラフィックレコーディング」

富士通システム統合研究所
ハイマスター領域 コンピュータウィザード
セキュリティマイスター 白神 一久

セキュリティマイスター紹介ページ

[写真]

2018年6月28日

「セキュリティ」に関するお問い合わせ・ご相談

Webでのお問い合わせ

お電話でのお問い合わせ

ページの先頭へ