upload-labs详解(1-12)文件上传分析
目录
uploa-labs-main
upload-labs-main第一关
前端防御
绕过前端防御
禁用js
Burpsuite抓包改包
upload-labs-main第二关
上传测试
错误类型
upload-labs-env
upload-labs-env第三关
上传测试
查看源码
解决方法
重命名,上传
upload-labs-env第四关
测试方法
上传文件
upload-labs-env第五关
代码解析
解题思路——大小写绕过
upload-labs-env第六关
代码
空格绕过
upload-labs-env第七关
代码
绕过
upload-labs-env第八关
::$DATA 绕过
upload-labs-env第九关
代码
思路
upload-labs-env第十关
代码
双写绕过
upload-labs第-env十一关
代码
思路——00截断问题(只存在于php5.2版本中)——get传参(url编码方式)
upload-labs-env第十二关
代码
思路——00截断——save_path是post传参
uploa-labs-main
upload-labs-main第一关
前端防御

有一个过滤函数checkFile()

绕过前端防御
禁用js
Chrome禁用js
设置—隐私与安全—网站设置—内容—JavaScript—不允许网站使用JavaScript

再次尝试上传,成功

Burpsuite抓包改包
首先为文件进行重命名,shell.php重命名为shell.jpg
上传shell.jpg文件
Burpsuite打开抓包
网页点击确定上传,

发送到重放器,改包,将shell.jpg改为shell.php,重新发送,上传成功

upload-labs-main第二关
上传测试

错误类型
文件类型不正确,
使用Burpsuite抓包改包

修改为image/png

上传成功
upload-labs-env
upload-labs-env第三关
上传测试

