FFRIエンジニアブログ

株式会社FFRIセキュリティのエンジニアが執筆する技術者向けブログです

インターンシップ報告 2

ご挨拶

株式会社FFRIでインターンシップを行っている、桑原と申します。私がインターンシップで体験した内容について報告させて頂きます。

インターンシップに期待したこと

エンジン開発部でのインターンシップ

私は以前から、マルウェアの動的検知に興味を持っており、マルウェアの解析も行っておりました。マルウェアの動的検知の分野に大変強いFFRIが「マルウェアの解析と検知ロジックの開発」というテーマでインターンシップを行っていたため、より実践的な技術と知識を身に着ける良い機会だと思い、本インターンシップに参加致しました。

基礎技術研究室でのインターンシップ

近年、IoTへの関心が高まっています。しかし、ネットワークのトラフィックデータからIoTマルウェアによる通信が急激に増えているという報告が多数挙げられています。IoTは様々な製品に取り入れられており、その中には不正にアクセス・操作されることで重大な危機に発展してしまうものも多数存在します。私は、この問題への理解を深めるため本インターンシップに参加致しました。

エンジン開発部でのインターンシップ

エンジン開発部では、4週間かけてマルウェア解析及びその検知ロジックの開発を行いました。

マルウェア解析

ここでは、2つのWindowsマルウェアの解析を行いました。 各マルウェアの解析は、Windows上で動的及び静的手法を用いて行いました。 動的解析ではx64dbgやOllyDbgなどのデバッカーを、静的解析ではディスアセンブラであるIDAや.NETプログラムのデコンパイラであるILSpyをそれぞれ使用しました。

バンキングマルウェア

1つ目に解析したマルウェアは、外部に情報を送信するマルウェアでした。

  • 挙動情報 実行ファイルである本マルウェアを実行することで攻撃コードが実行されます。具体的には、Windowsの正規サービスであるdllhost.exeを子プロセスとして起動し、プロセスホローイングにより攻撃コードを注入します。攻撃コードは子プロセスで実行されます。

  • 駆除方法 本マルウェアを駆除する際は、親プロセス及びその子プロセスであるdllhost.exeの実行を停止させる必要があります。

  • 特徴1 プロセスホローイング プロセスホローイングの処理では、セクションを使用した手法が使用されています。実行手順は以下のようになります。この処理を通じ、子プロセスへ攻撃コードをインジェクトすることが可能になります。

    1. CreateProcessによりdllhost.exeをサスペンド状態で起動
    2. ZwCreateSectionによりセクションの作成
    3. NtMapViewOfSectionにより2.で作成したセクションの自プロセスでのマップを作成
    4. NtMapViewOfSectionにより2.で作成したセクションの1. で作成した子プロセスでのマップを作成
    5. 3.で作成したマップへの攻撃コードの書き込み
    6. 3.で作成したマップをZwUnMapViewOfSectionにより閉じる
    7. ResumeThreadにより、1.で作成したプロセスの再開
    8. WaitForSingleObjectにより親プロセスを待機状態にする
  • 特徴2 ネットワークとの通信 本マルウェアでは、作成された子プロセスによりインターネットとの通信を行っています。接続先IPアドレスは86.105.18.236です。通信はwinhttp.dllを使用しHTTPSにより行われています。パケットは「Mozila/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0」などの文字列を使用し、Firefoxの通信であるかのように偽造されています。

  • 特徴3 アンチデバッグ処理 本マルウェアでは、様々なアンチデバッグ処理が施されています。プロセスホローイングの他に、実行コードの暗号化やヒープ領域でのコード実行が行われています。 実行コードの暗号化は、ディスアセンブラなどによる静的解析を妨げる手法の一つです。この手法では、実行コードを予め暗号化しておき、実行ファイル実行時に暗号化したコードを復号してから実行することで、実行することなくアセンブラを取り出すことを妨害します。 ヒープ領域でのコード実行も実行コードの暗号化と同様に静的解析を妨げる手法の一つです。この手法では、実行時に確保したメモリに実行コードを展開し、それを実行することで静的解析により処理の流れを取り出すことを妨害します。 アンチデバッグ処理を含んだマルウェアの処理の流れは以下のようになります。

    1. .textセクションでの通常コードの実行開始
    2. ヒープ領域への実行コードの展開
    3. ヒープ領域でのコード実行開始
    4. .textセクションへの実行コードの復号
    5. .textセクションでのコード実行開始
    6. ヒープ領域への実行コード展開
    7. ヒープ領域でのコード実行開始
    8. プロセスホローイングの実行
    9. 子プロセスでの攻撃コード実行

ランサムウェア

