suriyun-production / mmorpg-kit-docs

This is document for MMORPG KIT project (https://www.assetstore.unity3d.com/#!/content/110188?aid=1100lGeN)
https://suriyun-production.github.io/mmorpg-kit-docs
49 stars 10 forks source link

Gold exploit #2592

Closed moepi2k closed 3 weeks ago

moepi2k commented 1 month ago

there is a way that player can inject code and change sell price of an item.

e.g when i have an item which i set sell price to 2 palyer somehow was able to change its sellprice to 100000 and sold the item.

checked the log and his gold was increased

insthync commented 1 month ago

You may try to reproduce it by run the servers then run client in editor, change item price before sell it

moepi2k commented 1 month ago

i will check, maybe a player was able to exploit gm commands. the problem is the logging system dont log gm commands, only normal chat message

insthync commented 1 month ago

You said you checked the log, which log? When the log called, where in the code which called to write the message?

moepi2k commented 1 month ago

I nade loggin system used ur interface. In the logs i just saw that the player which had alot of gold asked for how he can sell stufd and then saw he sold some items, at the sane tine i saw he used / which i assume he tried some gm commands. But when you use a correct gm command like /add_item, it wont log with ur interface

insthync commented 4 weeks ago

You said you saw from the log, so which log function/interface that the message?

insthync commented 4 weeks ago

Or you gonna say you checked the log but found nothing?

moepi2k commented 4 weeks ago

no i just saw in the chat log the he used just a / which i assume he used a gm command after. since / is not really a gm command and will log as normal msg and gm command will not

insthync commented 4 weeks ago

So you checked the log and not found anything from log, right?

moepi2k commented 4 weeks ago

yes because gm commands are not logged

insthync commented 4 weeks ago

Yep, confusing with "checked the log and his gold was increased", it sounds like you found that the gold increased from log

moepi2k commented 4 weeks ago

Ah no sorry, just saw hus amount of gold when checked db entries.

insthync commented 3 weeks ago

Can this occurs because of banking issues?

moepi2k commented 3 weeks ago

no its just the negative amount as described. those small check i send u fix the issue

using Cysharp.Threading.Tasks;
using LiteNetLibManager;
using UnityEngine;

namespace MultiplayerARPG.MMO
{
    public partial class MMOServerBankMessageHandlers : MonoBehaviour, IServerBankMessageHandlers
    {
#if (UNITY_EDITOR || !EXCLUDE_SERVER_CODES) && UNITY_STANDALONE
        public IDatabaseClient DbServiceClient
        {
            get { return MMOServerInstance.Singleton.DatabaseClient; }
        }

        public ClusterClient ClusterClient
        {
            get { return (BaseGameNetworkManager.Singleton as MapNetworkManager).ClusterClient; }
        }
#endif

        public async UniTaskVoid HandleRequestDepositGuildGold(RequestHandlerData requestHandler, RequestDepositGuildGoldMessage request, RequestProceedResultDelegate<ResponseDepositGuildGoldMessage> result)
        {
#if (UNITY_EDITOR || !EXCLUDE_SERVER_CODES) && UNITY_STANDALONE
            if (request.gold <= 0)
            {
                result.InvokeError(new ResponseDepositGuildGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_NOT_ENOUGH_GOLD,
                });
                return;
            }
            if (!GameInstance.ServerUserHandlers.TryGetPlayerCharacter(requestHandler.ConnectionId, out IPlayerCharacterData playerCharacter))
            {
                result.InvokeError(new ResponseDepositGuildGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_NOT_LOGGED_IN,
                });
                return;
            }
            if (!GameInstance.ServerGuildHandlers.TryGetGuild(playerCharacter.GuildId, out GuildData guild))
            {
                result.InvokeError(new ResponseDepositGuildGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_NOT_JOINED_GUILD,
                });
                return;
            }
            if (playerCharacter.Gold - request.gold < 0)
            {
                result.InvokeError(new ResponseDepositGuildGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_NOT_ENOUGH_GOLD_TO_DEPOSIT,
                });
                return;
            }
            // Update gold
            DatabaseApiResult<GuildGoldResp> changeGoldResp = await DbServiceClient.ChangeGuildGoldAsync(new ChangeGuildGoldReq()
            {
                GuildId = playerCharacter.GuildId,
                ChangeAmount = request.gold
            });
            if (!changeGoldResp.IsSuccess)
            {
                result.InvokeError(new ResponseDepositGuildGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_INTERNAL_SERVER_ERROR,
                });
                return;
            }
            guild.gold = changeGoldResp.Response.GuildGold;
            playerCharacter.Gold -= request.gold;
            GameInstance.ServerGuildHandlers.SetGuild(playerCharacter.GuildId, guild);
            // Broadcast via chat server
            if (ClusterClient.IsNetworkActive)
            {
                ClusterClient.SendSetGuildGold(MMOMessageTypes.UpdateGuild, guild.id, guild.gold);
            }
            GameInstance.ServerGameMessageHandlers.SendSetGuildGoldToMembers(guild);
            result.InvokeSuccess(new ResponseDepositGuildGoldMessage());
