2015年3月19日に米国で掲載されたブログ記事の抄訳です。

Unit 42は新たなPOS(販売時点管理)マルウェアを検出しました。これには2014年11月に作成された最も古いものを含め、複数の変種が含まれています。各変種に一様に見つかる文字列に基づいて、このマルウェアを「FindPOS」と名付け、過去数週間、分析を行いました。

 

このマルウェアは特別に巧妙なものではありませんが、多数の変種がAlinaBackoffなどと同様にまん延の様相を見せています。FindPOSは明らかにMicrosoft Windows POSベンダーに対する強力な脅威と見なすべきであり、確実な防御のための対策をとる必要があります。

 

ワークフロー

このマルウェアは、メモリ スクレイピング(情報抽出)によってトラック データを収集し、見つかったデータをHTTP POST要求を介して引き出すことができます。また、キーストローク(タイピング認証)の記録機能も持つことがあります。このマルウェアは、POSデバイスを標的とするこれまでのマルウェアと共通した手法を多数使用しているものの、その広がり具合や継続的進化から、WindowsベースのPOS端末を利用する人々にとって脅威となっています。

FindPOSマルウェアの一般的なワークフローは次のとおりです。

 

進化

私たちは調査を続けるなかで、FindPOSの変種を合計9個検出しました。コンパイル タイムスタンプ(ファイル作成/修正日時)情報に基づいて、これらの変種が次のような時系列になっていることがわかります。

バージョン間の具体的な機能変更の内訳は次のとおりです。

 

バージョン2.1

  • 次の情報を使用するように、ハッシング アルゴリズムを変更:
    • ボリューム シリアル番号
    • ネットワーキング アダプタ(IPv4のみ)
  • 「uinfo」POSTパラメータを追加

 

バージョン5.57

  • インストール時に以前にインストールされたFindPOSを終了させる機能を追加
  • インストール時のコードのクリーンアップ
  • メイン スレッドを最低優先度に設定
  • メモリ スクレイピング チェックを追加
    • 有効期限年範囲は2014~2030
    • 有効期限月範囲は1~12
    • サービス コードの設定は「101」または「201」のいずれか
  • ファイルのダウンロード/実行機能を追加
  • 「Cookie: income=1」HTTPヘッダ-を削除
  • User-Agent HTTPヘッダーを追加

 

バージョン5.80

  • メモリ スクレイピング チェックを変更
    • 有効期限年は2030を越えないものとする(下限チェックはなし)
    • 有効期限月は12を越えないものとする(下限チェックはなし)
  • ドメイン/URI構成のコードを強化

 

バージョン5.90

  • キーロギング機能を追加

 

バージョン6.0

  • 大きな変更はなし

 

バージョン6.02

  • データ引き出し機能のマイナーチェンジ

 

バージョン6.03

  • 大きな変更はなし

 

バージョン6.04

  • データ引き出しスリープ タイマーのマイナーチェンジ

 

上記の時系列から、FindPOSは初期にきわめて積極的な開発が行われ、その後は最小限の変更が行われているようです。最小限の変更は、パフォーマンス上の理由か、おそらくバグの修正を目的として適用された可能性があります。

 

インストール

FindPOSは、実行を開始すると、英小文字8文字の実行可能ファイル名(例: abodeign.exe)を生成します。この名前は、次のシステム情報を基に生成されます。

  • C:\ボリューム シリアル番号
  • SystemBiosdate
  • VideoBiosdate
  • CPU識別子
  • Microsoft WindowsプロダクトID

 

名前の生成にこれらの値を使用することで、同じコンピュータ上での実行時の名前生成に一貫性が維持されます。なお、使用されるハッシング アルゴリズムはバージョン2.1で変更されています。詳細については、上記の「進化」のセクションを参照してください。

その後、この実行可能ファイル名が、実行中のマルウェアの元の実行可能ファイル名と比較されます。これらの名前が一致しなかった場合、マルウェアは自身のインストール ルーチンの実行に進みます。

 

FindPOSは、さきほど生成した実行可能ファイル名を使って、次の各ディレクトリに自身をコピーし始めます。

  • %SystemRoot%\System32\[名前].exe
  • %USERPROFILE%\[名前].exe

 

