@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.
Files changed (197) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +281 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +703 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +4 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/scanner/batch.d.ts +12 -0
  12. package/dist/scanner/batch.d.ts.map +1 -0
  13. package/dist/scanner/batch.js +104 -0
  14. package/dist/scanner/batch.js.map +1 -0
  15. package/dist/scanner/bundler.d.ts +35 -0
  16. package/dist/scanner/bundler.d.ts.map +1 -0
  17. package/dist/scanner/bundler.js +120 -0
  18. package/dist/scanner/bundler.js.map +1 -0
  19. package/dist/scanner/cache.d.ts +45 -0
  20. package/dist/scanner/cache.d.ts.map +1 -0
  21. package/dist/scanner/cache.js +153 -0
  22. package/dist/scanner/cache.js.map +1 -0
  23. package/dist/scanner/cache.test.d.ts +2 -0
  24. package/dist/scanner/cache.test.d.ts.map +1 -0
  25. package/dist/scanner/cache.test.js +149 -0
  26. package/dist/scanner/cache.test.js.map +1 -0
  27. package/dist/scanner/capabilities.d.ts +29 -0
  28. package/dist/scanner/capabilities.d.ts.map +1 -0
  29. package/dist/scanner/capabilities.js +217 -0
  30. package/dist/scanner/capabilities.js.map +1 -0
  31. package/dist/scanner/checks/ast.d.ts +3 -0
  32. package/dist/scanner/checks/ast.d.ts.map +1 -0
  33. package/dist/scanner/checks/ast.js +469 -0
  34. package/dist/scanner/checks/ast.js.map +1 -0
  35. package/dist/scanner/checks/ast.test.d.ts +2 -0
  36. package/dist/scanner/checks/ast.test.d.ts.map +1 -0
  37. package/dist/scanner/checks/ast.test.js +389 -0
  38. package/dist/scanner/checks/ast.test.js.map +1 -0
  39. package/dist/scanner/checks/behavioral.d.ts +3 -0
  40. package/dist/scanner/checks/behavioral.d.ts.map +1 -0
  41. package/dist/scanner/checks/behavioral.js +367 -0
  42. package/dist/scanner/checks/behavioral.js.map +1 -0
  43. package/dist/scanner/checks/blocklist.d.ts +3 -0
  44. package/dist/scanner/checks/blocklist.d.ts.map +1 -0
  45. package/dist/scanner/checks/blocklist.js +32 -0
  46. package/dist/scanner/checks/blocklist.js.map +1 -0
  47. package/dist/scanner/checks/blocklist.test.d.ts +2 -0
  48. package/dist/scanner/checks/blocklist.test.d.ts.map +1 -0
  49. package/dist/scanner/checks/blocklist.test.js +74 -0
  50. package/dist/scanner/checks/blocklist.test.js.map +1 -0
  51. package/dist/scanner/checks/chains.d.ts +35 -0
  52. package/dist/scanner/checks/chains.d.ts.map +1 -0
  53. package/dist/scanner/checks/chains.js +505 -0
  54. package/dist/scanner/checks/chains.js.map +1 -0
  55. package/dist/scanner/checks/chains.test.d.ts +2 -0
  56. package/dist/scanner/checks/chains.test.d.ts.map +1 -0
  57. package/dist/scanner/checks/chains.test.js +250 -0
  58. package/dist/scanner/checks/chains.test.js.map +1 -0
  59. package/dist/scanner/checks/dataflow.d.ts +3 -0
  60. package/dist/scanner/checks/dataflow.d.ts.map +1 -0
  61. package/dist/scanner/checks/dataflow.js +316 -0
  62. package/dist/scanner/checks/dataflow.js.map +1 -0
  63. package/dist/scanner/checks/dependencies.d.ts +13 -0
  64. package/dist/scanner/checks/dependencies.d.ts.map +1 -0
  65. package/dist/scanner/checks/dependencies.js +225 -0
  66. package/dist/scanner/checks/dependencies.js.map +1 -0
  67. package/dist/scanner/checks/dependencies.test.d.ts +2 -0
  68. package/dist/scanner/checks/dependencies.test.d.ts.map +1 -0
  69. package/dist/scanner/checks/dependencies.test.js +248 -0
  70. package/dist/scanner/checks/dependencies.test.js.map +1 -0
  71. package/dist/scanner/checks/finding-quality.test.d.ts +8 -0
  72. package/dist/scanner/checks/finding-quality.test.d.ts.map +1 -0
  73. package/dist/scanner/checks/finding-quality.test.js +164 -0
  74. package/dist/scanner/checks/finding-quality.test.js.map +1 -0
  75. package/dist/scanner/checks/ioc.d.ts +20 -0
  76. package/dist/scanner/checks/ioc.d.ts.map +1 -0
  77. package/dist/scanner/checks/ioc.js +234 -0
  78. package/dist/scanner/checks/ioc.js.map +1 -0
  79. package/dist/scanner/checks/ioc.test.d.ts +2 -0
  80. package/dist/scanner/checks/ioc.test.d.ts.map +1 -0
  81. package/dist/scanner/checks/ioc.test.js +298 -0
  82. package/dist/scanner/checks/ioc.test.js.map +1 -0
  83. package/dist/scanner/checks/manifest.d.ts +6 -0
  84. package/dist/scanner/checks/manifest.d.ts.map +1 -0
  85. package/dist/scanner/checks/manifest.js +123 -0
  86. package/dist/scanner/checks/manifest.js.map +1 -0
  87. package/dist/scanner/checks/manifest.test.d.ts +2 -0
  88. package/dist/scanner/checks/manifest.test.d.ts.map +1 -0
  89. package/dist/scanner/checks/manifest.test.js +108 -0
  90. package/dist/scanner/checks/manifest.test.js.map +1 -0
  91. package/dist/scanner/checks/obfuscation.d.ts +3 -0
  92. package/dist/scanner/checks/obfuscation.d.ts.map +1 -0
  93. package/dist/scanner/checks/obfuscation.js +432 -0
  94. package/dist/scanner/checks/obfuscation.js.map +1 -0
  95. package/dist/scanner/checks/obfuscation.test.d.ts +2 -0
  96. package/dist/scanner/checks/obfuscation.test.d.ts.map +1 -0
  97. package/dist/scanner/checks/obfuscation.test.js +399 -0
  98. package/dist/scanner/checks/obfuscation.test.js.map +1 -0
  99. package/dist/scanner/checks/package.d.ts +17 -0
  100. package/dist/scanner/checks/package.d.ts.map +1 -0
  101. package/dist/scanner/checks/package.js +422 -0
  102. package/dist/scanner/checks/package.js.map +1 -0
  103. package/dist/scanner/checks/package.test.d.ts +2 -0
  104. package/dist/scanner/checks/package.test.d.ts.map +1 -0
  105. package/dist/scanner/checks/package.test.js +518 -0
  106. package/dist/scanner/checks/package.test.js.map +1 -0
  107. package/dist/scanner/checks/patterns.d.ts +5 -0
  108. package/dist/scanner/checks/patterns.d.ts.map +1 -0
  109. package/dist/scanner/checks/patterns.js +251 -0
  110. package/dist/scanner/checks/patterns.js.map +1 -0
  111. package/dist/scanner/checks/patterns.test.d.ts +2 -0
  112. package/dist/scanner/checks/patterns.test.d.ts.map +1 -0
  113. package/dist/scanner/checks/patterns.test.js +147 -0
  114. package/dist/scanner/checks/patterns.test.js.map +1 -0
  115. package/dist/scanner/checks/unicode.d.ts +3 -0
  116. package/dist/scanner/checks/unicode.d.ts.map +1 -0
  117. package/dist/scanner/checks/unicode.js +247 -0
  118. package/dist/scanner/checks/unicode.js.map +1 -0
  119. package/dist/scanner/checks/unicode.test.d.ts +2 -0
  120. package/dist/scanner/checks/unicode.test.d.ts.map +1 -0
  121. package/dist/scanner/checks/unicode.test.js +202 -0
  122. package/dist/scanner/checks/unicode.test.js.map +1 -0
  123. package/dist/scanner/checks/yara.d.ts +23 -0
  124. package/dist/scanner/checks/yara.d.ts.map +1 -0
  125. package/dist/scanner/checks/yara.js +349 -0
  126. package/dist/scanner/checks/yara.js.map +1 -0
  127. package/dist/scanner/checks/yara.test.d.ts +2 -0
  128. package/dist/scanner/checks/yara.test.d.ts.map +1 -0
  129. package/dist/scanner/checks/yara.test.js +126 -0
  130. package/dist/scanner/checks/yara.test.js.map +1 -0
  131. package/dist/scanner/constants.d.ts +18 -0
  132. package/dist/scanner/constants.d.ts.map +1 -0
  133. package/dist/scanner/constants.js +37 -0
  134. package/dist/scanner/constants.js.map +1 -0
  135. package/dist/scanner/detection-coverage.test.d.ts +2 -0
  136. package/dist/scanner/detection-coverage.test.d.ts.map +1 -0
  137. package/dist/scanner/detection-coverage.test.js +216 -0
  138. package/dist/scanner/detection-coverage.test.js.map +1 -0
  139. package/dist/scanner/download.d.ts +76 -0
  140. package/dist/scanner/download.d.ts.map +1 -0
  141. package/dist/scanner/download.js +339 -0
  142. package/dist/scanner/download.js.map +1 -0
  143. package/dist/scanner/download.test.d.ts +2 -0
  144. package/dist/scanner/download.test.d.ts.map +1 -0
  145. package/dist/scanner/download.test.js +149 -0
  146. package/dist/scanner/download.test.js.map +1 -0
  147. package/dist/scanner/index.d.ts +8 -0
  148. package/dist/scanner/index.d.ts.map +1 -0
  149. package/dist/scanner/index.js +167 -0
  150. package/dist/scanner/index.js.map +1 -0
  151. package/dist/scanner/index.test.d.ts +2 -0
  152. package/dist/scanner/index.test.d.ts.map +1 -0
  153. package/dist/scanner/index.test.js +71 -0
  154. package/dist/scanner/index.test.js.map +1 -0
  155. package/dist/scanner/loaders/zoo.d.ts +3 -0
  156. package/dist/scanner/loaders/zoo.d.ts.map +1 -0
  157. package/dist/scanner/loaders/zoo.js +112 -0
  158. package/dist/scanner/loaders/zoo.js.map +1 -0
  159. package/dist/scanner/types.d.ts +118 -0
  160. package/dist/scanner/types.d.ts.map +1 -0
  161. package/dist/scanner/types.js +2 -0
  162. package/dist/scanner/types.js.map +1 -0
  163. package/dist/scanner/utils.d.ts +14 -0
  164. package/dist/scanner/utils.d.ts.map +1 -0
  165. package/dist/scanner/utils.js +25 -0
  166. package/dist/scanner/utils.js.map +1 -0
  167. package/dist/scanner/vsix.d.ts +6 -0
  168. package/dist/scanner/vsix.d.ts.map +1 -0
  169. package/dist/scanner/vsix.js +213 -0
  170. package/dist/scanner/vsix.js.map +1 -0
  171. package/dist/scanner/vsix.test.d.ts +2 -0
  172. package/dist/scanner/vsix.test.d.ts.map +1 -0
  173. package/dist/scanner/vsix.test.js +355 -0
  174. package/dist/scanner/vsix.test.js.map +1 -0
  175. package/package.json +60 -0
  176. package/zoo/blocklist/extensions.json +201 -0
  177. package/zoo/iocs/blockchain-extensions.txt +21 -0
  178. package/zoo/iocs/c2-domains.txt +50 -0
  179. package/zoo/iocs/c2-ips.txt +24 -0
  180. package/zoo/iocs/hashes.txt +47 -0
  181. package/zoo/iocs/malicious-npm.txt +85 -0
  182. package/zoo/iocs/wallets.txt +18 -0
  183. package/zoo/signatures/yara/README.md +46 -0
  184. package/zoo/signatures/yara/blockchain_c2.yar +48 -0
  185. package/zoo/signatures/yara/code_execution.yar +165 -0
  186. package/zoo/signatures/yara/credential_harvesting.yar +116 -0
  187. package/zoo/signatures/yara/crypto_wallet_targeting.yar +92 -0
  188. package/zoo/signatures/yara/data_exfiltration.yar +207 -0
  189. package/zoo/signatures/yara/google_calendar_c2.yar +187 -0
  190. package/zoo/signatures/yara/messaging_c2.yar +103 -0
  191. package/zoo/signatures/yara/multi_stage_attacks.yar +331 -0
  192. package/zoo/signatures/yara/obfuscation_patterns.yar +208 -0
  193. package/zoo/signatures/yara/powershell_attacks.yar +116 -0
  194. package/zoo/signatures/yara/rat_capabilities.yar +243 -0
  195. package/zoo/signatures/yara/self_propagation.yar +239 -0
  196. package/zoo/signatures/yara/unicode_stealth.yar +48 -0
  197. package/zoo/signatures/yara/websocket_c2.yar +83 -0
