Skip to content

getMoneyAfterWashing - black money laundered anywhere, no location/item/permission check #1

Description

@Pajt9whauht283as

Description

msk_blackmoney:getMoneyAfterWashing in server.lua (lines 39-87) converts all black money into clean cash with no server-side location, item or permission check:

RegisterNetEvent('msk_blackmoney:getMoneyAfterWashing')
AddEventHandler('msk_blackmoney:getMoneyAfterWashing', function()
	local src = source
    local xPlayer = ESX.GetPlayerFromId(src)

	local blackmoney = xPlayer.getAccount('black_money')
	if not blackmoney or (blackmoney and blackmoney.money == 0) then return end

	xPlayer.removeAccountMoney('black_money', blackmoney.money)
	...
	xPlayer.addAccountMoney('money', blackmoney.money - amount)
	...
end)

The intended flow requires the player to:

  1. have the required item (Config.neededItem, checked inside the admin-restricted command at lines 5-13),
  2. physically travel to the washing location,
  3. complete the skill-check minigame on the client (msk_blackmoney:startBlackmoney / skipSkillCheck).

None of that is enforced on the server for the final payout event:

  • No location/distance check — the event does not verify the player is anywhere near Config.Locations['wash_money']
  • No item checkConfig.neededItem is only consumed by the admin command; the payout event never validates it
  • No minigame/state check — there is no server-side "washing in progress" state; the client skill check is purely cosmetic
  • No permission check — although the command to start washing is {'admin'} restricted, the payout event itself is a plain RegisterNetEvent that any player can trigger directly

Also note msk_blackmoney:removeItem (lines 89-95) takes an arbitrary item name from the client and removes it without validating that the item is part of the washing flow — an attacker could use it to destroy arbitrary items in their own inventory (e.g. bypass "must hold the required item" mechanics by removing the needed item mid-flow, or grief themselves), though the primary issue is the wash itself.

Impact

  • Any player with black money (drugs, heists, dirty cash from any source) can launder their entire balance to clean cash instantly, anywhere, without the required item or the skill check
  • The admin restriction on the start command is meaningless because the payout is publicly triggerable
  • Economy bypass: the intended risk/gameplay (travel + minigame + time) is completely removed

Suggested fix

  • Track a server-side washing session (player started washing at location X, minigame passed) and require it in getMoneyAfterWashing
  • Validate #(xPlayer.getCoords() - Config.Locations['wash_money'].moneyCut.coords) <= someDistance
  • Validate that the player holds Config.neededItem before paying out
  • Add a cooldown and a "currently washing" state per player

Affected file

server.lua - msk_blackmoney:getMoneyAfterWashing

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions