IQAlcoholFarm

$ IQAlcoholFarm [Paid] 1.3.38

Sempai

Admin
Команда форума
Администратор
VIP
12 Май 2022
5,516
902
30
43,239

Суть проблемы​

Консольная команда func.alcohol (обрабатывает клики по UI магазина NPC) регистрируется без какой-либо проверки прав или источника вызова - доступна любому подключённому игроку через игровую консоль (F1), не только через клик по кнопке в интерфейсе.

Ветка category selling <Category> amount.buy <Y> <Page> <Amount> парсит Amount через Int32.Parse без ограничения диапазона (только if (Amount == 0) return;) , а метод BuyItem() вообще не проверяет, хватает ли у игрока предмета-цены - снятие валюты (TakeItems) и выдача товара (GiveItem) выполняются безусловно. Проверка достатка (HaveItem) в коде существует, но вызывается только для подсветки кнопки в UI - это чисто визуальная подсказка клиенту, сервер её не перепроверяет при реальном исполнении команды.

Как эксплуатируется​

Игрок вручную вводит в консоль:

func.alcohol category selling Exchanger amount.buy 0 0 -1000000

(индекс/страница/категория подбираются под нужный товар в конфиге).

Что происходит внутри TakeItems: при отрицательном Amount итоговый TargetAmount (цена × количество) становится отрицательным. Условие if (use.amount > TargetAmount) из-за этого выполняется всегда (любое положительное число больше отрицательного), и код делает:

use.amount -= TargetAmount; // при TargetAmount < 0 это фактически += |TargetAmount|

То есть вместо списания валюты стек предмета-цены у игрока раздувается на произвольную величину - достаточно иметь всего 1 штуку нужного предмета в инвентаре.

Даже без отрицательных чисел: если просто вызвать amount.buy с большим Amount, не имея вообще валюты, TakeItems спишет только то, что реально есть (может не хватить или быть 0), но GiveItem всё равно выдаст полный объём товара - оплата не обязательна.

Что в итоге​

Полноценный дюп любого предмета, назначенного как "цена" в категориях EquipmentCategory/ExchangerCategory (по дефолтному конфигу - scrap, water.salt/алкоголь), плюс бесплатное получение товаров из магазина (оружие, hazmat и т.д. в Exchanger-категории). Уязвимость эксплуатируется без прав администратора, без взаимодействия с самим NPC — чистый консольный вызов.

Как я это исправил у себя​

  1. В обработчике команды (FuncionalCommad, ветка "selling"): Amount валидируется в диапазон 1..1000 (константа MaxBuyAmount), Y/Page - проверяются на выход за границы фактического списка товаров на странице, до этого возможен был и IndexOutOfRangeException на кривом Y.
  2. В BuyItem(): перед TakeItems/GiveItem добавлена серверная проверка HaveItem(player, PriceItems.Shortname, PriceItems.Amount * Amount, PriceItems.SkinID) - если у игрока реально нет нужного количества, покупка просто не выполняется.
Исправлю