查看源码
$is_upload = false;$msg = null;if (isset($_POST['submit'])) {if (file_exists(UPLOAD_PATH)) {$deny_ext = array('.asp','.aspx','.php','.jsp');//定义一个数组$deny_ext,包含不允许上传的文件扩展名$file_name = trim($_FILES['upload_file']['name']);$file_name = deldot($file_name);//删除文件名末尾的点$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空if(!in_array($file_ext, $deny_ext)) {$temp_file = $_FILES['upload_file']['tmp_name'];//获取上传文件的临时路径,文件在服务器上以临时文件的形式存储$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file,$img_path)) {$is_upload = true;} else {$msg = '上传出错!';}} else {$msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}}
分析源码
需要绕过黑名单的过滤
.php3 、Phtml等都可以被解析
需要修改Apache的配置文件httpd.conf,使.php3 .phtml也可以被解析,当Apache和php版本低时,服务端可以修改
在配置文件中添加
AddType application/x-httpd-php .phtml
重启Apache
注意:在靶场实验中可能存在这个漏洞,真实项目中不会存在
解决方法
黑名单绕过
在upload-labs-env原版环境中,Apache的配置文件httpd.conf有将 .php3 .phtml解析成php文件

重命名,上传
上传成功

解析成功

upload-labs-env第四关
测试方法
需要.htaccess文件
我们下载upload-labs-env原版环境,自带phpstudy的低版本
在Apache的低版本中,如果在目录中上传一个.htaccess文件
AddType application/x-httpd-php .jpg
会将后来上传的jpg文件解析成php,shell代码得以执行
上传文件

解析成功

upload-labs-env第五关
代码解析
$is_upload = false;
$msg = null;# isset - 检测变量是否已经声明并且不为空
# $_POST['submit'] - 表示表单中名为 submit 的按钮被点击
if (isset($_POST['submit'])) {# file_exists — 检查文件或目录是否存在返回值为true或falseif (file_exists(UPLOAD_PATH)) {# 定义一个数组 $deny_ext,包含一系列禁止上传的文件扩展名$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");# trim — 去除字符串首尾处的空白字符(或者其他字符)# $_FILES['upload_file'] 是表单中 name="upload_file" 对应的上传文件信息# 它包含以下常见字段:# $_FILES['upload_file']['name']:上传文件的原始名称(如 example.jpg)。# $_FILES['upload_file']['type']:上传文件的 MIME 类型(如 image/jpeg)。# $_FILES['upload_file']['size']:上传文件的大小(以字节为单位)。# $_FILES['upload_file']['tmp_name']:上传文件的临时存储路径。# $_FILES['upload_file']['error']:与文件上传相关的任何错误代码$file_name = trim($_FILES['upload_file']['name']);$file_name = deldot($file_name);//删除文件名末尾的点#strrchr — 查找指定字符在字符串中的最后一次出现的位置,返回从最后一个点开始到字符串末尾的部分$file_ext = strrchr($file_name, '.');#str_ireplace - 执行不区分大小写的字符串替换,在目标字符串中查找指定的子字符串(无视大小写),然后用另一个字符串替换它$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空#in_array — 检查数组中是否存在某个值,检查数组$deny_ext中是否存在$file_extif (!in_array($file_ext, $deny_ext)) {# $_FILES['upload_file']['tmp_name']:上传文件的临时存储路径。$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;#move_uploaded_file — 将上传的文件移动到新位置if (move_uploaded_file($temp_file, $img_path)) {$is_upload = true;} else {$msg = '上传出错!';}} else {$msg = '此文件类型不允许上传!';}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}
}
解题思路——大小写绕过
文件后缀大写绕过
上传.php文件
修改后缀名为.PHP
上传成功
解析执行

upload-labs-env第六关
代码
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");$file_name = $_FILES['upload_file']['name'];$file_name = deldot($file_name);//删除文件名末尾的点$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
空格绕过
文件名后缀加空格绕过

upload-labs-env第七关
代码
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");$file_name = trim($_FILES['upload_file']['name']);$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空
绕过
文件后缀名后加点

upload-labs-env第八关
::$DATA 绕过

upload-labs-env第九关
代码
没有对代码进行重命名拼接路径
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {if (file_exists(UPLOAD_PATH)) {$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");$file_name = trim($_FILES['upload_file']['name']);$file_name = deldot($file_name);//删除文件名末尾的点$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空if (!in_array($file_ext, $deny_ext)) {$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH.'/'.$file_name;if (move_uploaded_file($temp_file, $img_path)) {$is_upload = true;} else {$msg = '上传出错!';}} else {$msg = '此文件类型不允许上传!';}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}
}

思路
deldot()函数从后向前检测,当检测到末尾的第一个点时会继续它的检测,但是遇到空格会停下来
更改文件名为 index.php. . 即.php点 空格 点
运行php时,首先删除文件名末尾的点,
...... ,
最后一步检查,去除最后的空格,
此时文件名为index.php.
上传到Windows环境中时,系统会将其视为一个没有扩展名的文件,
Windows会将 index.php. 解释为没有扩展名的文件,因为末尾的点会被忽略。文件的实际名称会变成 index.php,但扩展名会被视为不存在

upload-labs-env第十关
代码
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {if (file_exists(UPLOAD_PATH)) {$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");$file_name = trim($_FILES['upload_file']['name']);$file_name = str_ireplace($deny_ext,"", $file_name);$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) {$is_upload = true;} else {$msg = '上传出错!';}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}
}
使用str_ireplace()函数寻找文件名中存在的黑名单字符串,将它替换成空(即将它删掉),可以使用双写绕过黑名单
双写绕过

upload-labs第-env十一关
代码
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){$ext_arr = array('jpg','png','gif');//$_FILES['upload_file']['name']:获取上传文件的原始文件名//strrpos($_FILES['upload_file']['name'], "."):查找文件名中最后一个点(.)的位置//substr(..., strrpos(...) + 1):从最后一个点的下一个字符开始截取,得到文件扩展名$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);if(in_array($file_ext,$ext_arr)){//$_FILES['upload_file']['tmp_name']:获取上传文件的临时存储路径$temp_file = $_FILES['upload_file']['tmp_name'];//$_GET['save_path']:从 URL 参数中获取保存路径//rand(10, 99):生成一个 10 到 99 之间的随机数//date("YmdHis"):生成当前日期时间字符串,格式为 年月日时分秒//最终路径格式:保存路径/随机数+时间戳.扩展名$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;if(move_uploaded_file($temp_file,$img_path)){$is_upload = true;} else {$msg = '上传出错!';}} else{$msg = "只允许上传.jpg|.png|.gif类型文件!";}
}
思路——00截断问题(只存在于php5.2版本中)——get传参(url编码方式)
在c语言中\0是结束符
php底层是运行c语言
使用\0使截断代码,使后面代码不再运行

使用的传递方式是urlcode传参,%00使用url解码后为空字符
当一个字符串中存在空字符的时候,在被解析的时候会导致空字符后面的字符被丢弃
当php代码运行到
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;if(move_uploaded_file($temp_file,$img_path)){
时,路径变成了/upload/web.php 后面的连接字符都被丢弃了,
之后将文件上传文件index.jpg的文件内容移动到web.php中,这样恶意代码就可以被解析了
upload-labs-env第十二关
代码
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){$ext_arr = array('jpg','png','gif');$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);if(in_array($file_ext,$ext_arr)){$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;if(move_uploaded_file($temp_file,$img_path)){$is_upload = true;} else {$msg = "上传失败";}} else {$msg = "只允许上传.jpg|.png|.gif类型文件!";}
}
思路——00截断——save_path是post传参
0x00 是十六进制表示的空字符(ASCII 值为 0)


在web.php后面加一个空格,在Burpsuite的hex转换中,找到这个空格(十六进制空格的编码为20)
将其修改为十六进制的空字符表示00

修改后

发送

相关文章:
upload-labs详解(1-12)文件上传分析
目录 uploa-labs-main upload-labs-main第一关 前端防御 绕过前端防御 禁用js Burpsuite抓包改包 upload-labs-main第二关 上传测试 错误类型 upload-labs-env upload-labs-env第三关 上传测试 查看源码 解决方法 重命名,上传 upload-labs-env第四关…...
RAG系统(检索增强生成)的优化策略
RAG(检索增强生成)系统的优化可以从多个方面入手,主要包括数据、查询、检索、生成、框架和评估等几个重要环节。本文将详细介绍这些优化策略,并为每个环节提供具体的操作方法。 一、数据优化 1. 数据清洗和增强 数据质量直接影响检索和生成的效果,因此需要进行细致的数据…...
写毕业论文用哪个AI好?这6款AIGC论文工具给你答案
撰写毕业论文是一项艰巨的任务,AIGC 论文工具的出现为同学们提供了有力支持。以下 6 款工具在功能、适用场景等方面各有优势,助你高效完成毕业论文。 文赋 AI 论文 文赋 AI 论文堪称毕业论文写作的得力助手。它的生成速度令人惊叹,短短 5 分…...
loadingcache优化
问题分析 通过当前现场的火焰图进行分析 原本的loadingcache public LoadingCache<Integer, Student> map Caffeine.newBuilder().refreshAfterWrite(CONTRACT_CACHE_HOURS, TimeUnit.HOURS).maximumSize(CONTRACT_CONFIG_CACHE_SIZE).recordStats().build(key -> …...
【Vue3 Element UI - Plus + Tyscript 实现Tags标签输入及回显】
Vue3 Element Plus TypeScript 实现 Tags 标签输入及回显 在开发后台管理系统或表单页面时,动态标签(Tags) 是一个常见的功能需求。用户可以通过输入框添加标签,并通过关闭按钮删除标签,同时还需要支持标签数据的提…...
STM32 子设备通过CAN发送数据到主设备
采集ADC、GPS经纬坐标、温湿度数据、大气压数据通过CAN方式发送给主设备端,帧ID按照如下定义: 我尼玛一个标准帧ID位数据是11位,扩展帧才是111829位,它说最开头的是四位是真类型,并给我如下解释: 它把帧的定…...
Python可视化——地理空间型图表(自用)
地图信息可视化的实现就是将不可展开的曲面上的地理坐标信息转化为二维平面进行显示,这个过程也叫地图投影(空间三维投影到平面二维) 地图投影的要求:等面积、等角度、等距离。总的来说就是映射到二维平面中的任何点通过比例尺放大…...
WordPress报502错误问题解决-php-fpm-84.service loaded failed failed LSB: starts php-fpm
文章目录 问题描述问题排查问题解决 问题描述 服务器环境: php:8.4MySQL:8.0Nginx:1.26.2 在访问站点时,一直报502,而两天前还能正常访问。 问题排查 导致502的问题很多,比如站点访问量太大…...
Python在SEO中的自动化应用爬虫开发与日志分析实例
引言 搜索引擎优化(SEO)是数字营销中至关重要的一环,旨在提高网站在搜索引擎结果页面(SERP)中的排名。随着互联网数据的爆炸式增长,手动进行SEO分析和管理变得愈发困难。Python作为一种强大的编程语言&…...
thingsboard edge 在windows 环境下的配置
按照官方文档:Installing ThingsBoard Edge on Windows | ThingsBoard Edge,配置好java环境和PostgreSQL。 下载对应的windows 环境下的tb-edge安装包。下载附件 接下来操作具体如下 步骤1,需要先在thingsboard 服务上开启edge 权限 步骤2…...
nnMamba:基于状态空间模型的3D生物医学图像分割、分类和地标检测
摘要 本文提出了一种基于状态空间模型(SSMs)的创新架构——nnMamba,用于解决3D生物医学图像分割、分类及地标检测任务中的长距离依赖建模难题。nnMamba结合了卷积神经网络(CNN)的局部特征提取能力与SSMs的全局上下文建…...
nginx 配置403页面(已亲测)
问题:GET请求访问漏洞url即可看到泄露的内网ip 解决方式: 1.配置nginx 不显示真实Ip 2.限制接口只能是POST请求 具体配置: 编写一个403.html 在nginx的配置文件中,配置location参数: location /api/validationCode…...
SyntaxError: Invalid or unexpected token in JSON at position x
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 🍚 蓝桥云课签约作者、…...
Uncaught TypeError: Cannot read properties of undefined (reading ‘xxx‘)
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 🍚 蓝桥云课签约作者、…...
Nginx 跨域配置详细讲解
一、跨域请求概述 跨域资源共享(CORS,Cross-Origin Resource Sharing)是一种机制,它使用额外的HTTP头部来告诉浏览器让运行在一个origin(域)上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资…...
前端开发基石:HTML语义化深度解析与实践指南
一、语义化设计的本质价值 1.1 从文档结构到信息表达 在Web诞生初期(1991年),HTML仅包含18个标签用于学术文档展示。经过30年发展,HTML5已拥有超过110个标签,其中语义化标签占比提升至60%。这种演进背后是互联网从简…...
mongodb安装教程以及mongodb的使用
MongoDB是由C语言编写的一种面向文档的NoSQL数据库,旨在为WEB应用提供可扩展的高性能数据存储解决方案。与传统的关系型数据库(如 MySQL 或 PostgreSQL)不同,MongoDB 存储数据的方式是以 BSON(类似于 JSON 的二进制格式…...
C# 中的多线程同步机制:lock、Monitor 和 Mutex 用法详解
在多线程编程中,线程同步是确保多个线程安全地访问共享资源的关键技术。C# 提供了几种常用的同步机制,其中 lock、Monitor 和 Mutex 是最常用的同步工具。本文将全面介绍这三种同步机制的用法、优缺点以及适用场景,帮助开发者在多线程开发中做…...
【通义万相】蓝耘智算 | 开源视频生成新纪元:通义万相2.1模型部署与测评
【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈人工智能与大模型应用 ⌋ ⌋ ⌋ 人工智能(AI)通过算法模拟人类智能,利用机器学习、深度学习等技术驱动医疗、金融等领域的智能化。大模型是千亿参数的深度神经网络(如ChatGPT&…...
期权帮|中证1000股指期权交割结算价怎么算?
期权帮锦鲤三三每日分享期权知识,帮助期权新手及时有效地掌握即市趋势与新资讯! 中证1000股指期权交割结算价怎么算? 一、按照最后交易日结算价: (1)计算方法:最后交易日标的指数(…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...