@@ -0,0 +1,92 @@
1
+ /*
2
+ GlassWorm Cryptocurrency Wallet Targeting Detection
3
+ Detects patterns for targeting cryptocurrency wallet extensions
4
+
5
+ IMPORTANT: These rules require CLEAR malicious intent indicators.
6
+ Many legitimate tools interact with crypto wallets.
7
+ */
8
+
9
+ rule MAL_JS_GlassWorm_Wallet_Seed_Extraction_Jan25 {
10
+ meta:
11
+ description = "Detects GlassWorm-style wallet seed phrase extraction from storage combined with network exfil"
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
+ // Seed phrase patterns (very specific)
20
+ $seed1 = "seedPhrase" ascii wide
21
+ $seed2 = "mnemonic" ascii wide
22
+ $seed3 = "recoveryPhrase" ascii wide
23
+
24
+ // Private key extraction
25
+ $privkey = "privateKey" ascii wide
26
+
27
+ // Storage access
28
+ $storage1 = "localStorage.getItem" ascii wide
29
+ $storage2 = "chrome.storage" ascii wide
30
+
31
+ // Exfiltration - must send somewhere
32
+ $exfil1 = "discord.com/api/webhooks" ascii wide
33
+ $exfil2 = "discordapp.com/api/webhooks" ascii wide
34
+ $exfil3 = /fetch\s*\(\s*["'][^"']*["']\s*,\s*\{[^}]*body/ ascii wide
35
+ $exfil4 = "axios.post" ascii wide
36
+
37
+ condition:
38
+ any of ($seed*, $privkey) and any of ($storage*) and any of ($exfil*)
39
+ }
40
+
41
+ rule MAL_JS_GlassWorm_Multi_Wallet_Enum_Jan25 {
42
+ meta:
43
+ description = "Detects GlassWorm-style enumeration of 3+ crypto wallet browser extension IDs for targeting"
44
+ severity = "high"
45
+ score = "85"
46
+ author = "vsix-audit"
47
+ date = "2025-01-29"
48
+ reference = "https://www.koi.security/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace"
49
+
50
+ strings:
51
+ // MetaMask extension ID
52
+ $metamask_id = "nkbihfbeogaeaoehlefnkodbefgpgknn" ascii wide
53
+
54
+ // Phantom extension ID
55
+ $phantom_id = "bfnaelmomeimhlpmgjnjophhpkkoljpa" ascii wide
56
+
57
+ // Coinbase Wallet extension ID
58
+ $coinbase_id = "hnfanknocfeofbddgcijnmhnfnkdnaad" ascii wide
59
+
60
+ // Other wallet extension IDs
61
+ $trust_id = "egjidjbpglichdcondbcbdnbeeppgdph" ascii wide
62
+ $exodus_id = "aholpfdialjgjfhomihkjbmgjidlcdno" ascii wide
63
+
64
+ // Additional wallet extension IDs
65
+ $rabby_id = "acmacodkjbdgmoleebolmdjonilkdbch" ascii wide
66
+ $keplr_id = "dmkamcknogkgcdfhhbddcghachkejeap" ascii wide
67
+ $okx_id = "mcohilncbfahbmgdjkbpemcciiolgcge" ascii wide
68
+ $bitget_id = "jiidiaalihmmhddjgbnbgdfflelocpak" ascii wide
69
+ $rainbow_id = "opfgelmcmbiajamepnmloijbpoleiama" ascii wide
70
+ $zerion_id = "klghhnkeealcohjjanjjdaeeggmfmlpl" ascii wide
71
+ $backpack_id = "aflkmfhebedbjioipglgcbcmnbpgliof" ascii wide
72
+ $solflare_id = "bhhhlbepdkbapadjdnnojkbgioiodbic" ascii wide
73
+
74
+ // Must be checking for multiple
75
+ $check = /chrome\.runtime\.sendMessage|chrome\.management\.get/ ascii wide
76
+
77
+ condition:
78
+ 3 of ($metamask_id, $phantom_id, $coinbase_id, $trust_id, $exodus_id,
79
+ $rabby_id, $keplr_id, $okx_id, $bitget_id, $rainbow_id,
80
+ $zerion_id, $backpack_id, $solflare_id) and $check
81
+ }
82
+
83
+ // REMOVED: GlassWorm_Crypto_Wallet_Targeting
84
+ // Too broad - matched "metamask" + "phantom" + "address"
85
+ // which appears in many legitimate dApp extensions.
86
+
87
+ // REMOVED: GlassWorm_Wallet_Transaction_Interception
88
+ // Too broad - "transaction" + "hook" + "to/from/value" matches
89
+ // virtually all web3 applications.
90
+
91
+ // REMOVED: GlassWorm_Wallet_Extension_Enumeration
92
+ // Too broad - wallet detection is legitimate for dApps.
@@ -0,0 +1,207 @@
1
+ /*
2
+ Data Exfiltration Detection
3
+ Detects patterns for stealing and transmitting sensitive data
4
+ */
5
+
6
+ rule C2_JS_Discord_Webhook_Jan25 {
7
+ meta:
8
+ description = "Detects Discord webhook URL patterns commonly used for data exfiltration and C2 communication"
9
+ severity = "high"
10
+ score = 75
11
+ author = "vsix-audit"
12
+ date = "2025-01-29"
13
+
14
+ strings:
15
+ $webhook1 = /discord\.com\/api\/webhooks\/\d+\/[a-zA-Z0-9_-]+/ ascii wide
16
+ $webhook2 = /discordapp\.com\/api\/webhooks\/\d+\/[a-zA-Z0-9_-]+/ ascii wide
17
+ $webhook3 = "discord.com/api/webhooks" ascii wide
18
+ $webhook4 = "discordapp.com/api/webhooks" ascii wide
19
+
20
+ condition:
21
+ any of them
22
+ }
23
+
24
+ rule C2_JS_Free_Hosting_Jan25 {
25
+ meta:
26
+ description = "Detects free hosting service domains commonly abused for C2 infrastructure and data exfiltration"
27
+ severity = "medium"
28
+ score = 60
29
+ author = "vsix-audit"
30
+ date = "2025-01-29"
31
+
32
+ strings:
33
+ // Vercel - commonly abused
34
+ $vercel = /[a-z0-9-]+\.vercel\.app/ ascii wide
35
+
36
+ // PythonAnywhere - commonly abused for exfil
37
+ $pythonanywhere = /[a-z0-9-]+\.pythonanywhere\.com/ ascii wide
38
+
39
+ // Netlify
40
+ $netlify = /[a-z0-9-]+\.netlify\.app/ ascii wide
41
+
42
+ // Glitch
43
+ $glitch = /[a-z0-9-]+\.glitch\.me/ ascii wide
44
+
45
+ // Replit
46
+ $replit = /[a-z0-9-]+\.repl\.co/ ascii wide
47
+
48
+ // Railway
49
+ $railway = /[a-z0-9-]+\.railway\.app/ ascii wide
50
+
51
+ // Render
52
+ $render = /[a-z0-9-]+\.onrender\.com/ ascii wide
53
+
54
+ // Cloudflare Pages
55
+ $cf_pages = /[a-z0-9-]+\.pages\.dev/ ascii wide
56
+
57
+ // Cloudflare Workers
58
+ $cf_workers = /[a-z0-9-]+\.workers\.dev/ ascii wide
59
+
60
+ // Firebase Hosting
61
+ $firebase1 = /[a-z0-9-]+\.web\.app/ ascii wide
62
+ $firebase2 = /[a-z0-9-]+\.firebaseapp\.com/ ascii wide
63
+
64
+ // AWS Amplify
65
+ $amplify = /[a-z0-9-]+\.amplifyapp\.com/ ascii wide
66
+
67
+ // Heroku
68
+ $heroku = /[a-z0-9-]+\.herokuapp\.com/ ascii wide
69
+
70
+ // Deno Deploy
71
+ $deno = /[a-z0-9-]+\.deno\.dev/ ascii wide
72
+
73
+ // Fly.io
74
+ $fly = /[a-z0-9-]+\.fly\.dev/ ascii wide
75
+
76
+ // Ngrok tunnels
77
+ $ngrok1 = /[a-z0-9-]+\.ngrok\.io/ ascii wide
78
+ $ngrok2 = /[a-z0-9-]+\.ngrok-free\.app/ ascii wide
79
+
80
+ condition:
81
+ any of them
82
+ }
83
+
84
+ rule STEALER_JS_SSH_Key_Exfil_Jan25 {
85
+ meta:
86
+ description = "Detects SSH private key file access combined with network transmission for credential theft"
87
+ severity = "critical"
88
+ score = 90
89
+ author = "vsix-audit"
90
+ date = "2025-01-29"
91
+
92
+ strings:
93
+ // SSH key paths
94
+ $ssh1 = ".ssh/id_rsa" ascii wide
95
+ $ssh2 = ".ssh/id_ed25519" ascii wide
96
+ $ssh3 = ".ssh/id_ecdsa" ascii wide
97
+ $ssh4 = ".ssh/id_dsa" ascii wide
98
+
99
+ // File reading
100
+ $read1 = "readFileSync" ascii wide
101
+ $read2 = "readFile" ascii wide
102
+ $read3 = "createReadStream" ascii wide
103
+
104
+ // Network transmission
105
+ $net1 = "fetch(" ascii wide
106
+ $net2 = "axios" ascii wide
107
+ $net3 = "request(" ascii wide
108
+ $net4 = "https.request" ascii wide
109
+ $net5 = "http.request" ascii wide
110
+ $net6 = ".post(" ascii wide
111
+ $net7 = ".put(" ascii wide
112
+
113
+ condition:
114
+ any of ($ssh*) and any of ($read*) and any of ($net*)
115
+ }
116
+
117
+ rule STEALER_JS_Credential_File_Exfil_Jan25 {
118
+ meta:
119
+ description = "Detects credential file access (.npmrc, .env, .aws/credentials) combined with network exfiltration"
120
+ severity = "critical"
121
+ score = 90
122
+ author = "vsix-audit"
123
+ date = "2025-01-29"
124
+
125
+ strings:
126
+ // Credential files
127
+ $cred1 = ".npmrc" ascii wide
128
+ $cred2 = ".netrc" ascii wide
129
+ $cred3 = ".git-credentials" ascii wide
130
+ $cred4 = ".env" ascii wide
131
+ $cred5 = "credentials.json" ascii wide
132
+ $cred6 = ".aws/credentials" ascii wide
133
+
134
+ // File reading
135
+ $read1 = "readFileSync" ascii wide
136
+ $read2 = "readFile" ascii wide
137
+
138
+ // Network transmission
139
+ $net1 = "fetch(" ascii wide
140
+ $net2 = "axios" ascii wide
141
+ $net3 = ".post(" ascii wide
142
+ $net4 = "discord.com/api/webhooks" ascii wide
143
+
144
+ condition:
145
+ any of ($cred*) and any of ($read*) and any of ($net*)
146
+ }
147
+
148
+ rule STEALER_JS_Browser_Data_Theft_Jan25 {
149
+ meta:
150
+ description = "Detects browser credential and cookie theft pattern targeting Chrome/Firefox/Edge storage files"
151
+ severity = "critical"
152
+ score = 95
153
+ author = "vsix-audit"
154
+ date = "2025-01-29"
155
+
156
+ strings:
157
+ // Browser data paths
158
+ $chrome1 = "Chrome" ascii wide nocase
159
+ $chrome2 = "User Data" ascii wide nocase
160
+ $chrome3 = "Login Data" ascii wide nocase
161
+ $chrome4 = "Cookies" ascii wide nocase
162
+ $firefox1 = "Firefox" ascii wide nocase
163
+ $firefox2 = "logins.json" ascii wide nocase
164
+ $edge1 = "Edge" ascii wide nocase
165
+ $brave1 = "BraveSoftware" ascii wide nocase
166
+
167
+ // Storage paths
168
+ $storage1 = "Local Storage" ascii wide nocase
169
+ $storage2 = "leveldb" ascii wide nocase
170
+ $storage3 = "IndexedDB" ascii wide nocase
171
+
172
+ // File operations
173
+ $read1 = "readFileSync" ascii wide
174
+ $read2 = "copyFileSync" ascii wide
175
+ $read3 = "createReadStream" ascii wide
176
+
177
+ condition:
178
+ (2 of ($chrome*) or any of ($firefox*) or ($edge1 and $chrome3) or $brave1) and
179
+ any of ($storage*) and any of ($read*)
180
+ }
181
+
182
+ rule STEALER_JS_Env_Token_Exfil_Jan25 {
183
+ meta:
184
+ description = "Detects API token access from process.env variables combined with network transmission"
185
+ severity = "high"
186
+ score = 80
187
+ author = "vsix-audit"
188
+ date = "2025-01-29"
189
+
190
+ strings:
191
+ // Token environment variables
192
+ $env1 = "process.env.GITHUB_TOKEN" ascii wide
193
+ $env2 = "process.env.NPM_TOKEN" ascii wide
194
+ $env3 = "process.env.OPENAI_API_KEY" ascii wide
195
+ $env4 = "process.env.ANTHROPIC_API_KEY" ascii wide
196
+ $env5 = "process.env.AWS_SECRET" ascii wide
197
+ $env6 = "process.env.AZURE" ascii wide
198
+ $env7 = /process\.env\.[A-Z_]*(TOKEN|KEY|SECRET|PASSWORD)/ ascii wide
199
+
200
+ // Network transmission
201
+ $net1 = "fetch(" ascii wide
202
+ $net2 = "axios" ascii wide
203
+ $net3 = ".post(" ascii wide
204
+
205
+ condition:
206
+ any of ($env*) and any of ($net*)
207
+ }
@@ -0,0 +1,187 @@
1
+ /*
2
+ GlassWorm Google Calendar C2 Detection
3
+ Detects Google Calendar API usage for command and control fallback
4
+ Based on GlassWorm using Google Calendar as backup C2 channel
5
+ */
6
+
7
+ rule C2_JS_GlassWorm_Google_Calendar_Jan25 {
8
+ meta:
9
+ description = "Detects GlassWorm-style Google Calendar API usage for command and control fallback channel"
10
+ severity = "high"
11
+ score = "80"
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
+ // Google Calendar API
18
+ $google_calendar = "google-calendar" ascii wide
19
+ $calendar_api = "calendarApi" ascii wide
20
+ $gcal_api = "gcalApi" ascii wide
21
+ $calendar_google = "calendar.google" ascii wide
22
+
23
+ // Calendar API endpoints
24
+ $calendar_app = "calendar.app.google" ascii wide
25
+ $googleapis_calendar = "googleapis.com/calendar" ascii wide
26
+ $calendar_v3 = "calendar/v3" ascii wide
27
+ $calendar_events = "calendar/events" ascii wide
28
+
29
+ // Calendar authentication
30
+ $calendar_auth = "calendarAuth" ascii wide
31
+ $gcal_auth = "gcalAuth" ascii wide
32
+ $calendar_token = "calendarToken" ascii wide
33
+ $calendar_oauth = "calendarOAuth" ascii wide
34
+
35
+ // Calendar event access
36
+ $calendar_events_list = "calendarEvents" ascii wide
37
+ $event_list = "eventList" ascii wide
38
+ $get_events = "getEvents" ascii wide
39
+ $list_events = "listEvents" ascii wide
40
+
41
+ // Event parsing
42
+ $parse_events = "parseEvents" ascii wide
43
+ $event_parser = "eventParser" ascii wide
44
+ $calendar_parser = "calendarParser" ascii wide
45
+ $event_data = "eventData" ascii wide
46
+
47
+ condition:
48
+ // High confidence: Google Calendar API + event access + parsing
49
+ (any of ($google_calendar, $calendar_api, $gcal_api, $calendar_google, $calendar_app, $googleapis_calendar, $calendar_v3, $calendar_events)) and
50
+ (any of ($calendar_auth, $gcal_auth, $calendar_token, $calendar_oauth)) and
51
+ (any of ($calendar_events_list, $event_list, $get_events, $list_events, $parse_events, $event_parser, $calendar_parser, $event_data))
52
+ }
53
+
54
+ rule C2_JS_GlassWorm_Calendar_Commands_Jan25 {
55
+ meta:
56
+ description = "Detects GlassWorm-style calendar event parsing used to receive and execute C2 commands"
57
+ severity = "high"
58
+ score = "85"
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
+ // Event command parsing
65
+ $event_commands = "eventCommands" ascii wide
66
+ $calendar_commands = "calendarCommands" ascii wide
67
+ $parse_commands = "parseCommands" ascii wide
68
+ $command_parser = "commandParser" ascii wide
69
+
70
+ // Event data extraction
71
+ $event_summary = "eventSummary" ascii wide
72
+ $event_description = "eventDescription" ascii wide
73
+ $event_title = "eventTitle" ascii wide
74
+ $event_content = "eventContent" ascii wide
75
+
76
+ // Command execution from events
77
+ $execute_command = "executeCommand" ascii wide
78
+ $run_command = "runCommand" ascii wide
79
+ $command_exec = "commandExec" ascii wide
80
+ $exec_from_event = "execFromEvent" ascii wide
81
+
82
+ // Event monitoring
83
+ $monitor_events = "monitorEvents" ascii wide
84
+ $watch_events = "watchEvents" ascii wide
85
+ $event_watcher = "eventWatcher" ascii wide
86
+ $calendar_monitor = "calendarMonitor" ascii wide
87
+
88
+ // Event filtering
89
+ $filter_events = "filterEvents" ascii wide
90
+ $event_filter = "eventFilter" ascii wide
91
+ $command_filter = "commandFilter" ascii wide
92
+ $c2_filter = "c2Filter" ascii wide
93
+
94
+ condition:
95
+ // Detect event command parsing with execution capabilities
96
+ (any of ($event_commands, $calendar_commands, $parse_commands, $command_parser)) and
97
+ (any of ($event_summary, $event_description, $event_title, $event_content)) and
98
+ (any of ($execute_command, $run_command, $command_exec, $exec_from_event, $monitor_events, $watch_events, $event_watcher, $calendar_monitor, $filter_events, $event_filter, $command_filter, $c2_filter))
99
+ }
100
+
101
+ rule C2_JS_GlassWorm_Calendar_Backup_Jan25 {
102
+ meta:
103
+ description = "Detects GlassWorm-style calendar-based backup C2 mechanism with redundancy and failover patterns"
104
+ severity = "medium"
105
+ score = "70"
106
+ author = "vsix-audit"
107
+ date = "2025-01-29"
108
+ reference = "https://www.koi.security/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace"
109
+
110
+ strings:
111
+ // Backup C2 patterns
112
+ $backup_c2 = "backupC2" ascii wide
113
+ $fallback_c2 = "fallbackC2" ascii wide
114
+ $secondary_c2 = "secondaryC2" ascii wide
115
+ $alternate_c2 = "alternateC2" ascii wide
116
+
117
+ // C2 redundancy
118
+ $c2_redundancy = "c2Redundancy" ascii wide
119
+ $c2_backup = "c2Backup" ascii wide
120
+ $c2_failover = "c2Failover" ascii wide
121
+ $c2_resilience = "c2Resilience" ascii wide
122
+
123
+ // Calendar C2
124
+ $calendar_c2 = "calendarC2" ascii wide
125
+ $gcal_c2 = "gcalC2" ascii wide
126
+ $calendar_channel = "calendarChannel" ascii wide
127
+ $event_c2 = "eventC2" ascii wide
128
+
129
+ // C2 rotation
130
+ $c2_rotation = "c2Rotation" ascii wide
131
+ $c2_switch = "c2Switch" ascii wide
132
+ $c2_alternate = "c2Alternate" ascii wide
133
+ $c2_cycle = "c2Cycle" ascii wide
134
+
135
+ // C2 resilience
136
+ $c2_persistence = "c2Persistence" ascii wide
137
+ $c2_survival = "c2Survival" ascii wide
138
+ $c2_durability = "c2Durability" ascii wide
139
+ $c2_reliability = "c2Reliability" ascii wide
140
+
141
+ condition:
142
+ // Detect backup C2 with calendar integration
143
+ (any of ($backup_c2, $fallback_c2, $secondary_c2, $alternate_c2, $c2_redundancy, $c2_backup, $c2_failover, $c2_resilience)) and
144
+ (any of ($calendar_c2, $gcal_c2, $calendar_channel, $event_c2)) and
145
+ (any of ($c2_rotation, $c2_switch, $c2_alternate, $c2_cycle, $c2_persistence, $c2_survival, $c2_durability, $c2_reliability))
146
+ }
147
+
148
+ rule C2_JS_GlassWorm_Calendar_Exfil_Jan25 {
149
+ meta:
150
+ description = "Detects GlassWorm-style data exfiltration using calendar events with encoded payloads"
151
+ severity = "medium"
152
+ score = "75"
153
+ author = "vsix-audit"
154
+ date = "2025-01-29"
155
+ reference = "https://www.koi.security/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace"
156
+
157
+ strings:
158
+ // Event exfiltration
159
+ $event_exfil = "eventExfil" ascii wide
160
+ $calendar_exfil = "calendarExfil" ascii wide
161
+ $event_data_exfil = "eventDataExfil" ascii wide
162
+ $calendar_data_exfil = "calendarDataExfil" ascii wide
163
+
164
+ // Event creation for exfiltration
165
+ $create_event = "createEvent" ascii wide
166
+ $add_event = "addEvent" ascii wide
167
+ $insert_event = "insertEvent" ascii wide
168
+ $post_event = "postEvent" ascii wide
169
+
170
+ // Data encoding in events
171
+ $encode_in_event = "encodeInEvent" ascii wide
172
+ $event_encoding = "eventEncoding" ascii wide
173
+ $calendar_encoding = "calendarEncoding" ascii wide
174
+ $event_base64 = "eventBase64" ascii wide
175
+
176
+ // Event data patterns
177
+ $event_payload = "eventPayload" ascii wide
178
+ $event_data = "eventData" ascii wide
179
+ $calendar_payload = "calendarPayload" ascii wide
180
+ $event_content = "eventContent" ascii wide
181
+
182
+ condition:
183
+ // Detect event-based exfiltration with data encoding
184
+ (any of ($event_exfil, $calendar_exfil, $event_data_exfil, $calendar_data_exfil)) and
185
+ (any of ($create_event, $add_event, $insert_event, $post_event)) and
186
+ (any of ($encode_in_event, $event_encoding, $calendar_encoding, $event_base64, $event_payload, $event_data, $calendar_payload, $event_content))
187
+ }
@@ -0,0 +1,103 @@
1
+ /*
2
+ Messaging Platform C2 Detection
3
+ Detects use of messaging platforms (Telegram, Slack) for C2 and exfiltration
4
+ */
5
+
6
+ rule C2_JS_Telegram_Bot_Jan25 {
7
+ meta:
8
+ description = "Detects Telegram bot API used for C2 communication with command execution or system info gathering"
9
+ severity = "high"
10
+ score = 85
11
+ author = "vsix-audit"
12
+ date = "2025-01-30"
13
+
14
+ strings:
15
+ // Telegram API
16
+ $tg1 = "api.telegram.org" ascii wide
17
+ $tg2 = "/bot" ascii wide
18
+ $tg3 = "telegram" ascii wide nocase
19
+
20
+ // Bot methods
21
+ $method1 = "sendMessage" ascii wide
22
+ $method2 = "getUpdates" ascii wide
23
+ $method3 = "sendDocument" ascii wide
24
+ $method4 = "sendPhoto" ascii wide
25
+
26
+ // Command execution or system info (C2 indicators)
27
+ $exec1 = "child_process" ascii wide
28
+ $exec2 = ".exec(" ascii wide
29
+ $exec3 = ".spawn(" ascii wide
30
+ $exec4 = "execSync" ascii wide
31
+ $sys1 = "os.hostname" ascii wide
32
+ $sys2 = "os.userInfo" ascii wide
33
+ $sys3 = "os.platform" ascii wide
34
+ $sys4 = "process.env" ascii wide
35
+
36
+ condition:
37
+ any of ($tg*) and any of ($method*) and any of ($exec*, $sys*)
38
+ }
39
+
40
+ rule STEALER_JS_Telegram_Exfil_Jan25 {
41
+ meta:
42
+ description = "Detects Telegram API used for file exfiltration targeting sensitive credential paths like .ssh"
43
+ severity = "high"
44
+ score = 80
45
+ author = "vsix-audit"
46
+ date = "2025-01-30"
47
+
48
+ strings:
49
+ // Telegram API
50
+ $tg1 = "api.telegram.org" ascii wide
51
+ $tg2 = "/bot" ascii wide
52
+
53
+ // Document sending
54
+ $send1 = "sendDocument" ascii wide
55
+ $send2 = "sendFile" ascii wide
56
+ $send3 = "multipart/form-data" ascii wide
57
+
58
+ // File reading
59
+ $read1 = "readFileSync" ascii wide
60
+ $read2 = "readFile" ascii wide
61
+ $read3 = "createReadStream" ascii wide
62
+
63
+ // Sensitive paths
64
+ $path1 = ".ssh" ascii wide
65
+ $path2 = ".npmrc" ascii wide
66
+ $path3 = ".env" ascii wide
67
+ $path4 = "credentials" ascii wide
68
+ $path5 = ".aws" ascii wide
69
+ $path6 = ".git-credentials" ascii wide
70
+
71
+ condition:
72
+ any of ($tg*) and any of ($send*) and any of ($read*) and any of ($path*)
73
+ }
74
+
75
+ rule C2_JS_Slack_Webhook_Jan25 {
76
+ meta:
77
+ description = "Detects Slack webhook URL used for data exfiltration with system info or file access patterns"
78
+ severity = "high"
79
+ score = 75
80
+ author = "vsix-audit"
81
+ date = "2025-01-30"
82
+
83
+ strings:
84
+ // Slack webhook URL pattern
85
+ $slack1 = "hooks.slack.com/services" ascii wide
86
+ $slack2 = "hooks.slack.com" ascii wide
87
+ $slack3 = /T[A-Z0-9]{8,}\/B[A-Z0-9]{8,}\/[a-zA-Z0-9]{20,}/ ascii wide
88
+
89
+ // Data transmission
90
+ $send1 = "fetch(" ascii wide
91
+ $send2 = "axios" ascii wide
92
+ $send3 = ".post(" ascii wide
93
+ $send4 = "request(" ascii wide
94
+
95
+ // Data collection indicators
96
+ $data1 = "JSON.stringify" ascii wide
97
+ $data2 = "process.env" ascii wide
98
+ $data3 = "os.hostname" ascii wide
99
+ $data4 = "readFileSync" ascii wide
100
+
101
+ condition:
102
+ any of ($slack*) and any of ($send*) and any of ($data*)
103
+ }