一、前言 根据“天问”平台的监测分析,在2023年2月份,共发现了261 个npm恶意包。这些恶意包中,依赖混淆攻击仍然持续不断,攻击者利用简单的npm包来窃取和收集可被攻击对象的敏感信息。此外,还有一些攻击者针对Windows平台精心构造了木马病毒。通过一个伪装的程序崩溃页面,诱导用户下载安装包含木马后门的flash安装包。一旦安装运行后,攻击者可以持续地控制受害者主机。
二、分析 2.1 持续的依赖混淆攻击 在2023年2月,针对npm生态的依赖混淆攻击屡屡发生。例如恶意npm包micro-username
在package.json的scripts字段中直接嵌入恶意代码。这种做法在npm生态的软件供应链攻击中已经是非常常见且频繁的。scripts字段中定义的preinstall内容会在安装时自动以shell环境执行,攻击者滥用了npm的这一点特性来进行攻击。而在这个恶意包中,攻击者将受害者主机的名称和用户名称发送至远程接收服务器。
除此之外,这一类的恶意包中往往还包含了攻击者的一些描述声明,表明自己是进行所谓的“安全测试”或者“安全研究”。例如在包micro-username
中就包含了一串描述字符:“Simple PoC package for testing for dependency confusion vulnerabilities.”,攻击者试图表明该包是用来证明和测试依赖混淆漏洞的。
然而,出于安全研究的道德考量,这种行为是不被认可的。因此,在分析过程中,只要npm包中包含了可能会危及用户机器的行为(比如收集敏感信息等),都被认为是恶意的。
随着依赖混淆攻击的持续进行,不同的攻击者会使用不同的域名来进行信息的收集,除了以往常见的域名外,在本月的恶意包分析中还发现了以下几个新增的域名:
1 2 3 4 5 6 7 8 9 curetosec.online oast.live oast.site oast.me ident.me vabch.org lupin.monster tirvax.com bind9-or-callback-server.com
2.2 针对Windows平台的恶意攻击 2023年2月3日,攻击者cq0km9hu
上传了一个名为aabquerys
的恶意包,在该恶意包仅有一个被严重混淆后名为jquery.js
文件。
经过反混淆分析后,发现该JavaScript文件会伪装出一个程序崩溃后的crash页面,诱使用户点击“安装兼容程序”按钮,实际上会从攻击者的远程服务器下载木马后门,并将其执行。此外,该文件还会检测用户的操作系统平台,只有在PC端才会执行,否则会弹出错误提示信息“此插件仅支持在电脑端安装”。从上述行为可以看出,该恶意程序具有明确的目的性和针对性。
根据分析,从远程服务器下载的恶意样本为Windows PE文件,其伪装成flash安装包并在受害者主机上执行一系列恶意操作。经过天穹沙箱分析平台的深入分析,发现该恶意样本采用Inno Setup Module
工具进行打包伪装。执行后,该样本将再次下载一个名为demon.bin
的远程控制木马。据分析,该木马是基于一个开源远程控制开发框架Havoc
开发而成。通过该木马,受害者主机会连接到远程C2,并进一步受到恶意指令的攻击。更为详细的分析结果可以参考天穹沙箱报告 。
需要注意的是,恶意包中并没有自动执行混淆的JavaScript脚本。根据天问供应链依赖分析平台的查询结果,在整个npm生态中也没有任何依赖使用该恶意包,该恶意包的名称aabquerys
和一个正常包的名称abquery
较为相似,这是一个在JQuery基础上再次开发的第三方库。恶意包内唯一一个文件以jquery.js
命名并导出,我们推测,攻击者可能利用了一些jQuery开发人员的输入错误,从而引入该npm包,并触发其恶意行为。
此外,通过分析该npm包上传者的帐号,我们发现攻击者使用了一个@bestdefinitions.com的匿名邮箱。进一步检索使用该邮箱发布的npm包,我们发现其他两个疑似相同作者的恶意包,分别是aabquery
和nvm_jquery
。这两个包使用了相同的混淆方式,但攻击逻辑略有不同,我们猜测这可能是攻击者在本地测试用的包。
附录 2023年2月恶意包名称汇总如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 hellosign-embedded-cla@8.0.2 bykea_node_boilerplate@2.0.1 mypy-action@6.0.2 mypy-action@8.0.2 swisspost@99.99.99 buildin@99.99.1 nayduck@99.99.97 nayduck@99.99.96 dwolla-algolia-search@50.50.50 dwolla-algolia-search@50.50.60 browser-abc@99.99.99 browser-main@99.99.99 browser-main-obj-redirect@99.99.99 browser-main-unmodified@99.99.99 common-dep-required@99.99.99 bundle-dep@99.99.99 mk1@99.99.99 nested-export@99.99.99 typecommon@99.99.99 nested-file@99.99.99 symlink-peer@99.99.99 erc1400@99.99.99 abacus-cmdline@99.99.99 buildin@99.99.2 zsbpwebsdktest@9999.99.9 zsbpwebsdktest@9999.99.91 zsbpwebsdktest@9999.99.92 zsbpwebsdktest@9999.99.93 zsbpwebsdktest@9999.99.94 eslint-plugin-indeed@99.99.9 texture-allocator@99.99.99 editor-layer-index@99.99.99 jumflot@99.99.99 compositionupdate@88.8.8 rb-web-info-component@99.99.99 zsbpwebsdktest3@9999.999.99 zsbpwebsdktest3@9999.999.990 zsbpwebsdk@9999.99.1 zsbpsdk@9999.99.1 zsbpsdk@9999.999.100 zsbpwebsdk@9999.999.100 editor-layer-index@99.99.80 texture-allocator@99.99.80 use-sync-external-store-shim@1.0.0 use-sync-external-store-shim@1.0.1 flp_all@1.0.0 micro-username@2.0.6 micro-username@2.0.9 micro-username@2.1.0 micro-username@2.1.1 micro-username@2.1.2 micro-username@2.1.3 commentrating@99.9.1 twinmotion@99.1.1 diesel-site@99.9.1 dist-web@99.1.1 plain-function@20.1.1 egs-trusted-domains@99.2.1 allianz-icons@7.999.9 allianz-icons@8.999.7 egstore-carousel@99.2.1 allianz-icons@8.999.4 allianz-icons@8.999.3 allianz-icons@8.999.6 allianz-icons@8.999.5 proton-account@99.99.999 proton-pack@99.99.9999 allianz-icons@9.999.2 allianz-icons@8.999.8 vpro-dev@1.0.0 minify_flp@1.0.0 @gumtree/ui-library@10.0.0 @gumtree/ui-library@0.5.0 @gumtree/ui-library@5.0.0 @gumtree/ui-library@30.0.0 @gumtree/ui-library@20.0.0 @gumtree/ui-library@0.4.0 @gumtree/ui-library@0.2.0 @gumtree/ui-library@0.1.0 @gumtree/ui-library@1.0.0 @gumtree/ui-library@0.3.0 ftvi-meteo-frontend@0.21.0 ftvi-meteo-frontend@0.20.0 ftvi-meteo-frontend@0.20.1 testneb@1.0.1 action-destinations@70.0.2 action-destinations@70.0.3 instantsearch-web@3.2.15 testnebb@1.0.1 micro-username@2.1.4 recurly-dev@6.0.5 apache2@1.1.9 micro-username@2.1.5 micro-username@2.1.6 micro-username@2.1.7 micro-username@2.1.8 micro-username@2.1.9 micro-username@2.2.0 jquery-impromtu@1.0.0 smart-commons@19.6.1 smart-commons@9.6.1 egstore-carousel@99.2.2 commentrating@99.9.3 twinmotion@99.1.2 dist-web@99.1.2 plain-function@20.1.2 diesel-site@99.9.2 @chegg/wtai-upload-widget@9.999.2 reporter-app-dist@1.0.0 reporter-app-dist@1.0.1 reporter-app-dist@1.1.1 @chegg/wtai-upload-widget@9.999.8 @chegg/wtai-upload-widget@9.999.7 saddlebag-event-logger@5.0.0 skyscanner-themes@5.0.0 testingforbug855@1.1.1 capacity-planning-projection@9.1.3 eslint-config-bayzat@50.1.1 virgil-spring-boot-starter@20.0.0 another-dev-dependency2@3.0.0 fusion-cli-tests@0.0.0-monorepo not-a-real-project@0.0.0 not-a-real-dep@0.0.0 proton-account@99.99.9999 proton-pack@99.9999.9999 hackerone2222@1.0.0 azure-rest-api-specs-tests@1.0.0 fe-core-components-vuejs@0.15.0 fe-core-components-vuejs@0.14.1 jquery-mask@99.0.0 jquery-mask@1.7.7 mobile-kohana@68.0.0 nokia-smp@1.0.2 prize-market@1.999.0 prize-market@2.999.0 prize-market@3.999.0 prize-market@4.999.0 prize-market@5.999.0 prize-market@6.999.0 flow-faucet@5.999.0 flow-faucet@1.999.0 flow-faucet@2.999.0 flow-faucet@3.999.0 flow-faucet@4.999.0 flow-faucet@6.999.0 flow-faucet@7.999.0 flow-faucet@8.999.0 flow-faucet@9.999.0 flow-faucet@10.999.0 prize-market@7.999.0 prize-market@8.999.0 prize-market@9.999.0 prize-market@10.999.0 transparent-proxy@1.11.0 bnjuilopjhgthtyi@99.99.99 kuna-chart-header@1.999.0 kuna-chart-header@2.999.0 kuna-chart-header@3.999.0 kuna-chart-header@4.999.0 kuna-chart-header@5.999.0 kuna-chart-header@6.999.0 kuna-chart-header@7.999.0 kuna-chart-header@8.999.0 kuna-chart-header@9.999.0 kuna-chart-header@10.999.0 asc-deps@0.0.1 ban-notifier4@1.0.0 dc-preview-utils@99.0.0 dc-preview-utils@99.0.1 azure-sp@3.0.0 xsstesttttttttt@1.0.1 zsbpwebsdktest2@9999.9.9 xsstesttttttttt@1.0.3 ban-notifier6@1.0.1 seaport_v1_2@99.0.0 seaport_v1_2@1.0.0 @pagseguro/pagseguro-utils-test@1.999.1 @pagseguro/pagseguro-utils@9.99.9 @pagseguro/pagseguro-utils@3.10.9 @pagseguro/pagseguro-utils@3.99.9 idcs-dialog@1.0.0 idcs-dialog@1.2.0 notebooklanguageserver@3.0.0 kiosk-util@9999.9999.9998 legal-footer@9999.9999.9998 multivariate-experiments@9999.9999.9998 privacy-mask@9999.9999.9998 theme-next@9999.9999.9998 theme-next@9999.9999.9999 privacy-mask@9999.9999.9999 multivariate-experiments@9999.9999.9999 legal-footer@9999.9999.9999 kiosk-util@9999.9999.9999 spectra-ui-commons@35.0.0 transparent-proxy@1.11.1 transparent-proxy@1.11.2 transparent-proxy@1.11.3 miro-api-clients@8.0.5 transparent-proxy@1.11.4 transparent-proxy@1.11.5 transparent-proxy@1.11.6 transparent-proxy@1.11.7 eg-affiliates-common@1.0.2 eg-affiliates-common-test@0.0.2 confusedatma@4.0.0 confusedatma@6.0.0 vmw-atk@1.0.0 zsbpwebsdktest3@9999.9.9 zsbpwebsdk@9999.9.1 zsbpwebsdk@9999.9.2 @doccledev/pattern-library@5.0.99 tempomati-omega-3@1.0.0 tempomati-omega-5-emcuf31@1.0.0 tempomati-omega-5-emcuf31@1.0.1 tempomati-omega-5-emcuf311@1.0.1 tempomati-omega-5-emcuf2@1.0.1 tempomati-omega-5-emcuf5@1.0.1 tempomati-omega-69-emcuf8@1.0.0 tempomati-omega-69-emcuf7@1.0.0 apomakqyr3@1.0.0 stateful-fastclick@1.0.0 sapling-output-plugin@1.0.0 piercing-library@1.0.0 tempomatrce3@1.0.0 common-dep-target@1.0.0 hackity@1.0.0 myattenuator@1.0.0 typeparsers@1.0.0 react-test-renderer-17@1.0.0 webpack-dev-server.legacy@1.0.0 webpack-cli.legacy@1.0.0 spectra-ui-commons@16.3.8 micro-username@1.0.5 micro-username@1.0.9 micro-username@1.4.0 micro-username@1.5.0 @appdirect/public-custom-app-ui@0.0.9 micro-username@2.0.4 micro-username@2.0.5 wf-extract-text-in-image2@1.0.0 wf-extract-text-in-image2@1.0.1 wf-extract-text-in-image2@1.0.2 wf-extract-text-in-image2@1.0.3 @nobixe9651/ng-fds@1.0.2 eslint-plugin-dropbox-sign@99999.1.0 eslint-plugin-dropbox-sign@99999.1.1 eslint-plugin-dropbox-sign@99999.1.2 opbox-web@99.0.0 opbox@99.0.0 opbox-seller-shop-service@99.0.0 fkletbbpoc@0.0.1 staging-opbox-web-browser@99.0.0 ifoodshop-react-ui@99.0.0 eslint-plugin-dropbox-sign@999999999999999.0.0 nvm_jquery@1.0.0 nvm_jquery@1.0.1 nvm_jquery@1.0.2 aabquery@1.0.0 aabquerv@1.0.1 aabquerys@1.0.0 aabauervs@1.0.1