Ivanti Connect Secureの脆弱性を起点とした侵害で確認されたマルウェア
以前のJPCERT/CC Eyesで、Ivanti Connect Secureの脆弱性を利用して設置されたマルウェアSPAWNCHIMERAやDslogdRATについて紹介しましたが、JPCERT/CCでは、現在まで継続してIvanti Connect Secureの脆弱性を悪用する攻撃活動を確認しています。今回は、2024年12月から2025年7月現在までCVE-2025-0282やCVE-2025-22457を悪用する攻撃者が使用した以下のマルウェア、ツール、攻撃者が組織内ネットワークに侵入した際に使用する攻撃手法について解説します。
- MDifyLoaderとCobalt Strike Beacon
- vshell
- Fscan
MDifyLoaderとCobalt Strike Beacon
Cobalt Strikeの実行までの流れを図1に示します。初めに設定されたタスクなどから正規ファイルが動作し、ローダー(以下、MDifyLoaderという。)がDLLサイドローディングによって実行されます。MDifyLoaderは暗号化されたデータファイルを読み込み、Cobalt Strike Beaconをデコード後、メモリ上で実行します。
MDifyLoaderはオープンソースのlibPeConv[1]をもとに作成されたローダーです。データファイルの復号においてはRC4が使用され、RC4の鍵は実行ファイルのMD5ハッシュ値を使用します。この方法により実行ファイル、ローダー、データファイルの3つがそろっていないと動作しないため、分析を妨害する目的などが考えられます。なお、使用された正規ファイルにはJava RMI コンパイラのrmic.exeやpush_detect.exeなどが使用された事例を確認しています。
MDifyLoaderの各関数内においては、図2に示すようなジャンクコードが無数に挿入されていました。ジャンクコードは意味のほとんどない関数の呼び出しや変数の参照を組み合わせて挿入されており、相対アドレスの値がコード内に含まれる点や関数の返り値の値を参照するため、ジャンクコードを機械的に判別することが難しく、難読化解除を妨害する工夫が見受けられました。
通常、Cobalt Strike Beaconはコンフィグデータを検体内部に持っており、1バイトのXOR鍵を使用して実行時にデコードされ参照されますが、攻撃者が使用するCobalt Strike Beaconではコンフィグデータのデコード方式にRC4が使用され、そのRC4鍵は"google"としてBeacon内にハードコードされていました。その追加されたRC4のコードを図3に示します。また、設定されているコンフィグの要素数からCobalt StrikeのVersion 4.5であることを確認しています。なお、BeaconのNameフィールドにNewBeacon.dllと記載があり、攻撃者によって付けられた本Beaconの名称と考えられます。
vshellの使用
vshellはGitHubで公開されていたGo言語で書かれたマルチプラットフォーム環境で動作するRATです(本ブログ執筆時点では、対象のGitHubレポジトリは公開されていません)。攻撃者は、Windows実行ファイルのvshell version 4.6.0を使用する事例を確認しています。使用されたvshellの特徴として実行時に中国語環境かどうかをチェックする機能が含まれており、そのコードの一部を図4に示します。攻撃者はvshellの実行に何度も失敗しており、そのたびに新しいvshellを設置、実行を試みた痕跡が確認されました。原因としては、内部テスト用に使用していた言語確認機能をそのまま使ってしまった可能性が考えられます。
Fscan
Fscan[2]はオープンソースのGo言語で書かれたネットワークスキャンツールです。攻撃者はローダーを介してFscanを実行します。Fscan実行までの流れを図5に示します。Fscanの実行には正規のpython.exeが悪用されています。DLLサイドローディングで悪意のあるpython311.dllをロードさせ、エンコードされたFscanであるk.binを読み込み、デコード後、メモリ上で実行されます。なお、python311.dllはオープンソースのFilelessRemotePE[3]をもとに作成されており、Fscan本体の復号には内部にハードコードされている"99999999"を鍵としてRC4を使用し、デコードします。
組織内ネットワークに侵入後の攻撃活動
以降では組織内ネットワークに侵入した攻撃者が使用した横展開方法や永続化、防衛回避手法などについて解説します。
横展開(Lateral Movement)
攻撃者は内部ネットワークへの侵入後、ADサーバーに対してブルートフォース攻撃などを行い認証情報の取得を試みます。また、内部ネットワークに対しネットワークスキャンを行いFTPサーバーやMSSQLサーバー、SSHサーバーに対してもブルートフォース攻撃を行います。さらに、SMBの脆弱性であるMS17-010を悪用して、脆弱性が未修整のホストに侵入します。これらの活動により取得した資格情報などを用いてRDPやSMBを経由して他のシステムへ横展開し、マルウェアを設置します。
永続化(Persistence)
攻撃者は新たなドメインアカウントを作成し、これを既存の各グループに登録することで取得していた認証情報が失効した場合でも再侵入することが可能なアカウントを確保しました。このようなアカウントは、通常の運用と見分けがつきにくく、長期間にわたり内部ネットワークへのアクセスを維持することが可能となります。加えて、マルウェアの永続化方法として、攻撃者はマルウェアをサービスやタスクスケジューラとして登録することで、システム起動時や特定のイベントトリガーにおいてマルウェアが実行されるよう設定しました。
防衛回避(Defense Evasion)
Windows環境において使用されるマルウェアは正規ファイルを使ったローダーを介して実行することでセキュリティ製品による検知や監視の回避を狙っていると考えられます。なお、FilelessRemotePEをもとに作成されているFscanのローダーには、FilelessRemotePEの機能であるNtdll.dllへのETW Bypass機能があるため、EDRなどの検知回避を狙っていると考えられます。
おわりに
これらの攻撃は2024年12月から現在まで続いており、Ivanti Connect SecureなどのVPN機器を狙った攻撃は今後も継続して行われることが予想されます。なお、Appendixにマルウェアのハッシュ値、通信先、Cobalt Strikeのコンフィグ、vshellのコンフィグなどをそれぞれ記載していますのでご確認ください。
インシデントレスポンスグループ 増渕 維摩、喜野 孝太、亀井 智矢
参考情報
[1] libPeConv
https://github.com/hasherezade/libpeconv
[2] Fscan
https://github.com/shadow1ng/Fscan
[3] FilelessRemotePE
https://github.com/ASkyeye/FilelessRemotePE
Appendix A:MITRE ATT&CK
表1: 攻撃活動におけるATT&CKマッピング
戦術(Tactic) | テクニックID | テクニック名 | 内容 |
---|---|---|---|
Initial Access | T1133 | External Remote Services | VPN機器の脆弱性を悪用して侵入 |
Execution | T1053.005 | Scheduled Task/Job: Scheduled Task | スケジュールタスク経由でマルウェアを実行 |
T1136.002 | Create Account: Domain Account | 永続化のために新たなドメインアカウントを作成 | |
T1098 | Account Manipulation | 作成したアカウントを各グループに追加し、持続的なアクセスを確保 | |
T1543.003 | Create or Modify System Process: Windows Service | マルウェアをWindowsサービスとして登録し、自動実行の設定 | |
T1053.005 | Scheduled Task | タスクスケジューラを用いてマルウェアを定期的またはトリガー条件で再実行させる | |
Privilege Escalation | T1543.003 | Create or Modify System Process: Windows Service | マルウェアをWindowsサービスとして登録し、自動実行の設定 |
Defense Evasion | T1036 | Masquerading | マルウェアを正規のファイルや名称に偽装し、異常な挙動を隠蔽 |
T1070.004 | File Deletion | 攻撃の痕跡を隠すために、使用したマルウェアやツールを削除 | |
T1140 | Deobfuscate/Decode Files or Information | 各ローダーによる難読化や復号テクニックの使用 | |
T1562.001 | Impair Defenses: Disable or Modify Tools | Fscanのローダーによるntd.dllへのパッチによるETWの無効化 | |
Credential Access | T1110.001 | Password Guessing | ADサーバーやFTP、MSSQL、SSHに対してブルートフォース攻撃を実施し、認証情報を取得 |
Discovery | T1087 | Account Discovery | アカウント情報を収集 |
Lateral Movement | T1210 | Exploitation for Lateral Movement | SMBのMS17-010脆弱性を悪用して、他のホストに横展開を実施 |
T1021.001 | Remote Services: Remote Desktop Protocol | 取得した資格情報を用いてRDP経由で他ホストへ横展開 | |
T1021.002 | Remote Services: SMB/Windows Admin Shares | SMB共有を通じて侵害を拡大 | |
Command and Control | T1573 | Encrypted Channel | TLSやカスタム暗号化プロトコルを利用し、C2通信を暗号化 |
Appendix B:マルウェア
表2: マルウェア
Malware | Filename | SHA256 Hash |
---|---|---|
Python(Legitimate) | python.exe | 0cbf71efa09ec4ce62d95c1448553314728ed5850720c8ad40352bfbb39be99a |
Fscan Loader | python311.dll | 699290a753f35ae3f05a7ea1984d95f6e6f21971a146714fca5708896e5e6218 |
Fscan | k.bin | cff2afc651a9cba84a11a4e275cc9ec49e29af5fd968352d40aeee07fb00445e |
Java RMI Compiler(Legitimate) | rmic.exe | a747be292339eae693b7c26cac0d33851cba31140fd0883371cc8de978583dbe |
push_detect(Legitimate) | push_detect.exe | f12250a43926dba46dcfb6145b7f1a524c0eead82bd1a8682307d1f2f1f1e66f |
MDifyLoader | jli.dll | 45ecb7b23b328ab762d8519e69738a20eb0cd5618a10abb2c57a9c72582aa7e7 |
MDifyLoader | Microsoft.WindowsAppRuntime.Bootstrap.dll | 9e91862b585fc4d213e9aaadd571435c1a007d326bd9b07b72dbecb77d1a27ac |
Cobalt Strike version 4.5 | update.dat | 09087fc4f8c261a810479bb574b0ecbf8173d4a8365a73113025bd506b95e3d7 |
Cobalt Strike version 4.5 | config.ini | 1652ab693512cd4f26cc73e253b5b9b0e342ac70aa767524264fef08706d0e69 |
vshell | ws_windows_amd2.exe | 48f3915fb8d8ad39dc5267894a950efc863bcc660f1654187b3d77a302fd040f |
vshell | ws_windows_amd64.exe | 54350d677174269b4dc25b0ccfb0029d6aeac5abbbc8d39eb880c9fd95691125 |
vshell | ws.exe | 85f9819118af284e6b00ce49fb0c85ff0c0b9d7a0589e1bb56a275ed91314965 |
Appendix C:通信先
- 172.237.6[.]207:80
- proxy.objectlook[.]com:80
- api.openedr.eu[.]org:443
- community.openedr.eu[.]org:443
- query.datasophos[.]com:443
Appendix D:各コンフィグ情報
- vshellのコンフィグ
{"server":"proxy.objectlook[.]com:80","type":"ws","vkey":"safeshell","proxy":"http[:]//10.71.30[.]140:8080","salt":"safeshell","l":false,"e":false}
- Cobalt Strikeのコンフィグ
BeaconType - HTTPS Port - 443 SleepTime - 97352 MaxGetSize - 2105202 Jitter - 48 MaxDNS - Not Found PublicKey_MD5 - e880c4268fb48aebc5510e02f49d3bce C2Server - api.openedr.eu[.]org,/avatar/js/flashdetect.min.js,community.openedr.eu[.]org,/avatar/js/utm5.min.js UserAgent - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 HttpPostUri - /Destroy/stylesheets/color_definitions_base Malleable_C2_Instructions - Remove 2025 bytes from the end Remove 6017 bytes from the beginning NetBIOS decode 'a' XOR mask w/ random key HttpGet_Metadata - ConstHeaders Accept: application/json, application/xml, text/html Accept-Language: zh-hk Accept-Encoding: br, compress Metadata mask base64url prepend "secure_id_4427KV8TXLHDJ9YJAM5XRIXHI12=" header "Cookie" HttpPost_Metadata - ConstHeaders Accept: text/html, application/json, image/* Accept-Language: ar-ma Accept-Encoding: gzip, * SessionId mask base64url parameter "_SFUYPJNK" Output mask netbiosu print PipeName - Not Found DNS_Idle - Not Found DNS_Sleep - Not Found SSH_Host - Not Found SSH_Port - Not Found SSH_Username - Not Found SSH_Password_Plaintext - Not Found SSH_Password_Pubkey - Not Found SSH_Banner - HttpGet_Verb - GET HttpPost_Verb - POST HttpPostChunk - 0 Spawnto_x86 - %windir%\syswow64\svchost.exe -k wksvc Spawnto_x64 - %windir%\sysnative\SearchProtocolHost.exe CryptoScheme - 0 Proxy_Config - Not Found Proxy_User - Not Found Proxy_Password - Not Found Proxy_Behavior - Use IE settings Watermark_Hash - MYhXSMGVvcr7PtOTMdABvA== Watermark - 666666 bStageCleanup - True bCFGCaution - False KillDate - 0 bProcInject_StartRWX - False bProcInject_UseRWX - False bProcInject_MinAllocSize - 6771 ProcInject_PrependAppend_x86 - b'\x90\x90\x90f\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1fD\x00\x00PXf\x90PX\x0f\x1f\x00\x0f\x1fD\x00\x00f\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f\x00PXPX\x0f\x1f\x80\x00\x00\x00\x00f\x90\x0f\x1f\x00\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f\x84\x00\x00\x00\x00\x00' b'f\x0f\x1fD\x00\x00\x0f\x1f\x80\x00\x00\x00\x00\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f\x00\x90\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f\x80\x00\x00\x00\x00f\x0f\x1f\x84\x00\x00\x00\x00\x00' ProcInject_PrependAppend_x64 - b'\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f\x80\x00\x00\x00\x00f\x90PX\x0f\x1f@\x00\x0f\x1f\x80\x00\x00\x00\x00\x0f\x1f@\x00f\x0f\x1f\x84\x00\x00\x00\x00\x00f\x0f\x1f\x84\x00\x00\x00\x00\x00\x90PX\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f@\x00f\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f\x00\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f@\x00f\x0f\x1fD\x00\x00f\x0f\x1f\x84\x00\x00\x00\x00\x00' b'\x90\x0f\x1f\x00PX\x90PX\x0f\x1f@\x00f\x0f\x1f\x84\x00\x00\x00\x00\x00PX\x0f\x1f\x84\x00\x00\x00\x00\x00f\x90PX\x0f\x1fD\x00\x00\x0f\x1fD\x00\x00' ProcInject_Execute - ntdll:RtlUserThreadStart CreateThread NtQueueApcThread-s CreateRemoteThread RtlCreateUserThread ProcInject_AllocationMethod - NtMapViewOfSection bUsesCookies - True HostHeader - headersToRemove - Not Found DNS_Beaconing - Not Found DNS_get_TypeA - Not Found DNS_get_TypeAAAA - Not Found DNS_get_TypeTXT - Not Found DNS_put_metadata - Not Found DNS_put_output - Not Found DNS_resolver - Not Found DNS_strategy - failover DNS_strategy_rotate_seconds - -1 DNS_strategy_fail_x - 100 DNS_strategy_fail_seconds - -1 Retry_Max_Attempts - 0 Retry_Increase_Attempts - 0 Retry_Duration - 0
- Cobalt Strikeのコンフィグ
BeaconType - HTTPS Port - 443 SleepTime - 92318 MaxGetSize - 1408170 Jitter - 48 MaxDNS - Not Found PublicKey_MD5 - 492cdc5bc3d8cc5e6440a0da246f6684 C2Server - query.datasophos[.]com,/Enable/v5.10/VPGH7WQQPR UserAgent - Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36 HttpPostUri - /Enable/v8.20/STE7U5WILZII Malleable_C2_Instructions - Remove 7449 bytes from the end Remove 2614 bytes from the beginning Base64 URL-safe decode XOR mask w/ random key HttpGet_Metadata - ConstHeaders Accept: application/xml, application/xhtml+xml, image/* Accept-Language: fr-lu Accept-Encoding: gzip, br Metadata mask netbios prepend "affiliate_id_69W8Y3G469RVG2W2=" header "Cookie" HttpPost_Metadata - ConstHeaders Accept: application/xhtml+xml, image/*, text/html Accept-Language: zh-tw Accept-Encoding: compress, gzip SessionId mask netbios parameter "_TXLXHKQC" Output mask netbiosu print PipeName - Not Found DNS_Idle - Not Found DNS_Sleep - Not Found SSH_Host - Not Found SSH_Port - Not Found SSH_Username - Not Found SSH_Password_Plaintext - Not Found SSH_Password_Pubkey - Not Found SSH_Banner - HttpGet_Verb - GET HttpPost_Verb - POST HttpPostChunk - 0 Spawnto_x86 - %windir%\syswow64\w32tm.exe Spawnto_x64 - %windir%\sysnative\WUAUCLT.exe CryptoScheme - 0 Proxy_Config - Not Found Proxy_User - Not Found Proxy_Password - Not Found Proxy_Behavior - Use IE settings Watermark_Hash - MYhXSMGVvcr7PtOTMdABvA== Watermark - 666666 bStageCleanup - True bCFGCaution - False KillDate - 0 bProcInject_StartRWX - False bProcInject_UseRWX - False bProcInject_MinAllocSize - 6344 ProcInject_PrependAppend_x86 - b'PX\x0f\x1f\x84\x00\x00\x00\x00\x00f\x0f\x1fD\x00\x00PXf\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f\x80\x00\x00\x00\x00\x0f\x1f\x84\x00\x00\x00\x00\x00\x90f\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f\x80\x00\x00\x00\x00\x90\x90\x90\x0f\x1f\x80\x00\x00\x00\x00\x90' b'f\x0f\x1fD\x00\x00\x0f\x1f@\x00\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f@\x00' ProcInject_PrependAppend_x64 - b'\x0f\x1f\x00\x90PX\x0f\x1f\x80\x00\x00\x00\x00f\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f\x00\x0f\x1f\x80\x00\x00\x00\x00\x0f\x1f\x00\x90\x90' b'\x0f\x1f\x00PXf\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1fD\x00\x00f\x0f\x1fD\x00\x00' ProcInject_Execute - ntdll:RtlUserThreadStart CreateThread NtQueueApcThread-s CreateRemoteThread RtlCreateUserThread ProcInject_AllocationMethod - VirtualAllocEx bUsesCookies - True HostHeader - headersToRemove - Not Found DNS_Beaconing - Not Found DNS_get_TypeA - Not Found DNS_get_TypeAAAA - Not Found DNS_get_TypeTXT - Not Found DNS_put_metadata - Not Found DNS_put_output - Not Found DNS_resolver - Not Found DNS_strategy - round-robin DNS_strategy_rotate_seconds - -1 DNS_strategy_fail_x - -1 DNS_strategy_fail_seconds - -1 Retry_Max_Attempts - 0 Retry_Increase_Attempts - 0 Retry_Duration - 0