2つ目に解析したマルウェアは、ファイルを暗号化するランサムウェアでした。

  • 挙動情報 実行ファイルである本マルウェアを実行することでファイルの暗号化処理が始まります。本マルウェアではディレクトリの探索を行い、発見した特定の拡張子を持つファイルを暗号化し、元のファイルの削除を行います。

  • 駆除方法 本マルウェアの駆除には、実行されている本プロセス及び子プロセスの除去が必要です。また、暗号化されたファイルの復号には、暗号化に使用されたパスワードを用いて復号する必要があります。

  • 特徴1 ディレクトリ探索処理 ディレクトリの探索では、下記に示したディレクトリの子ディレクトリを全て探索しています。

Personal(My Documents) デスクトップ MyComputer MyMusic
MyPictures MyVideos StartMenu CommonStartup
ProgramFilesX86 CommonProgramFilesX86 ProgramFiles CommonProgramFiles
Startup CommonDocumets CommonPictures CommonMusic
CommonVideos CommonDesktopDirectory Favorites Windows
Downloads ProgramFiles(x86) D:\ E:\
F:\ G:\ I:\ J:\
K:\ L:\ M:\ N:\
O:\ P:\ Q:\ R:\
S:\ T:\ U:\ V:\
W:\ X:\ Y:\ Z:\
  • 特徴2 ファイル暗号化処理 ファイルの暗号化には.NET FrameworkのSystem.Security.Cryptography.CryptoStreamが使用されています。また、暗号化には”password”という文字列がパスワードとして使用されています。暗号化されたファイルは、ファイル名の末尾に”.MTC-2K”という拡張子が追加されます。また、暗号化処理終了後、元のファイルは削除されます。 暗号化されるのは以下に示した拡張子を持つファイルです。
.txt .html .dll .exe .docb .docm .dot .dotm .dotx .xaml
.xltm .xlsx .pptm .pot .pps .ppsm .ppsx .ppam .potx .potm
.vmdk .vmx .gpg .aes .ARC .PAQ .bz2 .tbk .bak .tar
.gif .raw .cgm .tif .tiff .nef .psd .ai .svg .djvu
.py .asf .mpeg .vob .mpg .wmv .fla .swf .wav .mp3
.vb .vbs .ps1 .bat .cmd .js .asm .h .pas .cpp
.mdb .accdb .sql .sqlitedb .sqlite3 .asc .lay6 .lay .mml .sxm
.dif .stc .sxc .ots .ods .3dm .max .3ds .uot .stw
.msi .ico .pyd .pyc .chm .txt .json .avi .dip .pl
.xlsm .xlsb .xlw .xlt .xlm .xml .xlc .jtp .jnt .xltx
.edb .hwp .602 .sxi .sti .sldx .sldm .sldm .vdi .jpg
.tgz .gz .7z .rar .zip .backup .iso .vcd .bmp .png
.m4u .m3u .mid .wma .flv .3g2 .mkv .3gp .mp4 .mov
.sh .class .jar .java .rb .asp .jsp .brd .sch .dch
.c .cs .suo .sln .ldf .mdf .ibd .myi .myd .frm
.otg .odg .uop .std .sxd .otp .odp .wb2 .slk .odb
.sxw .ott .odt .pem .p12 .csr .crt .key .pfx .der
.dbf .db

検知ロジック開発

バンキングマルウェア

本バンキングマルウェアでは、マルウェアの挙動として特徴的なプロセスホローイングに対する検知ロジックの実装を行いました。 検知ロジックは以下の通りです。

  1. CreateProcess系のAPIにおいて子プロセスの起動がサスペンド状態で行われているかの確認
  2. MapViowOfSection系のAPIにおいてサスペンド状態で起動した子プロセスへのマップ作成を確認
  3. 1.、2.が確認された場合、独自のフィルタを適用し、マルウェアとして検知

ランサムウェア

本ランサムウェアは最小限の構成であり、不審な手順による検知・解析を回避する処理が存在しなかったため、ランサムウェア特有の処理に対する検知ロジックを開発しました。 検知ロジックは以下の通りです。

  1. 暗号化処理特有のAPI呼び出しを確認
  2. ランサムウェア特有のファイル作成、削除、アクセス処理を確認
  3. 1.、2.が確認された場合、独自のフィルタを適用し、マルウェアとして検知

基礎技術研究室

基礎技術研究室では、4週間かけてIoTの脆弱性の調査及び検証を行いました。

AGLの脆弱性調査

この度のインターンシップでは、IoT機器としてシングルボードコンピュータであるRaspberry PiにAGLと呼ばれるOSをインストールしたものを使用しました。AGLとは、Automotive Grade Linuxと呼ばれるインターネットに接続する自動車に向けて開発されたLinuxベースのOSです。AGLの脆弱性調査では、以下の内容に取り組みました。

  • SMACKの調査
  • ConnManの調査

SMACKの調査