これらのファイル コピー操作が正常に完了すると、マルウェアは次の各レジストリ キーを書き込みます。

  • HKLM\Software\Microsoft\Windows\CurrentVersion\Run [名前] :%SystemRoot%\System32\[名前].exe
  • HKCU\Software\Microsoft\Windows\CurrentVersion\Run [名前] :%USERPROFILE%\[名前].exe

 

マルウェアは、CreateProcessAの呼び出しを介して、%SystemRoot%\System32\[名前].exeの新しいインスタンスの作成を開始します。この処理が正常に完了すると、終了前に次のコマンドを実行します。このコマンドは、元の実行可能ファイルを削除するためのものです。

cmd.exe /c del [元の実行可能ファイルのパス] >> NUL

 

%SystemRoot%\System32\[名前].exeに対するCreateProcessAの呼び出しに失敗した場合、FindPOSは%USERPROFILE%\[名前].exeの新しいインスタンスの作成を試みます。これに成功すると、FindPOSはさきほどと同じ手法を使って元の実行可能ファイルの削除を試みます。

 

インストールが正常に完了すると、FindPOSは、必ず1つのFindPOSインスタンスのみが稼働するようにするために、グローバル ミューテックスを作成します。このミューテックスには次の名前が付けられます。

  • WIN_[16進数]

[16進数]は、16桁の大文字の16進文字列であり、インストール ルーチンの実行時にマルウェア実行可能ファイル名の生成で使われたものと同じ手法で生成されます。

 

このミューテックスの作成が正常に完了すると、FindPOSはメモリのスクレイピングを開始します。さらにキーストロークのロギングも開始する場合があります。

 

 

メモリ スクレイピング

メモリ スクレイピング(情報抽出)は、過去に検出されたPOSマルウェアの大半で検出されている手法です。コンセプトは単純で、POS端末で実行されているプロセスメモリを読み取り、トラック データを探すというものです。POS端末では、カード決済情報が暗号化されて送信されるまでの一瞬の間、暗号化されていない状態でメモリに存在することがあります。攻撃者はこのわずかの隙をついてトラック データを探します。

メモリ スクレイパーのパフォーマンスを高める一般的な手法の1つは、explorer.exe、lsass.exe、csrss.exeなどのよく見られるプロセス名のブラックリストを作成することです。また、特定のプロセス名を標的としたホワイトリスト アプローチを使用するマルウェアもあります。しかし、FindPOSはまったく新しいアプローチを使用しています。このマルウェアは、EnumProcessesOpenProcessGetTokenInformation、およびLookupAccountSidの呼び出しを介して、システム上の各プロセスの所有者を特定します。その後、プロセスの所有者を「NT AUTHORITY」文字列と比較します。これによって、システムまたはサービスとして実行されていないプロセスを除外します。次の例では、「dwm.exe」と複数の「conhost.exe」インスタンス以外のすべてのプロセスが除外されます。

図1  実行中のプロセスの例

プロセスが除外されなかった場合は、VirtualQueryExReadProcessMemoryの呼び出しを介してメモリがスクレイピングされます。これはほぼすべてのメモリ スクレイパーで見られるごく一般的なアプローチです。

データの読み取りが完了すると、FindPOSはトラック データを探し始めます。バージョン5.57から、トラック データ内で検出される各種データに基づくチェックを実行するようになりました。たとえば、バージョン5.57以降では、有効期限日が2014年7月から2030年12月までの範囲に含まれないトラック データを無視します。これは、期限切れのカード データを取り込まれないようにするためです。

 

また、検出されたトラック データ内に出現するサービス コードに特に注意を払っています。サービス コードは、カード リーダーに通されたカードの種類を表す3桁の数字です。ここで取り上げている事例では、次のオプションが設定されているカードのみを取り込んでいます。

1 – 「国際データ交換OK」または「国際データ交換、可能な場合はIC(チップ)を使用」

2 – 「標準」

3 – 「制限なし」

 

これらの制限を追加することによって、攻撃する意味のないカードを無視できるようになります。たとえばギフト カード、デビット カード、テスト カードなどです。

 

検出されたトラック データは、メモリに格納され、その後「data」 POSTパラメータを使って引き出されます。

 

キーロギング

