Area: mobieusMarket / BBS (audit p3) · Surface: mobieusMarket /market/{slug}/mark-sold + /market/{slug}/feedback · Dimension: security · Severity: major
OWASP A01 Broken Access Control / business-logic abuse. Any authenticated user can damage a victim's marketplace trade reputation: (1) create a free listing, (2) POST /market/{slug}/mark-sold with buyer_username=<victim>, (3) POST /market/{slug}/feedback with target_user_id=<victim's id> and rating=-1 plus a defamatory body. The victim never bought anything and never consented. The forged negative feedback shows on their public /market/user/<victim>/feedback page and decrements their positive-ratio reputation badge. There is no two-sided confirmation of a sale anywhere in the flow.
Evidence
MarketplaceController.php:825-846 markSold(): `$buyerUsername = trim($_POST['buyer_username'] ?? '');` then `$buyer = User::findByUsername($buyerUsername); if ($buyer) { $buyerId = (int) $buyer['id']; } ListingSale::record((int) $listing['id'], $buyerId);` — the seller names ANY existing username and a listing_sales row is inserted with that user's id, with no consent/verification the user ever transacted (ListingSale::record at ListingSale.php:26 just INSERTs buyer_id). Then submitFeedback (MarketplaceController.php:1444-1466) accepts the seller's `target_user_id` as long as it is in `ListingSale::buyerIdsFor` — which now contains the forged buyer — and writes `TradeFeedback::create(... $rating, 'seller', ...)` with rating as low as -1 (line 1480-1489). TradeFeedback::summaryFor (TradeFeedback.php:70-88) aggregates ALL rows WHERE to_user_id=victim into the negative counter, and TradeFeedback::receivedBy (line 52-67) renders them on the public page TradeFeedbackController@show (/market/user/{username}/feedback).
Suggested fix. Do not let a seller unilaterally bind an arbitrary buyer to a sale. Either require buyer-side confirmation before a listing_sales row is created (an offer/accept handshake), or restrict seller->buyer feedback to buyers who have themselves taken an action proving the transaction (e.g. the buyer must have initiated/confirmed the purchase). At minimum, do not surface seller-initiated feedback on the recipient's public reputation until the named buyer confirms the transaction.
Filed by the automated tenant-app audit and adversarially evidence-verified. Status: verified. Open — not yet actioned.
Patrick Bass
@mobieus