#endif
        }

        public async UniTaskVoid HandleRequestDepositUserGold(RequestHandlerData requestHandler, RequestDepositUserGoldMessage request, RequestProceedResultDelegate<ResponseDepositUserGoldMessage> result)
        {
#if (UNITY_EDITOR || !EXCLUDE_SERVER_CODES) && UNITY_STANDALONE
            if (request.gold <= 0)
            {
                result.InvokeError(new ResponseDepositUserGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_NOT_ENOUGH_GOLD,
                });
                return;
            }
            if (GameInstance.Singleton.goldStoreMode == GoldStoreMode.UserGoldOnly)
            {
                result.InvokeError(new ResponseDepositUserGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_SERVICE_NOT_AVAILABLE,
                });
                return;
            }
            if (!GameInstance.ServerUserHandlers.TryGetPlayerCharacter(requestHandler.ConnectionId, out IPlayerCharacterData playerCharacter))
            {
                result.InvokeError(new ResponseDepositUserGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_NOT_LOGGED_IN,
                });
                return;
            }
            if (playerCharacter.Gold - request.gold < 0)
            {
                result.InvokeError(new ResponseDepositUserGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_NOT_ENOUGH_GOLD_TO_DEPOSIT,
                });
                return;
            }
            // Update gold
            DatabaseApiResult<GoldResp> changeGoldResp = await DbServiceClient.ChangeGoldAsync(new ChangeGoldReq()
            {
                UserId = playerCharacter.UserId,
                ChangeAmount = request.gold
            });
            if (!changeGoldResp.IsSuccess)
            {
                result.InvokeError(new ResponseDepositUserGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_INTERNAL_SERVER_ERROR,
                });
                return;
            }
            playerCharacter.UserGold = changeGoldResp.Response.Gold;
            playerCharacter.Gold -= request.gold;
            result.InvokeSuccess(new ResponseDepositUserGoldMessage());
#endif
        }

        public async UniTaskVoid HandleRequestWithdrawGuildGold(RequestHandlerData requestHandler, RequestWithdrawGuildGoldMessage request, RequestProceedResultDelegate<ResponseWithdrawGuildGoldMessage> result)
        {
#if (UNITY_EDITOR || !EXCLUDE_SERVER_CODES) && UNITY_STANDALONE
            if (request.gold <= 0)
            {
                result.InvokeError(new ResponseWithdrawGuildGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_NOT_ENOUGH_GOLD,
                });
                return;
            }
            if (!GameInstance.ServerUserHandlers.TryGetPlayerCharacter(requestHandler.ConnectionId, out IPlayerCharacterData playerCharacter))
            {
                result.InvokeError(new ResponseWithdrawGuildGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_NOT_LOGGED_IN,
                });
                return;
            }
            if (!GameInstance.ServerGuildHandlers.TryGetGuild(playerCharacter.GuildId, out GuildData guild))
            {
                result.InvokeError(new ResponseWithdrawGuildGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_NOT_JOINED_GUILD,
                });
                return;
            }
            // Get gold
            DatabaseApiResult<GuildGoldResp> goldResp = await DbServiceClient.GetGuildGoldAsync(new GetGuildGoldReq()
            {
                GuildId = playerCharacter.GuildId
            });
            if (!goldResp.IsSuccess)
            {
                result.InvokeError(new ResponseWithdrawGuildGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_INTERNAL_SERVER_ERROR,
                });
                return;
            }
            if (goldResp.Response.GuildGold - request.gold < 0)
            {
                result.InvokeError(new ResponseWithdrawGuildGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_NOT_ENOUGH_GOLD_TO_WITHDRAW,
                });
                return;
            }
            // Update gold
            DatabaseApiResult<GuildGoldResp> changeGoldResp = await DbServiceClient.ChangeGuildGoldAsync(new ChangeGuildGoldReq()
            {
                GuildId = playerCharacter.GuildId,
                ChangeAmount = -request.gold
            });
            if (!changeGoldResp.IsSuccess)
            {
                result.InvokeError(new ResponseWithdrawGuildGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_INTERNAL_SERVER_ERROR,
                });
                return;
            }
            guild.gold = changeGoldResp.Response.GuildGold;
            playerCharacter.Gold = playerCharacter.Gold.Increase(request.gold);
            GameInstance.ServerGuildHandlers.SetGuild(playerCharacter.GuildId, guild);
            // Broadcast via chat server
            if (ClusterClient.IsNetworkActive)
            {
                ClusterClient.SendSetGuildGold(MMOMessageTypes.UpdateGuild, guild.id, guild.gold);
            }
            GameInstance.ServerGameMessageHandlers.SendSetGuildGoldToMembers(guild);
            result.InvokeSuccess(new ResponseWithdrawGuildGoldMessage());