バージョン5.90から、FindPOSファミリーにキーロギング(キー入力操作を記憶する)機能が追加されました。磁気カード リーダーの多くが、しばしばキーボード装置をエミュレートします。これを踏まえて、多数のPOSマルウェア ファミリーにキーロギング機能が組み込まれています。キーロギングでは、トラック データ収集だけでなく、侵入したコンピュータ上でユーザー名やパスワードなどの機密情報を収集することができます。

この目的で、FindPOSではキーロギングを実行する新しいスレッドを作成します。一般的な手法を使って、新たな空白ウィンドウの作成、直接入力装置としての自身の登録、GetRawInputData APIの呼び出しが行われます。

キーストロークはメモリに格納され、その後引き出されます。キーストロークは、「logs」 POSTパラメータを介して引き出されます。

 

データの引き出し

FindPOSでは、HTTP POST要求を介してデータが引き出されます。サンプルごとに、いくつかのハードコードされたドメインが構成されます。これは多くの場合FindPOSの変種間で異なります。HTTP POST要求は120秒(2分)ごとに実行されます。トラック データやキーストローク データなどのデータが見つかった場合は、このデータが挿入されます。バージョン5.80の要求の例を以下に示します。

この例に明らかなように、各要求にはいくつかのPOST変数が挿入されます。

 

「uinfo」パラメータのデコードの例を以下に示します。

>>> import base64
>>> base64.b64decode(“Sk9TSC1QQyBAIGpvc2gtUENcam9zaA==”)
‘JOSH-PC @ josh-PC\\josh’

 

キーストローク データとトラック データは、Base64エンコードと1バイトのXOR暗号化の組み合わせを使って識別不能にされます。このデータのデコードは次のように行われます。

>>> import base64
>>> raw = “”
>>> for s in base64.b64decode(“HxkaGxgfGhodGhoaGhsTGxcbHxoSGxobGhMbGBkeHxwdEhMaGxU=”):>>>     raw += chr(ord(s) ^ 0x2a)
>>> print raw
5301250070000191=15081010912345678901?

 

FindPOSには、データの引き出しのほかに、さらなるマルウェアのダウンロード/実行機能が追加されています。引き出し要求の送信後、サーバが0x1または0x4バイトに続けてURLで応答した場合、このファイルがダウンロードされ、その後実行されます。

 

ファイルは一時フォルダにダウンロードされ、ファイル自体にプレフィックス「BN」が付加されます。このダウンロードされたファイルは、CreateProcessAの呼び出しを介して実行されます。正常にダウンロードまたは実行できなかった場合、ファイルはディスクから削除されます。

 

ドメイン/IPアドレス情報

FindPOSマルウェアの調査で検出されたドメイン数は合計37です。これらのドメインのうち、13個の一意のIPアドレスが検出されました。これらのIPアドレスの地理的な位置は次のとおりです。全ドメインを網羅した完全なリストについては、付録を参照してください。

検出されたドメインの大半は、以下のWHOIS情報を使って構成されていました。

登録者名: Julio Quinlan
登録者の組織:  NA
登録者の番地: 4516 Glory Road
登録者の都市:Nashville
登録者の州: TN
登録者の郵便番号: 37204
登録者の国: us
登録者の電話番号: +01.9318135965
登録者の内線番号: 登録者のファックス番号: +01.9318135965
登録者のファックス内線番号: 登録者の電子メール: barkmanueta@rambler.ru

 

なお、登録者の電子メールについては、照会対象のドメインに応じてやや異なっていました。上記の情報は一見正規の情報のように見えますが、偽りであることがわかっています。

 

関連するサンプル – キーロギング/LogMeIn Recon

私たちの調査では、いくつかの類似するサンプルが検出されています。このようなサンプルの1つを以下に示します。

バージョン8.3 – LogMeIn Recon / キーロガー

 

このサンプルは、LogMeInアカウント情報の収集、キーストロークとマウス クリックのロギング、これらのデータの定期的な引き出し(リモート サーバへの送信)を実行します。このサンプルには、以前に検出されたFindPOSサンプルと同じ特性がいくつもあります。たとえば、インストール プロセス、URIスキーム、HTTP POST要求のフォーマット、PDB文字列などです。

 

このマルウェアは、実行を開始すると、FindPOSと同じ方法で自身をインストールします。また、前述の手法でミューテックスを作成します。このマルウェアは、次のレジストリ キーをチェックすることによって、侵入したコンピュータにLogMeIn Ignitionがインストールされているかどうかを判別しようとします。