SMACKとはAGLで使用されている強制アクセス制御です。SMACKでは、ファイルやプロセスなどにラベリングを行い、割り当てられたラベルをもとにアクセス制御を行います。

調査の結果、SMACKを使用することで脆弱性を悪用した権限昇格やシェルコードの実行を抑制することが可能であると分かりました。次節で調査を行うConnManからshへのアクセスなど、本来あり得ないアクセスをあらかじめ遮断しておくことで、ConnManの実行による脆弱性をついたシェルの実行を防ぐことができます。

しかし、root権限を使用することで、SMACKによるアクセス制限を受けずにファイル等にアクセスすることができるため、root権限を取得したユーザに対するアクセス権の制限は期待できません。また、SMACKを使用する上で、アクセス制御設定の際に注意が必要です。ラベル間のアクセス制御を適用する際、アクセス制御適用処理はroot権限のみに行わせることが可能ですが、適用処理時に読み込むアクセス制御リストファイルはroot権限でのみ書き込み可能なファイルではない可能性があります。これにより、root権限を獲得していない悪意あるユーザがアクセス制御リストファイルを書き換え、root権限を所持した正規のユーザにそのアクセス制御リストを適用させるという攻撃が可能になります。これを回避するために、アクセス制御リストの適用処理ではroot権限でのみ書き込み可能なファイルのみを使用するように注意が必要です。

ConnManの調査

ConnManとは、組み込みデバイス向けに作成されたネットワークマネージャです。ConnManのデーモンバイナリには、ASLR、カナリアコード、データ領域の実行禁止のセキュリティ機能が設けられていました。

ここでは、ConnManに存在するCVE-2017-12865の脆弱性についての調査を行いました。

本脆弱性はConnManの1.34以前のバージョンで有効であり、DNSレスポンスメッセージの処理に欠陥があるため発生します。正確には、ConnManでDNSレスポンスからドメイン名の取り出しを行うget_name関数に不備が存在するために発生します。この不備により、get_name関数では、ドメイン名の格納先にそのサイズ以上の書き込みを行えるため、バッファオーバフローの脆弱性が存在しています。バージョン1.34以前のConnManを使用されている場合は、すぐにアップデートを行うことをお勧めします。

以降、本脆弱性についての検証を行っていきます。

脆弱性の検証

ConnManに存在するCVE-2017-12865の脆弱性を検証するため、簡易的なDNSサーバの作成を行いました。

本脆弱性では、DNSレスポンスのドメイン名を読み込む際、読み込む文字数の制限が適切に実装されていないため、バッファオーバフローが発生してしまいます。この検証を行うため、作成したDNSサーバでは不正なドメイン名を使用してDNSレスポンスを構成します。実装したサーバを使用し、脆弱性の検証を行いました。サーバのIPアドレスは192.168.15.10、ConnMan側のIPアドレスは192.168.15.15です。

ConnMan側の端末にはsshでログインし、名前解決先は作成したサーバになるように設定しました。ConnMan側の端末での操作及びその結果を以下に示します。pingによる名前解決によりネットワークマネージャがDNSレスポンスを受け取り、sshによるネットワーク接続が遮断されています。

root@raspberrypi3:~# ping aaaaaaaaaaaaaaaaaaaa
Connection reset by 192.168.3.15 port 22

C:\Users\test>

また、/var/log/messagesを参照した結果以下のようなログが存在しました。4行目から、ConnManのデーモンであるconnmandにおいてシグナル 6(SIGABRT)が発生し、プロセスが終了していることがわかります。このことからConnManのダウンに成功していると判断しました。

Aug  6 10:16:16 raspberrypi3 auth.info systemd-logind[247]: Removed session c4.
Aug  6 10:19:19 raspberrypi3 daemon.info systemd[1]: Starting Cleanup of Temporary Directories...
Aug  6 10:19:19 raspberrypi3 daemon.info systemd[1]: Started Cleanup of Temporary Directories.
Aug  6 10:21:44 raspberrypi3 daemon.err connmand[664]: Aborting (signal 6) [/usr/sbin/connmand]
Aug  6 10:21:44 raspberrypi3 daemon.notice systemd[1]: connman.service: Main process exited, code=exited, status=1/FAILURE
Aug  6 10:21:44 raspberrypi3 daemon.notice systemd[1]: connman.service: Unit entered failed state.
Aug  6 10:21:44 raspberrypi3 daemon.warn systemd[1]: connman.service: Failed with result 'exit-code'.
Aug  6 10:21:44 raspberrypi3 daemon.info systemd[1]: connman.service: Service hold-off time over, scheduling restart.

脆弱性検証コードの有効性の証明

前節でConnManのダウンには成功しましたが、その正確な原因については分かっておりません。ここでは、作成した検証コードによってCVE-2017-12865の脆弱性を突き、ConnManのダウンに成功していることを確認していきます。