#endif
        }

        public async UniTaskVoid HandleRequestWithdrawUserGold(RequestHandlerData requestHandler, RequestWithdrawUserGoldMessage request, RequestProceedResultDelegate<ResponseWithdrawUserGoldMessage> result)
        {
#if (UNITY_EDITOR || !EXCLUDE_SERVER_CODES) && UNITY_STANDALONE
            if (request.gold <= 0)
            {
                result.InvokeError(new ResponseWithdrawUserGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_NOT_ENOUGH_GOLD,
                });
                return;
            }
            if (GameInstance.Singleton.goldStoreMode == GoldStoreMode.UserGoldOnly)
            {
                result.InvokeError(new ResponseWithdrawUserGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_SERVICE_NOT_AVAILABLE,
                });
                return;
            }
            if (!GameInstance.ServerUserHandlers.TryGetPlayerCharacter(requestHandler.ConnectionId, out IPlayerCharacterData playerCharacter))
            {
                result.InvokeError(new ResponseWithdrawUserGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_NOT_LOGGED_IN,
                });
                return;
            }
            // Get gold
            DatabaseApiResult<GoldResp> goldResp = await DbServiceClient.GetGoldAsync(new GetGoldReq()
            {
                UserId = playerCharacter.UserId
            });
            if (!goldResp.IsSuccess)
            {
                result.InvokeError(new ResponseWithdrawUserGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_INTERNAL_SERVER_ERROR,
                });
                return;
            }
            if (goldResp.Response.Gold - request.gold < 0)
            {
                result.InvokeError(new ResponseWithdrawUserGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_NOT_ENOUGH_GOLD_TO_WITHDRAW,
                });
                return;
            }
            // Update gold
            DatabaseApiResult<GoldResp> changeGoldResp = await DbServiceClient.ChangeGoldAsync(new ChangeGoldReq()
            {
                UserId = playerCharacter.UserId,
                ChangeAmount = -request.gold
            });
            if (!changeGoldResp.IsSuccess)
            {
                result.InvokeError(new ResponseWithdrawUserGoldMessage()
                {
                    message = UITextKeys.UI_ERROR_INTERNAL_SERVER_ERROR,
                });
                return;
            }
            playerCharacter.UserGold = changeGoldResp.Response.Gold;
            playerCharacter.Gold = playerCharacter.Gold.Increase(request.gold);
            result.InvokeSuccess(new ResponseWithdrawUserGoldMessage());
#endif
        }
    }
}
insthync commented 3 weeks ago

How is it not related? If you can hack money with banking negative money amount to increase your money?

insthync commented 3 weeks ago

And if you going to push codes to a public repo, you should try to create pull requests, you said you want to learn, then learn to use it.

moepi2k commented 3 weeks ago

i dont get it. just add the changes and the bug is fixxed

moepi2k commented 3 weeks ago

i cant make pull request sincei dont have core access ^^

insthync commented 3 weeks ago

MMO repo is public

moepi2k commented 3 weeks ago

true, but is the lan component also in the mmo rep? because u need to make the changes there too

insthync commented 3 weeks ago

Then just make for mmo repo

moepi2k commented 3 weeks ago

okey