HKCU\Software\LogMeIn Ignition\[変数のハッシュ]\Account :Email

 

電子メールを検出すると、すべて引き出します。これには、FindPOSに見られるものと同じHTTP POST要求を使用します。ただし、このサンプルでは、「data」POSTパラメータではなく、「logs」パラメータを使用します。以下のとおりです。

このマルウェアはキーストロークとマウス クリックのロギングを開始します。2分ごとにこれらのデータを引き出します。

 

このサンプルはキーボード装置をエミュレートするカード リーダーを持つPOS端末からトラック データをスクレイピングするために使用された可能性もありますが、むしろ、より多くのPOSコンピュータにアクセスする目的で使われた可能性のほうが高いのではないかと私は見ています。おそらくこのサンプルは、複数のPOSコンピュータを管理するコンピュータにドロップされ、このコンピュータから取得した情報を使って、このコンピュータの管理対象となっているPOSコンピュータへのアクセスを試みたのではないでしょうか。

また、もう1つ興味深いのは、このサンプルのコンパイル タイムスタンプがキーロギング機能の導入(バージョン5.90)のおよそ2週間後であることです。マルウェアの開発者が新しい手口をレパートリーに加えた時期とちょうど一致するのです。

 

結論

全体的に見て、FindPOSはそれほど巧妙なものではありません。巧妙なコマンド アンド コントロール構造、強力な暗号化、検出したあらゆるデータに対するluhnチェックの実行など、これまでのマルウェアに見られたいくつかの機能は使用されていません。また、このマルウェアの進化の状況から、このマルウェアが一から開発されたらしいことが窺えます。これまでに検出されたマルウェアとわずかな類似点はあるものの、FindPOSはまったく新しいマルウェアであると私たちは確信しています。

 

このマルウェアは格段に巧妙なものではありませんが、多数の変種がAlinaBackoffなどのファミリーと同様にまん延しています。FindPOSは明らかにMicrosoft Windows POSベンダーに対する強力な脅威と見なすべきであり、確実な防御のための対策をとる必要があります。

 

対策として、あらゆるリモート アクセス サービス(LogMeIn、VNC、RDPなど)に対する2要素認証の構成、アンチウイルスの確実なインストールと更新、POSデバイスでのWeb参照や電子メール チェックなどの承認されていない機能の使用禁止などがあげられます。

 

パロアルトネットワークスのお客様はWildFireによって保護されます。WildFireはFindPOSのサンプルを自動的にマルウェアとして分類します。また、私たちが検出した、これら攻撃に関連するインジケータがPANDBおよびアンチマルウェア防御システムに追加されています。

 

付録

サンプル情報

バージョン2.0

バージョン2.1

バージョン5.57

バージョン5.80

バージョン5.90

バージョン6.0

バージョン6.02

バージョン6.03

バージョン6.04

YARAルール

import \"cuckoo\"

rule findpos
{
	meta:
		description = \"FindPOS is a newly discovered POS family.\"
		category = \"Point of Sale\"
		author = \"Josh Grunzweig\"

	strings:
		$s1 = \"oprat=2&uid=%I64u&uinfo=%s&win=%d.%d&vers=%s\" nocase wide ascii

		$pdb1 = \"H:\\\\Work\\\\Current\\\\FindStr\\\\Release\\\\FindStr.pdb\" nocase wide ascii
		$pdb2 = \"H:\\\\Work\\\\FindStrX\\\\Release\\\\FindStr.pdb\" nocase wide ascii
    		$pdb3 = \"H:\\\\Work\\\\Current\\\\KeyLogger\\\\Release\\\\KeyLogger.pdb\" nocase wide ascii

	condition:
		any of ($s*) or
		any of ($pdb*) or
        (
          cuckoo.sync.mutex(/WIN_[a-fA-F0-9]{16}/) and
          cuckoo.registry.key_access(/\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run/) and
          (
              cuckoo.filesystem.file_access(/C\\:\\\\WINDOWS\\\\System32\\\\\\w{8}\\.exe/) or
              cuckoo.filesystem.file_access(/C\\:\\\\Documents\\ and\\ Settings\\\\[^\\\\]+\\\\\\w{8}\\.exe/)
          )
        )
}