@trailofbits/vsix-audit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +281 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +703 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/scanner/batch.d.ts +12 -0
- package/dist/scanner/batch.d.ts.map +1 -0
- package/dist/scanner/batch.js +104 -0
- package/dist/scanner/batch.js.map +1 -0
- package/dist/scanner/bundler.d.ts +35 -0
- package/dist/scanner/bundler.d.ts.map +1 -0
- package/dist/scanner/bundler.js +120 -0
- package/dist/scanner/bundler.js.map +1 -0
- package/dist/scanner/cache.d.ts +45 -0
- package/dist/scanner/cache.d.ts.map +1 -0
- package/dist/scanner/cache.js +153 -0
- package/dist/scanner/cache.js.map +1 -0
- package/dist/scanner/cache.test.d.ts +2 -0
- package/dist/scanner/cache.test.d.ts.map +1 -0
- package/dist/scanner/cache.test.js +149 -0
- package/dist/scanner/cache.test.js.map +1 -0
- package/dist/scanner/capabilities.d.ts +29 -0
- package/dist/scanner/capabilities.d.ts.map +1 -0
- package/dist/scanner/capabilities.js +217 -0
- package/dist/scanner/capabilities.js.map +1 -0
- package/dist/scanner/checks/ast.d.ts +3 -0
- package/dist/scanner/checks/ast.d.ts.map +1 -0
- package/dist/scanner/checks/ast.js +469 -0
- package/dist/scanner/checks/ast.js.map +1 -0
- package/dist/scanner/checks/ast.test.d.ts +2 -0
- package/dist/scanner/checks/ast.test.d.ts.map +1 -0
- package/dist/scanner/checks/ast.test.js +389 -0
- package/dist/scanner/checks/ast.test.js.map +1 -0
- package/dist/scanner/checks/behavioral.d.ts +3 -0
- package/dist/scanner/checks/behavioral.d.ts.map +1 -0
- package/dist/scanner/checks/behavioral.js +367 -0
- package/dist/scanner/checks/behavioral.js.map +1 -0
- package/dist/scanner/checks/blocklist.d.ts +3 -0
- package/dist/scanner/checks/blocklist.d.ts.map +1 -0
- package/dist/scanner/checks/blocklist.js +32 -0
- package/dist/scanner/checks/blocklist.js.map +1 -0
- package/dist/scanner/checks/blocklist.test.d.ts +2 -0
- package/dist/scanner/checks/blocklist.test.d.ts.map +1 -0
- package/dist/scanner/checks/blocklist.test.js +74 -0
- package/dist/scanner/checks/blocklist.test.js.map +1 -0
- package/dist/scanner/checks/chains.d.ts +35 -0
- package/dist/scanner/checks/chains.d.ts.map +1 -0
- package/dist/scanner/checks/chains.js +505 -0
- package/dist/scanner/checks/chains.js.map +1 -0
- package/dist/scanner/checks/chains.test.d.ts +2 -0
- package/dist/scanner/checks/chains.test.d.ts.map +1 -0
- package/dist/scanner/checks/chains.test.js +250 -0
- package/dist/scanner/checks/chains.test.js.map +1 -0
- package/dist/scanner/checks/dataflow.d.ts +3 -0
- package/dist/scanner/checks/dataflow.d.ts.map +1 -0
- package/dist/scanner/checks/dataflow.js +316 -0
- package/dist/scanner/checks/dataflow.js.map +1 -0
- package/dist/scanner/checks/dependencies.d.ts +13 -0
- package/dist/scanner/checks/dependencies.d.ts.map +1 -0
- package/dist/scanner/checks/dependencies.js +225 -0
- package/dist/scanner/checks/dependencies.js.map +1 -0
- package/dist/scanner/checks/dependencies.test.d.ts +2 -0
- package/dist/scanner/checks/dependencies.test.d.ts.map +1 -0
- package/dist/scanner/checks/dependencies.test.js +248 -0
- package/dist/scanner/checks/dependencies.test.js.map +1 -0
- package/dist/scanner/checks/finding-quality.test.d.ts +8 -0
- package/dist/scanner/checks/finding-quality.test.d.ts.map +1 -0
- package/dist/scanner/checks/finding-quality.test.js +164 -0
- package/dist/scanner/checks/finding-quality.test.js.map +1 -0
- package/dist/scanner/checks/ioc.d.ts +20 -0
- package/dist/scanner/checks/ioc.d.ts.map +1 -0
- package/dist/scanner/checks/ioc.js +234 -0
- package/dist/scanner/checks/ioc.js.map +1 -0
- package/dist/scanner/checks/ioc.test.d.ts +2 -0
- package/dist/scanner/checks/ioc.test.d.ts.map +1 -0
- package/dist/scanner/checks/ioc.test.js +298 -0
- package/dist/scanner/checks/ioc.test.js.map +1 -0
- package/dist/scanner/checks/manifest.d.ts +6 -0
- package/dist/scanner/checks/manifest.d.ts.map +1 -0
- package/dist/scanner/checks/manifest.js +123 -0
- package/dist/scanner/checks/manifest.js.map +1 -0
- package/dist/scanner/checks/manifest.test.d.ts +2 -0
- package/dist/scanner/checks/manifest.test.d.ts.map +1 -0
- package/dist/scanner/checks/manifest.test.js +108 -0
- package/dist/scanner/checks/manifest.test.js.map +1 -0
- package/dist/scanner/checks/obfuscation.d.ts +3 -0
- package/dist/scanner/checks/obfuscation.d.ts.map +1 -0
- package/dist/scanner/checks/obfuscation.js +432 -0
- package/dist/scanner/checks/obfuscation.js.map +1 -0
- package/dist/scanner/checks/obfuscation.test.d.ts +2 -0
- package/dist/scanner/checks/obfuscation.test.d.ts.map +1 -0
- package/dist/scanner/checks/obfuscation.test.js +399 -0
- package/dist/scanner/checks/obfuscation.test.js.map +1 -0
- package/dist/scanner/checks/package.d.ts +17 -0
- package/dist/scanner/checks/package.d.ts.map +1 -0
- package/dist/scanner/checks/package.js +422 -0
- package/dist/scanner/checks/package.js.map +1 -0
- package/dist/scanner/checks/package.test.d.ts +2 -0
- package/dist/scanner/checks/package.test.d.ts.map +1 -0
- package/dist/scanner/checks/package.test.js +518 -0
- package/dist/scanner/checks/package.test.js.map +1 -0
- package/dist/scanner/checks/patterns.d.ts +5 -0
- package/dist/scanner/checks/patterns.d.ts.map +1 -0
- package/dist/scanner/checks/patterns.js +251 -0
- package/dist/scanner/checks/patterns.js.map +1 -0
- package/dist/scanner/checks/patterns.test.d.ts +2 -0
- package/dist/scanner/checks/patterns.test.d.ts.map +1 -0
- package/dist/scanner/checks/patterns.test.js +147 -0
- package/dist/scanner/checks/patterns.test.js.map +1 -0
- package/dist/scanner/checks/unicode.d.ts +3 -0
- package/dist/scanner/checks/unicode.d.ts.map +1 -0
- package/dist/scanner/checks/unicode.js +247 -0
- package/dist/scanner/checks/unicode.js.map +1 -0
- package/dist/scanner/checks/unicode.test.d.ts +2 -0
- package/dist/scanner/checks/unicode.test.d.ts.map +1 -0
- package/dist/scanner/checks/unicode.test.js +202 -0
- package/dist/scanner/checks/unicode.test.js.map +1 -0
- package/dist/scanner/checks/yara.d.ts +23 -0
- package/dist/scanner/checks/yara.d.ts.map +1 -0
- package/dist/scanner/checks/yara.js +349 -0
- package/dist/scanner/checks/yara.js.map +1 -0
- package/dist/scanner/checks/yara.test.d.ts +2 -0
- package/dist/scanner/checks/yara.test.d.ts.map +1 -0
- package/dist/scanner/checks/yara.test.js +126 -0
- package/dist/scanner/checks/yara.test.js.map +1 -0
- package/dist/scanner/constants.d.ts +18 -0
- package/dist/scanner/constants.d.ts.map +1 -0
- package/dist/scanner/constants.js +37 -0
- package/dist/scanner/constants.js.map +1 -0
- package/dist/scanner/detection-coverage.test.d.ts +2 -0
- package/dist/scanner/detection-coverage.test.d.ts.map +1 -0
- package/dist/scanner/detection-coverage.test.js +216 -0
- package/dist/scanner/detection-coverage.test.js.map +1 -0
- package/dist/scanner/download.d.ts +76 -0
- package/dist/scanner/download.d.ts.map +1 -0
- package/dist/scanner/download.js +339 -0
- package/dist/scanner/download.js.map +1 -0
- package/dist/scanner/download.test.d.ts +2 -0
- package/dist/scanner/download.test.d.ts.map +1 -0
- package/dist/scanner/download.test.js +149 -0
- package/dist/scanner/download.test.js.map +1 -0
- package/dist/scanner/index.d.ts +8 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +167 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/index.test.d.ts +2 -0
- package/dist/scanner/index.test.d.ts.map +1 -0
- package/dist/scanner/index.test.js +71 -0
- package/dist/scanner/index.test.js.map +1 -0
- package/dist/scanner/loaders/zoo.d.ts +3 -0
- package/dist/scanner/loaders/zoo.d.ts.map +1 -0
- package/dist/scanner/loaders/zoo.js +112 -0
- package/dist/scanner/loaders/zoo.js.map +1 -0
- package/dist/scanner/types.d.ts +118 -0
- package/dist/scanner/types.d.ts.map +1 -0
- package/dist/scanner/types.js +2 -0
- package/dist/scanner/types.js.map +1 -0
- package/dist/scanner/utils.d.ts +14 -0
- package/dist/scanner/utils.d.ts.map +1 -0
- package/dist/scanner/utils.js +25 -0
- package/dist/scanner/utils.js.map +1 -0
- package/dist/scanner/vsix.d.ts +6 -0
- package/dist/scanner/vsix.d.ts.map +1 -0
- package/dist/scanner/vsix.js +213 -0
- package/dist/scanner/vsix.js.map +1 -0
- package/dist/scanner/vsix.test.d.ts +2 -0
- package/dist/scanner/vsix.test.d.ts.map +1 -0
- package/dist/scanner/vsix.test.js +355 -0
- package/dist/scanner/vsix.test.js.map +1 -0
- package/package.json +60 -0
- package/zoo/blocklist/extensions.json +201 -0
- package/zoo/iocs/blockchain-extensions.txt +21 -0
- package/zoo/iocs/c2-domains.txt +50 -0
- package/zoo/iocs/c2-ips.txt +24 -0
- package/zoo/iocs/hashes.txt +47 -0
- package/zoo/iocs/malicious-npm.txt +85 -0
- package/zoo/iocs/wallets.txt +18 -0
- package/zoo/signatures/yara/README.md +46 -0
- package/zoo/signatures/yara/blockchain_c2.yar +48 -0
- package/zoo/signatures/yara/code_execution.yar +165 -0
- package/zoo/signatures/yara/credential_harvesting.yar +116 -0
- package/zoo/signatures/yara/crypto_wallet_targeting.yar +92 -0
- package/zoo/signatures/yara/data_exfiltration.yar +207 -0
- package/zoo/signatures/yara/google_calendar_c2.yar +187 -0
- package/zoo/signatures/yara/messaging_c2.yar +103 -0
- package/zoo/signatures/yara/multi_stage_attacks.yar +331 -0
- package/zoo/signatures/yara/obfuscation_patterns.yar +208 -0
- package/zoo/signatures/yara/powershell_attacks.yar +116 -0
- package/zoo/signatures/yara/rat_capabilities.yar +243 -0
- package/zoo/signatures/yara/self_propagation.yar +239 -0
- package/zoo/signatures/yara/unicode_stealth.yar +48 -0
- package/zoo/signatures/yara/websocket_c2.yar +83 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/*
|
|
2
|
+
GlassWorm RAT Capabilities Detection
|
|
3
|
+
Detects Remote Access Trojan patterns including SOCKS proxy, VNC, and remote execution
|
|
4
|
+
Based on GlassWorm RAT capabilities for persistent access
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
rule RAT_JS_GlassWorm_SOCKS_Proxy_Jan25 {
|
|
8
|
+
meta:
|
|
9
|
+
description = "Detects GlassWorm-style SOCKS proxy server deployment for network tunneling and pivoting"
|
|
10
|
+
severity = "high"
|
|
11
|
+
score = "85"
|
|
12
|
+
author = "vsix-audit"
|
|
13
|
+
date = "2025-01-29"
|
|
14
|
+
reference = "https://www.koi.security/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace"
|
|
15
|
+
|
|
16
|
+
strings:
|
|
17
|
+
// SOCKS proxy patterns
|
|
18
|
+
$socks_proxy = "socks" nocase ascii wide
|
|
19
|
+
$socks_server = "socksServer" ascii wide
|
|
20
|
+
$socks_proxy_server = "socksProxyServer" ascii wide
|
|
21
|
+
$socks5 = "socks5" nocase ascii wide
|
|
22
|
+
$socks4 = "socks4" nocase ascii wide
|
|
23
|
+
|
|
24
|
+
// Network server creation
|
|
25
|
+
$create_server = "createServer" ascii wide
|
|
26
|
+
$net_create_server = "net.createServer" ascii wide
|
|
27
|
+
$http_create_server = "http.createServer" ascii wide
|
|
28
|
+
$https_create_server = "https.createServer" ascii wide
|
|
29
|
+
|
|
30
|
+
// Proxy configuration
|
|
31
|
+
$proxy_config = "proxyConfig" ascii wide
|
|
32
|
+
$proxy_server = "proxyServer" ascii wide
|
|
33
|
+
$proxy_port = "proxyPort" ascii wide
|
|
34
|
+
$proxy_host = "proxyHost" ascii wide
|
|
35
|
+
|
|
36
|
+
// Network binding
|
|
37
|
+
$listen = "listen" ascii wide
|
|
38
|
+
$bind = "bind" ascii wide
|
|
39
|
+
$port = "port" ascii wide
|
|
40
|
+
$host = "host" ascii wide
|
|
41
|
+
|
|
42
|
+
// SOCKS protocol
|
|
43
|
+
$socks_auth = "socksAuth" ascii wide
|
|
44
|
+
$socks_connect = "socksConnect" ascii wide
|
|
45
|
+
$socks_relay = "socksRelay" ascii wide
|
|
46
|
+
|
|
47
|
+
condition:
|
|
48
|
+
// High confidence: SOCKS proxy + server creation + network binding
|
|
49
|
+
(any of ($socks_proxy, $socks_server, $socks_proxy_server, $socks5, $socks4)) and
|
|
50
|
+
(any of ($create_server, $net_create_server, $http_create_server, $https_create_server)) and
|
|
51
|
+
(any of ($listen, $bind, $port, $host, $proxy_config, $proxy_server, $proxy_port, $proxy_host, $socks_auth, $socks_connect, $socks_relay))
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
rule RAT_JS_GlassWorm_VNC_Install_Jan25 {
|
|
55
|
+
meta:
|
|
56
|
+
description = "Detects GlassWorm-style VNC or HVNC installation for remote desktop access and control"
|
|
57
|
+
severity = "high"
|
|
58
|
+
score = "90"
|
|
59
|
+
author = "vsix-audit"
|
|
60
|
+
date = "2025-01-29"
|
|
61
|
+
reference = "https://www.koi.security/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace"
|
|
62
|
+
|
|
63
|
+
strings:
|
|
64
|
+
// VNC patterns
|
|
65
|
+
$vnc = "vnc" nocase ascii wide
|
|
66
|
+
$hvnc = "hvnc" nocase ascii wide
|
|
67
|
+
$tightvnc = "tightvnc" nocase ascii wide
|
|
68
|
+
$ultravnc = "ultravnc" nocase ascii wide
|
|
69
|
+
$realvnc = "realvnc" nocase ascii wide
|
|
70
|
+
|
|
71
|
+
// VNC installation
|
|
72
|
+
$vnc_install = "vncInstall" ascii wide
|
|
73
|
+
$vnc_setup = "vncSetup" ascii wide
|
|
74
|
+
$vnc_configure = "vncConfigure" ascii wide
|
|
75
|
+
$vnc_start = "vncStart" ascii wide
|
|
76
|
+
|
|
77
|
+
// VNC server
|
|
78
|
+
$vnc_server = "vncServer" ascii wide
|
|
79
|
+
$vnc_daemon = "vncDaemon" ascii wide
|
|
80
|
+
$vnc_service = "vncService" ascii wide
|
|
81
|
+
|
|
82
|
+
// Remote desktop access
|
|
83
|
+
$remote_desktop = "remoteDesktop" ascii wide
|
|
84
|
+
$desktop_sharing = "desktopSharing" ascii wide
|
|
85
|
+
$screen_sharing = "screenSharing" ascii wide
|
|
86
|
+
$remote_access = "remoteAccess" ascii wide
|
|
87
|
+
|
|
88
|
+
// VNC configuration
|
|
89
|
+
$vnc_password = "vncPassword" ascii wide
|
|
90
|
+
$vnc_port = "vncPort" ascii wide
|
|
91
|
+
$vnc_display = "vncDisplay" ascii wide
|
|
92
|
+
|
|
93
|
+
condition:
|
|
94
|
+
// High confidence: VNC installation + server setup + remote access
|
|
95
|
+
(any of ($vnc, $hvnc, $tightvnc, $ultravnc, $realvnc)) and
|
|
96
|
+
(any of ($vnc_install, $vnc_setup, $vnc_configure, $vnc_start, $vnc_server, $vnc_daemon, $vnc_service)) and
|
|
97
|
+
(any of ($remote_desktop, $desktop_sharing, $screen_sharing, $remote_access, $vnc_password, $vnc_port, $vnc_display))
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
rule RAT_JS_GlassWorm_Remote_Exec_Jan25 {
|
|
101
|
+
meta:
|
|
102
|
+
description = "Detects GlassWorm-style remote command execution infrastructure with network-triggered shell access"
|
|
103
|
+
severity = "critical"
|
|
104
|
+
score = "95"
|
|
105
|
+
author = "vsix-audit"
|
|
106
|
+
date = "2025-01-29"
|
|
107
|
+
reference = "https://www.koi.security/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace"
|
|
108
|
+
|
|
109
|
+
strings:
|
|
110
|
+
// Command execution patterns
|
|
111
|
+
$exec = "exec" ascii wide
|
|
112
|
+
$spawn = "spawn" ascii wide
|
|
113
|
+
$execFile = "execFile" ascii wide
|
|
114
|
+
$execSync = "execSync" ascii wide
|
|
115
|
+
|
|
116
|
+
// Child process creation
|
|
117
|
+
$child_process = "child_process" ascii wide
|
|
118
|
+
$fork = "fork" ascii wide
|
|
119
|
+
$spawn_process = "spawnProcess" ascii wide
|
|
120
|
+
|
|
121
|
+
// Remote command execution
|
|
122
|
+
$remote_exec = "remoteExec" ascii wide
|
|
123
|
+
$remote_command = "remoteCommand" ascii wide
|
|
124
|
+
$remote_shell = "remoteShell" ascii wide
|
|
125
|
+
$remote_cmd = "remoteCmd" ascii wide
|
|
126
|
+
|
|
127
|
+
// Command and control
|
|
128
|
+
$command_control = "commandControl" ascii wide
|
|
129
|
+
$cmd_control = "cmdControl" ascii wide
|
|
130
|
+
$shell_control = "shellControl" ascii wide
|
|
131
|
+
|
|
132
|
+
// Network command execution
|
|
133
|
+
$net_exec = "netExec" ascii wide
|
|
134
|
+
$socket_exec = "socketExec" ascii wide
|
|
135
|
+
$tcp_exec = "tcpExec" ascii wide
|
|
136
|
+
|
|
137
|
+
// Command parsing
|
|
138
|
+
$parse_command = "parseCommand" ascii wide
|
|
139
|
+
$execute_command = "executeCommand" ascii wide
|
|
140
|
+
$run_command = "runCommand" ascii wide
|
|
141
|
+
|
|
142
|
+
condition:
|
|
143
|
+
// Critical: Command execution + remote capabilities + network communication
|
|
144
|
+
(any of ($exec, $spawn, $execFile, $execSync, $child_process, $fork, $spawn_process)) and
|
|
145
|
+
(any of ($remote_exec, $remote_command, $remote_shell, $remote_cmd, $command_control, $cmd_control, $shell_control)) and
|
|
146
|
+
(any of ($net_exec, $socket_exec, $tcp_exec, $parse_command, $execute_command, $run_command))
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
rule RAT_JS_GlassWorm_Persistent_Backdoor_Jan25 {
|
|
150
|
+
meta:
|
|
151
|
+
description = "Detects GlassWorm-style persistent backdoor using registry, services, or scheduled tasks"
|
|
152
|
+
severity = "high"
|
|
153
|
+
score = "90"
|
|
154
|
+
author = "vsix-audit"
|
|
155
|
+
date = "2025-01-29"
|
|
156
|
+
reference = "https://www.koi.security/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace"
|
|
157
|
+
|
|
158
|
+
strings:
|
|
159
|
+
// Persistence mechanisms
|
|
160
|
+
$persistence = "persistence" ascii wide
|
|
161
|
+
$backdoor = "backdoor" ascii wide
|
|
162
|
+
$persistent = "persistent" ascii wide
|
|
163
|
+
$survive_reboot = "surviveReboot" ascii wide
|
|
164
|
+
|
|
165
|
+
// Registry persistence (Windows)
|
|
166
|
+
$reg_run = "regRun" ascii wide
|
|
167
|
+
$registry_run = "registryRun" ascii wide
|
|
168
|
+
$startup_key = "startupKey" ascii wide
|
|
169
|
+
$auto_start = "autoStart" ascii wide
|
|
170
|
+
|
|
171
|
+
// Service installation
|
|
172
|
+
$service_install = "serviceInstall" ascii wide
|
|
173
|
+
$service_create = "serviceCreate" ascii wide
|
|
174
|
+
$service_start = "serviceStart" ascii wide
|
|
175
|
+
$service_auto = "serviceAuto" ascii wide
|
|
176
|
+
|
|
177
|
+
// Scheduled tasks
|
|
178
|
+
$scheduled_task = "scheduledTask" ascii wide
|
|
179
|
+
$cron_job = "cronJob" ascii wide
|
|
180
|
+
$task_scheduler = "taskScheduler" ascii wide
|
|
181
|
+
|
|
182
|
+
// Startup folder
|
|
183
|
+
$startup_folder = "startupFolder" ascii wide
|
|
184
|
+
$startup_shortcut = "startupShortcut" ascii wide
|
|
185
|
+
$startup_link = "startupLink" ascii wide
|
|
186
|
+
|
|
187
|
+
// Hidden files
|
|
188
|
+
$hidden_file = "hiddenFile" ascii wide
|
|
189
|
+
$system_file = "systemFile" ascii wide
|
|
190
|
+
$temp_file = "tempFile" ascii wide
|
|
191
|
+
|
|
192
|
+
condition:
|
|
193
|
+
// High confidence: Persistence + registry/service manipulation + hidden files
|
|
194
|
+
(any of ($persistence, $backdoor, $persistent, $survive_reboot)) and
|
|
195
|
+
(any of ($reg_run, $registry_run, $startup_key, $auto_start, $service_install, $service_create, $service_start, $service_auto, $scheduled_task, $cron_job, $task_scheduler)) and
|
|
196
|
+
(any of ($startup_folder, $startup_shortcut, $startup_link, $hidden_file, $system_file, $temp_file))
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
rule RAT_JS_GlassWorm_Network_Recon_Jan25 {
|
|
200
|
+
meta:
|
|
201
|
+
description = "Detects GlassWorm-style network reconnaissance with port scanning and lateral movement capabilities"
|
|
202
|
+
severity = "medium"
|
|
203
|
+
score = "75"
|
|
204
|
+
author = "vsix-audit"
|
|
205
|
+
date = "2025-01-29"
|
|
206
|
+
reference = "https://www.koi.security/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace"
|
|
207
|
+
|
|
208
|
+
strings:
|
|
209
|
+
// Network scanning
|
|
210
|
+
$network_scan = "networkScan" ascii wide
|
|
211
|
+
$port_scan = "portScan" ascii wide
|
|
212
|
+
$host_scan = "hostScan" ascii wide
|
|
213
|
+
$network_discovery = "networkDiscovery" ascii wide
|
|
214
|
+
|
|
215
|
+
// Network enumeration
|
|
216
|
+
$enumerate_hosts = "enumerateHosts" ascii wide
|
|
217
|
+
$discover_hosts = "discoverHosts" ascii wide
|
|
218
|
+
$scan_network = "scanNetwork" ascii wide
|
|
219
|
+
$map_network = "mapNetwork" ascii wide
|
|
220
|
+
|
|
221
|
+
// Lateral movement
|
|
222
|
+
$lateral_movement = "lateralMovement" ascii wide
|
|
223
|
+
$pivot = "pivot" ascii wide
|
|
224
|
+
$jump_host = "jumpHost" ascii wide
|
|
225
|
+
$relay = "relay" ascii wide
|
|
226
|
+
|
|
227
|
+
// Network tools
|
|
228
|
+
$nmap = "nmap" ascii wide
|
|
229
|
+
$ping = "ping" ascii wide
|
|
230
|
+
$traceroute = "traceroute" ascii wide
|
|
231
|
+
$netstat = "netstat" ascii wide
|
|
232
|
+
|
|
233
|
+
// Network protocols
|
|
234
|
+
$tcp_scan = "tcpScan" ascii wide
|
|
235
|
+
$udp_scan = "udpScan" ascii wide
|
|
236
|
+
$icmp_scan = "icmpScan" ascii wide
|
|
237
|
+
|
|
238
|
+
condition:
|
|
239
|
+
// Detect network reconnaissance with scanning tools
|
|
240
|
+
(any of ($network_scan, $port_scan, $host_scan, $network_discovery, $enumerate_hosts, $discover_hosts, $scan_network, $map_network)) and
|
|
241
|
+
(any of ($lateral_movement, $pivot, $jump_host, $relay, $nmap, $ping, $traceroute, $netstat)) and
|
|
242
|
+
(any of ($tcp_scan, $udp_scan, $icmp_scan))
|
|
243
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/*
|
|
2
|
+
GlassWorm Self-Propagation Detection
|
|
3
|
+
Detects worm self-propagation patterns including automated publishing and credential reuse
|
|
4
|
+
Based on GlassWorm worm behavior for autonomous spread
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
rule MAL_JS_GlassWorm_Auto_Publish_Jan25 {
|
|
8
|
+
meta:
|
|
9
|
+
description = "Detects GlassWorm-style automated package publishing using stolen credentials for worm propagation"
|
|
10
|
+
severity = "high"
|
|
11
|
+
score = "85"
|
|
12
|
+
author = "vsix-audit"
|
|
13
|
+
date = "2025-01-29"
|
|
14
|
+
reference = "https://www.koi.security/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace"
|
|
15
|
+
|
|
16
|
+
strings:
|
|
17
|
+
// Package publishing
|
|
18
|
+
$npm_publish = "npm publish" ascii wide
|
|
19
|
+
$yarn_publish = "yarn publish" ascii wide
|
|
20
|
+
$publish_package = "publishPackage" ascii wide
|
|
21
|
+
$auto_publish = "autoPublish" ascii wide
|
|
22
|
+
|
|
23
|
+
// Extension publishing
|
|
24
|
+
$vsce_publish = "vsce publish" ascii wide
|
|
25
|
+
$extension_publish = "extensionPublish" ascii wide
|
|
26
|
+
$marketplace_publish = "marketplacePublish" ascii wide
|
|
27
|
+
$openvsx_publish = "openvsxPublish" ascii wide
|
|
28
|
+
|
|
29
|
+
// Automated publishing
|
|
30
|
+
$automated_publish = "automatedPublish" ascii wide
|
|
31
|
+
$auto_upload = "autoUpload" ascii wide
|
|
32
|
+
$batch_publish = "batchPublish" ascii wide
|
|
33
|
+
$mass_publish = "massPublish" ascii wide
|
|
34
|
+
|
|
35
|
+
// Credential usage
|
|
36
|
+
$use_credentials = "useCredentials" ascii wide
|
|
37
|
+
$auth_publish = "authPublish" ascii wide
|
|
38
|
+
$token_publish = "tokenPublish" ascii wide
|
|
39
|
+
$credential_publish = "credentialPublish" ascii wide
|
|
40
|
+
|
|
41
|
+
// Publishing APIs
|
|
42
|
+
$npm_api = "npmApi" ascii wide
|
|
43
|
+
$github_api = "githubApi" ascii wide
|
|
44
|
+
$openvsx_api = "openvsxApi" ascii wide
|
|
45
|
+
$marketplace_api = "marketplaceApi" ascii wide
|
|
46
|
+
|
|
47
|
+
condition:
|
|
48
|
+
// High confidence: Automated publishing + credential usage + API access
|
|
49
|
+
(any of ($npm_publish, $yarn_publish, $publish_package, $auto_publish, $vsce_publish, $extension_publish, $marketplace_publish, $openvsx_publish)) and
|
|
50
|
+
(any of ($automated_publish, $auto_upload, $batch_publish, $mass_publish)) and
|
|
51
|
+
(any of ($use_credentials, $auth_publish, $token_publish, $credential_publish, $npm_api, $github_api, $openvsx_api, $marketplace_api))
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
rule MAL_JS_GlassWorm_Credential_Reuse_Jan25 {
|
|
55
|
+
meta:
|
|
56
|
+
description = "Detects GlassWorm-style credential reuse pattern for compromising multiple accounts"
|
|
57
|
+
severity = "high"
|
|
58
|
+
score = "80"
|
|
59
|
+
author = "vsix-audit"
|
|
60
|
+
date = "2025-01-29"
|
|
61
|
+
reference = "https://www.koi.security/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace"
|
|
62
|
+
|
|
63
|
+
strings:
|
|
64
|
+
// Credential validation
|
|
65
|
+
$validate_credentials = "validateCredentials" ascii wide
|
|
66
|
+
$test_credentials = "testCredentials" ascii wide
|
|
67
|
+
$check_credentials = "checkCredentials" ascii wide
|
|
68
|
+
$verify_credentials = "verifyCredentials" ascii wide
|
|
69
|
+
|
|
70
|
+
// Credential reuse
|
|
71
|
+
$reuse_credentials = "reuseCredentials" ascii wide
|
|
72
|
+
$credential_reuse = "credentialReuse" ascii wide
|
|
73
|
+
$reuse_auth = "reuseAuth" ascii wide
|
|
74
|
+
$reuse_token = "reuseToken" ascii wide
|
|
75
|
+
|
|
76
|
+
// Multiple account access
|
|
77
|
+
$multi_account = "multiAccount" ascii wide
|
|
78
|
+
$batch_account = "batchAccount" ascii wide
|
|
79
|
+
$bulk_account = "bulkAccount" ascii wide
|
|
80
|
+
$mass_account = "massAccount" ascii wide
|
|
81
|
+
|
|
82
|
+
// Account enumeration
|
|
83
|
+
$enumerate_accounts = "enumerateAccounts" ascii wide
|
|
84
|
+
$list_accounts = "listAccounts" ascii wide
|
|
85
|
+
$scan_accounts = "scanAccounts" ascii wide
|
|
86
|
+
$discover_accounts = "discoverAccounts" ascii wide
|
|
87
|
+
|
|
88
|
+
// Credential rotation
|
|
89
|
+
$rotate_credentials = "rotateCredentials" ascii wide
|
|
90
|
+
$credential_rotation = "credentialRotation" ascii wide
|
|
91
|
+
$auth_rotation = "authRotation" ascii wide
|
|
92
|
+
|
|
93
|
+
condition:
|
|
94
|
+
// Detect credential validation with reuse patterns
|
|
95
|
+
(any of ($validate_credentials, $test_credentials, $check_credentials, $verify_credentials)) and
|
|
96
|
+
(any of ($reuse_credentials, $credential_reuse, $reuse_auth, $reuse_token)) and
|
|
97
|
+
(any of ($multi_account, $batch_account, $bulk_account, $mass_account, $enumerate_accounts, $list_accounts, $scan_accounts, $discover_accounts, $rotate_credentials, $credential_rotation, $auth_rotation))
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
rule MAL_JS_GlassWorm_Git_Automation_Jan25 {
|
|
101
|
+
meta:
|
|
102
|
+
description = "Detects GlassWorm-style automated git operations for spreading malicious code to repositories"
|
|
103
|
+
severity = "high"
|
|
104
|
+
score = "85"
|
|
105
|
+
author = "vsix-audit"
|
|
106
|
+
date = "2025-01-29"
|
|
107
|
+
reference = "https://www.koi.security/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace"
|
|
108
|
+
|
|
109
|
+
strings:
|
|
110
|
+
// Git automation
|
|
111
|
+
$git_automation = "gitAutomation" ascii wide
|
|
112
|
+
$auto_git = "autoGit" ascii wide
|
|
113
|
+
$git_bot = "gitBot" ascii wide
|
|
114
|
+
$automated_git = "automatedGit" ascii wide
|
|
115
|
+
|
|
116
|
+
// Git operations
|
|
117
|
+
$git_commit = "git commit" ascii wide
|
|
118
|
+
$git_push = "git push" ascii wide
|
|
119
|
+
$git_pull = "git pull" ascii wide
|
|
120
|
+
$git_clone = "git clone" ascii wide
|
|
121
|
+
|
|
122
|
+
// Automated git workflow
|
|
123
|
+
$git_workflow = "gitWorkflow" ascii wide
|
|
124
|
+
$auto_commit = "autoCommit" ascii wide
|
|
125
|
+
$auto_push = "autoPush" ascii wide
|
|
126
|
+
$batch_git = "batchGit" ascii wide
|
|
127
|
+
|
|
128
|
+
// Repository manipulation
|
|
129
|
+
$repo_manipulate = "repoManipulate" ascii wide
|
|
130
|
+
$repo_inject = "repoInject" ascii wide
|
|
131
|
+
$repo_contaminate = "repoContaminate" ascii wide
|
|
132
|
+
$repo_infect = "repoInfect" ascii wide
|
|
133
|
+
|
|
134
|
+
// Git hooks
|
|
135
|
+
$git_hooks = "gitHooks" ascii wide
|
|
136
|
+
$pre_commit = "preCommit" ascii wide
|
|
137
|
+
$post_commit = "postCommit" ascii wide
|
|
138
|
+
$pre_push = "prePush" ascii wide
|
|
139
|
+
|
|
140
|
+
condition:
|
|
141
|
+
// Detect git automation with repository manipulation
|
|
142
|
+
(any of ($git_automation, $auto_git, $git_bot, $automated_git, $git_commit, $git_push, $git_pull, $git_clone)) and
|
|
143
|
+
(any of ($git_workflow, $auto_commit, $auto_push, $batch_git)) and
|
|
144
|
+
(any of ($repo_manipulate, $repo_inject, $repo_contaminate, $repo_infect, $git_hooks, $pre_commit, $post_commit, $pre_push))
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
rule MAL_JS_GlassWorm_Worm_Propagation_Jan25 {
|
|
148
|
+
meta:
|
|
149
|
+
description = "Detects GlassWorm-style worm self-replication and autonomous propagation mechanisms"
|
|
150
|
+
severity = "critical"
|
|
151
|
+
score = "95"
|
|
152
|
+
author = "vsix-audit"
|
|
153
|
+
date = "2025-01-29"
|
|
154
|
+
reference = "https://www.koi.security/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace"
|
|
155
|
+
|
|
156
|
+
strings:
|
|
157
|
+
// Worm patterns
|
|
158
|
+
$worm = "worm" ascii wide
|
|
159
|
+
$propagate = "propagate" ascii wide
|
|
160
|
+
$spread = "spread" ascii wide
|
|
161
|
+
$infect = "infect" ascii wide
|
|
162
|
+
|
|
163
|
+
// Self-replication
|
|
164
|
+
$self_replicate = "selfReplicate" ascii wide
|
|
165
|
+
$self_copy = "selfCopy" ascii wide
|
|
166
|
+
$self_propagate = "selfPropagate" ascii wide
|
|
167
|
+
$auto_replicate = "autoReplicate" ascii wide
|
|
168
|
+
|
|
169
|
+
// Propagation vectors
|
|
170
|
+
$propagation_vector = "propagationVector" ascii wide
|
|
171
|
+
$spread_vector = "spreadVector" ascii wide
|
|
172
|
+
$infection_vector = "infectionVector" ascii wide
|
|
173
|
+
$attack_vector = "attackVector" ascii wide
|
|
174
|
+
|
|
175
|
+
// Autonomous behavior
|
|
176
|
+
$autonomous = "autonomous" ascii wide
|
|
177
|
+
$self_sustaining = "selfSustaining" ascii wide
|
|
178
|
+
$self_contained = "selfContained" ascii wide
|
|
179
|
+
$independent = "independent" ascii wide
|
|
180
|
+
|
|
181
|
+
// Worm lifecycle
|
|
182
|
+
$worm_lifecycle = "wormLifecycle" ascii wide
|
|
183
|
+
$infection_cycle = "infectionCycle" ascii wide
|
|
184
|
+
$propagation_cycle = "propagationCycle" ascii wide
|
|
185
|
+
$spread_cycle = "spreadCycle" ascii wide
|
|
186
|
+
|
|
187
|
+
condition:
|
|
188
|
+
// Critical: Worm behavior + self-replication + autonomous operation
|
|
189
|
+
(any of ($worm, $propagate, $spread, $infect)) and
|
|
190
|
+
(any of ($self_replicate, $self_copy, $self_propagate, $auto_replicate)) and
|
|
191
|
+
(any of ($propagation_vector, $spread_vector, $infection_vector, $attack_vector, $autonomous, $self_sustaining, $self_contained, $independent, $worm_lifecycle, $infection_cycle, $propagation_cycle, $spread_cycle))
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
rule MAL_JS_GlassWorm_Supply_Chain_Abuse_Jan25 {
|
|
195
|
+
meta:
|
|
196
|
+
description = "Detects GlassWorm-style supply chain abuse through package ecosystem and dependency injection"
|
|
197
|
+
severity = "high"
|
|
198
|
+
score = "90"
|
|
199
|
+
author = "vsix-audit"
|
|
200
|
+
date = "2025-01-29"
|
|
201
|
+
reference = "https://www.koi.security/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace"
|
|
202
|
+
|
|
203
|
+
strings:
|
|
204
|
+
// Supply chain patterns
|
|
205
|
+
$supply_chain = "supplyChain" ascii wide
|
|
206
|
+
$package_chain = "packageChain" ascii wide
|
|
207
|
+
$dependency_chain = "dependencyChain" ascii wide
|
|
208
|
+
$repo_chain = "repoChain" ascii wide
|
|
209
|
+
|
|
210
|
+
// Package ecosystem abuse
|
|
211
|
+
$ecosystem_abuse = "ecosystemAbuse" ascii wide
|
|
212
|
+
$package_abuse = "packageAbuse" ascii wide
|
|
213
|
+
$registry_abuse = "registryAbuse" ascii wide
|
|
214
|
+
$marketplace_abuse = "marketplaceAbuse" ascii wide
|
|
215
|
+
|
|
216
|
+
// Dependency injection
|
|
217
|
+
$dependency_inject = "dependencyInject" ascii wide
|
|
218
|
+
$package_inject = "packageInject" ascii wide
|
|
219
|
+
$repo_inject = "repoInject" ascii wide
|
|
220
|
+
$chain_inject = "chainInject" ascii wide
|
|
221
|
+
|
|
222
|
+
// Automated compromise
|
|
223
|
+
$auto_compromise = "autoCompromise" ascii wide
|
|
224
|
+
$batch_compromise = "batchCompromise" ascii wide
|
|
225
|
+
$mass_compromise = "massCompromise" ascii wide
|
|
226
|
+
$bulk_compromise = "bulkCompromise" ascii wide
|
|
227
|
+
|
|
228
|
+
// Trust exploitation
|
|
229
|
+
$trust_exploit = "trustExploit" ascii wide
|
|
230
|
+
$trust_abuse = "trustAbuse" ascii wide
|
|
231
|
+
$reputation_abuse = "reputationAbuse" ascii wide
|
|
232
|
+
$legitimacy_abuse = "legitimacyAbuse" ascii wide
|
|
233
|
+
|
|
234
|
+
condition:
|
|
235
|
+
// Detect supply chain abuse with automated compromise
|
|
236
|
+
(any of ($supply_chain, $package_chain, $dependency_chain, $repo_chain)) and
|
|
237
|
+
(any of ($ecosystem_abuse, $package_abuse, $registry_abuse, $marketplace_abuse)) and
|
|
238
|
+
(any of ($dependency_inject, $package_inject, $repo_inject, $chain_inject, $auto_compromise, $batch_compromise, $mass_compromise, $bulk_compromise, $trust_exploit, $trust_abuse, $reputation_abuse, $legitimacy_abuse))
|
|
239
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/*
|
|
2
|
+
GlassWorm Unicode Stealth Detection
|
|
3
|
+
Detects invisible Unicode variation selectors used to hide malicious code
|
|
4
|
+
|
|
5
|
+
IMPORTANT: This rule requires MANY variation selectors plus eval/Function.
|
|
6
|
+
A few zero-width characters are normal in i18n bundles.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
rule MAL_JS_GlassWorm_Unicode_Stealth_Jan25 {
|
|
10
|
+
meta:
|
|
11
|
+
description = "Detects GlassWorm-style invisible Unicode variation selectors used to hide malicious code"
|
|
12
|
+
severity = "critical"
|
|
13
|
+
score = "95"
|
|
14
|
+
author = "vsix-audit"
|
|
15
|
+
date = "2025-01-29"
|
|
16
|
+
reference = "https://www.koi.security/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace"
|
|
17
|
+
|
|
18
|
+
strings:
|
|
19
|
+
// UTF-8 encoded variation selectors (U+FE00-U+FE0F)
|
|
20
|
+
// Note: These are 3-byte UTF-8 sequences EF B8 80 through EF B8 8F
|
|
21
|
+
$vs_utf8 = { EF B8 (80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 8A | 8B | 8C | 8D | 8E | 8F) }
|
|
22
|
+
|
|
23
|
+
// Code execution patterns - must have eval or Function
|
|
24
|
+
$eval = "eval(" ascii wide
|
|
25
|
+
$function = "new Function(" ascii wide
|
|
26
|
+
|
|
27
|
+
// Decode patterns that are used to extract the hidden code
|
|
28
|
+
$decode1 = "String.fromCharCode" ascii wide
|
|
29
|
+
$decode2 = "charCodeAt" ascii wide
|
|
30
|
+
|
|
31
|
+
// Zero-width space (U+200B) - used in obfuscation
|
|
32
|
+
$zws = { E2 80 8B }
|
|
33
|
+
|
|
34
|
+
// Zero-width non-joiner (U+200C) and joiner (U+200D)
|
|
35
|
+
$zwc = { E2 80 (8C | 8D) }
|
|
36
|
+
|
|
37
|
+
condition:
|
|
38
|
+
// Require VERY MANY variation selectors (50+) for standalone detection
|
|
39
|
+
// Normal i18n/emoji bundles have < 30, malware has hundreds
|
|
40
|
+
(#vs_utf8 > 50 and any of ($eval, $function)) or
|
|
41
|
+
// Or: moderate VS count + both eval AND decode (full chain)
|
|
42
|
+
(#vs_utf8 > 20 and any of ($eval, $function) and any of ($decode*)) or
|
|
43
|
+
// Or: many zero-width chars + eval (different obfuscation style)
|
|
44
|
+
((#zws + #zwc) > 30 and any of ($eval, $function))
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// REMOVED: GlassWorm_Suspicious_Code_Gaps
|
|
48
|
+
// This rule was removed earlier - it matched any code with whitespace.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/*
|
|
2
|
+
WebSocket C2 Detection
|
|
3
|
+
Detects WebSocket-based command and control patterns
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
rule C2_JS_WebSocket_Command_Exec_Jan25 {
|
|
7
|
+
meta:
|
|
8
|
+
description = "Detects WebSocket C2 pattern with message handler triggering child_process command execution"
|
|
9
|
+
severity = "high"
|
|
10
|
+
score = 80
|
|
11
|
+
author = "vsix-audit"
|
|
12
|
+
date = "2025-01-30"
|
|
13
|
+
|
|
14
|
+
strings:
|
|
15
|
+
// WebSocket creation
|
|
16
|
+
$ws1 = "new WebSocket(" ascii wide
|
|
17
|
+
$ws2 = "WebSocket(" ascii wide
|
|
18
|
+
$ws3 = "ws://" ascii wide
|
|
19
|
+
$ws4 = "wss://" ascii wide
|
|
20
|
+
|
|
21
|
+
// Message handling (specific patterns)
|
|
22
|
+
$msg1 = ".onmessage" ascii wide
|
|
23
|
+
$msg2 = ".on('message'" ascii wide
|
|
24
|
+
$msg3 = ".on(\"message\"" ascii wide
|
|
25
|
+
|
|
26
|
+
// Command execution via child_process (not just setTimeout)
|
|
27
|
+
$exec_cp = "child_process" ascii wide
|
|
28
|
+
$exec_method1 = ".exec(" ascii wide
|
|
29
|
+
$exec_method2 = ".spawn(" ascii wide
|
|
30
|
+
$exec_sync1 = "execSync" ascii wide
|
|
31
|
+
$exec_sync2 = "spawnSync" ascii wide
|
|
32
|
+
|
|
33
|
+
// Eval from message (dangerous pattern)
|
|
34
|
+
$eval_msg = "eval(" ascii wide
|
|
35
|
+
|
|
36
|
+
// C2-specific patterns
|
|
37
|
+
$c2_cmd = "command" ascii wide
|
|
38
|
+
$c2_shell = "shell" ascii wide nocase
|
|
39
|
+
$c2_run = "runCommand" ascii wide
|
|
40
|
+
|
|
41
|
+
condition:
|
|
42
|
+
// WebSocket + message handler + child_process execution
|
|
43
|
+
any of ($ws*) and any of ($msg*) and
|
|
44
|
+
(
|
|
45
|
+
// Direct child_process usage with exec/spawn method
|
|
46
|
+
($exec_cp and any of ($exec_method*, $exec_sync*)) or
|
|
47
|
+
// Eval from WebSocket (rare in legit code)
|
|
48
|
+
($eval_msg and any of ($c2_cmd, $c2_shell, $c2_run))
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
rule RAT_JS_WebSocket_Reverse_Shell_Jan25 {
|
|
53
|
+
meta:
|
|
54
|
+
description = "Detects WebSocket reverse shell with shell process stdin/stdout piped through socket"
|
|
55
|
+
severity = "critical"
|
|
56
|
+
score = 95
|
|
57
|
+
author = "vsix-audit"
|
|
58
|
+
date = "2025-01-30"
|
|
59
|
+
|
|
60
|
+
strings:
|
|
61
|
+
// WebSocket creation
|
|
62
|
+
$ws1 = "new WebSocket(" ascii wide
|
|
63
|
+
$ws2 = "WebSocket(" ascii wide
|
|
64
|
+
$ws3 = "ws://" ascii wide
|
|
65
|
+
$ws4 = "wss://" ascii wide
|
|
66
|
+
|
|
67
|
+
// Shell paths
|
|
68
|
+
$shell1 = "/bin/sh" ascii wide
|
|
69
|
+
$shell2 = "/bin/bash" ascii wide
|
|
70
|
+
$shell3 = "/bin/zsh" ascii wide
|
|
71
|
+
$shell4 = "cmd.exe" ascii wide
|
|
72
|
+
$shell5 = "powershell" ascii wide nocase
|
|
73
|
+
|
|
74
|
+
// Stream piping (connecting shell to socket)
|
|
75
|
+
$pipe1 = ".pipe(" ascii wide
|
|
76
|
+
$pipe2 = "stdin" ascii wide
|
|
77
|
+
$pipe3 = "stdout" ascii wide
|
|
78
|
+
$pipe4 = "stderr" ascii wide
|
|
79
|
+
$pipe5 = ".send(" ascii wide
|
|
80
|
+
|
|
81
|
+
condition:
|
|
82
|
+
any of ($ws*) and any of ($shell*) and 2 of ($pipe*)
|
|
83
|
+
}
|