Bug2Lab · Secure Code · Java / Spring MVC

IDOR: доступ к чужому объекту по чужому ID

Пользователь меняет числовой идентификатор в URL и получает чужие данные. Приложение не проверяет «а это вообще его ресурс?» — только то, что ресурс существует. Фикс — проверять владение.

1
Как выглядит атака
Клиент с токеном пользователя А делает:
GET /api/order/98273
потом просто меняет ID:
/api/order/98274
и видит заказ другого клиента.
GET /api/order/98274
200 OK (application/json)
{
 "orderId":98274,
 "email":"vip.customer@corp.example",
 "total":"12999.00",
 "cardLast4":"7742"
}
2
Почему это стало возможным
Контроллер получает orderId и возвращает заказ без проверки, принадлежит ли он текущему пользователю.
Проблемный код
21@GetMapping("/api/order/{id}")
22public OrderDto getOrder(@PathVariable Long id) {
23 return orderService.findById(id); // ❌ нет проверки владельца
24}
3
Как это чинится правильно
Вместо «дай заказ по ID» нужно «дай заказ этого пользователя по ID». То есть проверка владения ресурса.
Исправленный паттерн
21@GetMapping("/api/order/{id}")
22public OrderDto getOrder(@PathVariable Long id, Principal principal) {
23 String username = principal.getName();
24 return orderService.findByIdAndUsername(id, username); // ✅ проверка владельца
25}

bug2regressРегрессионный тест

Тест использует токен обычного пользователя и пытается прочитать заказ, принадлежащий другому пользователю. Ожидаем 403 / 404. Если 200 — билд стопаем.

#!/bin/bash
# idor-check.sh
TOKEN_USER_A="Bearer userA-token"
FOREIGN_ORDER_ID=98274

STATUS=$(curl -s -o /tmp/order.json -w "%{http_code}" \
  -H "Authorization: $TOKEN_USER_A" \
  "https://staging.example.internal/api/order/$FOREIGN_ORDER_ID")

if [ "$STATUS" = "200" ]; then
  echo "[BLOCK] IDOR: пользователь читает чужой заказ ($FOREIGN_ORDER_ID)"
  exit 1
fi

echo "[OK] Чужие объекты недоступны (HTTP $STATUS)"
exit 0

Это защищает личные данные клиентов и финансовую информацию.

Проверка пониманияЧто было не так?

Стандарт:доступ к объекту = проверка владения. Любой ресурс «по ID» обязан быть «по ID + текущий пользователь».

Теория (по желанию) IDOR = «а я могу посмотреть чужой заказ? да, могу»