ダウン原因の確認にはGDBを用いたデバッキングにより行いました。

本検証コードにより、期待通りバッファオーバフローを起こした場合、ConnManのデーモンバイナリに設けられているカナリアコードチェック機能によりエラーが発生しデーモンが終了します。そこで、ダウン原因確認のためGDBによりカナリアコードチェック処理及びバッファオーバフローの発生箇所を確認していきます。

  • カナリアコードのチェック処理のデバック 画像1はCutterによるカナリアコードチェック処理のアセンブラコードです。画像1からカナリアコードのチェックを行う処理では、[sp+0x34]に保存されている正規のカナリアコードとsp+0xdc4に保存されているスタック書き換え確認用のコードを比較し、スタック書き換えを検知していることがわかります。画像2から検証時のスタックでは、[sp+0x34]0x56ff0900となっていますがsp+0xdc40x61616161となっていることがわかります。このため、スタックの書き換えが検知され__stack_chk_failが呼ばれプロセスが終了しています。

画像1 カナリアコードチェック処理のアセンブラ(Cutter)

画像2 検証時のカナリアコード(GDB)

  • バッファオーバフローの発生箇所のデバック バッファオーバフローはget_name関数で発生しています。この関数では、DNSレスポンスからドメイン名を取り出しを行っています。しかし、この処理に不備があり、取り出したドメイン名の格納先に格納先のサイズ以上の情報を書き込むことが可能になっています。これが、バッファオーバフロー発生の原因となっています。この関数では検証コードによって作成されたDNSレスポンスを格納しているバッファから、sp+0x9c0~sp+0x131a間に0x61及び0x3fの書き込みを行っています。画像3、4は上記のスタックにおける開始位置及び末尾の書き込み後の状態を表しています。本来のConnMan側はsp+0x9c0~sp+0xdc2間の書き込みを想定しています。また、get_name処理開始前はsp+0xdc4[sp+0x34]の値は画像5の様に等しいですが、get_name処理後は画像6の様にsp+0xdc40x61616161となっています。

画像3 ドメイン名格納先の開始位置(GDB)

画像4 ドメイン名格納先の末尾(GDB)

画像5 get_name処理前のカナリアコード(GDB)

画像6 get_name処理後のカナリアコード(GDB)

脆弱性検証コードについての結論

カナリアコードのチェックでは、[sp+0x34]sp+0xdc4の値を比較しています。また、get_name関数でのドメイン名の取り出し処理では検証用のDNSレスポンスにより、sp+0x9c0からsp+0x131aまでが0x61(ASCIIコードでaに対応)及び0x3f(ドメイン名のラベルごとの文字数を表す)で埋められています。sp+0xdc4はこの領域内に存在するため、カナリアコードのチェック処理で偽と判断され、__stack_chk_fail関数が呼ばれプロセスが終了しています。このため、get_name関数での名前取り出しでバッファオーバフローが発生し、それが原因でカナリアコードのチェックエラーが発生していることがわかります。

よって、作成した検証コードによりconnmandのダウンが成功していると判断することが出来ます。

任意コード実行に関して

escar Asia 2017の発表では、connmandの脆弱性をつきroot権限のshellを奪取するデモが公開されています。このデモの環境と今回調査した環境ではセキュリティ機能が違う可能性が考えられますが、仮に同じセキュリティ機能であった場合、回避する何かしらの手法が存在することが考えられます。

所感

エンジン開発部では、マルウェアの解析から検知ロジック開発までの一連の流れを経験しました。マルウェアの検知ロジックを開発する上で大切なことは、より多くのマルウェアを効果的に検知でき導入先の作業を阻害しないことです。これを実現するには、より多くのマルウェアが使用するロジックを最小単位で見つけ出し、かつ、そのロジックがマルウェア以外を過剰に検知しないことが求められます。また、動的な検知ロジックにおいてはプロセスを動作させながら監視を行うため、マルウェアがユーザを損害をもたらす前に検知する必要があります。そのため、ITに対する広い知識と解析の正確さの重要性を深く痛感致しました。

基礎技術研究室でのインターンシップでは、ConnManの脆弱性について多く触れました。この脆弱性は、ネットワークマネージャのダウンだけに留まらず、セキュリティ機能が無効、もしくは何かしらの手段によって突破された場合、攻撃者が任意のコード実行してしまう可能性もある、とても致命的な脆弱性です。しかし、この脆弱性が発生してしまった原因は、たった一か所のサイズチェック漏れです。今回使用したAGLは、大手自動車メーカーでも使用している車載用のOSです。近年、自動車自身が通信を行う自動車の開発に力が入っていますが、これらを外部から操作できてしまうと人命に直接かかわる大惨事に繋がる恐れがあります。これを防ぐためにも、慎重な開発とその漏れを防ぐセキュリティ対策の向上が必須であると改めて感じました。