From 9dece5f6d3ee1514c424be028286cc377ee8cd78 Mon Sep 17 00:00:00 2001 From: slq <71025924+Zwuiix-cmd@users.noreply.github.com> Date: Wed, 14 Aug 2024 06:11:24 +0200 Subject: [PATCH 1/3] Added security when using PurchaseReceiptPacket --- src/PurchaseReceiptPacket.php | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/PurchaseReceiptPacket.php b/src/PurchaseReceiptPacket.php index e6166c3b..2aeacea4 100644 --- a/src/PurchaseReceiptPacket.php +++ b/src/PurchaseReceiptPacket.php @@ -14,7 +14,9 @@ namespace pocketmine\network\mcpe\protocol; +use pocketmine\network\mcpe\JwtUtils; use pocketmine\network\mcpe\protocol\serializer\PacketSerializer; +use pocketmine\network\mcpe\protocol\types\login\JwtChain; use function count; class PurchaseReceiptPacket extends DataPacket implements ServerboundPacket{ @@ -35,8 +37,32 @@ public static function create(array $entries) : self{ protected function decodePayload(PacketSerializer $in) : void{ $count = $in->getUnsignedVarInt(); - for($i = 0; $i < $count; ++$i){ - $this->entries[] = $in->getString(); + if($count > 1) { + throw new PacketDecodeException("There should be a maximum of one jwt"); + } + + for($i = 0; $i < $count; ++$i) { + [, $data, ] = JwtUtils::parse($in->getString()); + if(!isset($data["sub"])) { + throw new PacketDecodeException("JWT payload must contain 'sub'"); + } + if(!isset($data["tid"])) { + throw new PacketDecodeException("JWT payload must contain 'tid'"); + } + if(!isset($data["xuid"])) { + throw new PacketDecodeException("JWT payload must contain 'xuid'"); + } + if(!isset($data["entitlements"])) { + throw new PacketDecodeException("JWT payload must contain 'entitlements'"); + } + + try { + json_decode($data["entitlements"], false, flags: JSON_THROW_ON_ERROR); + } catch(\Exception $exception) { + throw new PacketDecodeException($exception->getMessage()); + } + + $this->entries[] = $data["entitlements"]; } } From 9ff93616b1e5516b6ebf0e251a649ab3de298008 Mon Sep 17 00:00:00 2001 From: slq <71025924+Zwuiix-cmd@users.noreply.github.com> Date: Wed, 14 Aug 2024 06:11:51 +0200 Subject: [PATCH 2/3] Checks if emoteId is a uuid --- src/EmotePacket.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/EmotePacket.php b/src/EmotePacket.php index b925fea1..8c49c213 100644 --- a/src/EmotePacket.php +++ b/src/EmotePacket.php @@ -15,6 +15,7 @@ namespace pocketmine\network\mcpe\protocol; use pocketmine\network\mcpe\protocol\serializer\PacketSerializer; +use Ramsey\Uuid\Uuid; class EmotePacket extends DataPacket implements ClientboundPacket, ServerboundPacket{ public const NETWORK_ID = ProtocolInfo::EMOTE_PACKET; @@ -60,6 +61,10 @@ public function getFlags() : int{ protected function decodePayload(PacketSerializer $in) : void{ $this->actorRuntimeId = $in->getActorRuntimeId(); $this->emoteId = $in->getString(); + if(!Uuid::isValid($this->emoteId)) { + throw new PacketDecodeException("Invalid EmoteId"); + } + $this->xboxUserId = $in->getString(); $this->platformChatId = $in->getString(); $this->flags = $in->getByte(); From 6543db59df4970ff25d7d2530955b8f3fba25c8f Mon Sep 17 00:00:00 2001 From: slq <71025924+Zwuiix-cmd@users.noreply.github.com> Date: Wed, 14 Aug 2024 06:12:15 +0200 Subject: [PATCH 3/3] Checked if there are three jwt --- src/LoginPacket.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/LoginPacket.php b/src/LoginPacket.php index 707571f9..e33cff8f 100644 --- a/src/LoginPacket.php +++ b/src/LoginPacket.php @@ -72,6 +72,10 @@ protected function decodeConnectionRequest(string $binary) : void{ if(!is_array($chainDataJson["chain"])){ throw new PacketDecodeException("Chain data 'chain' element must be a list of strings"); } + if(count($chainDataJson["chain"]) !== 3) { + throw new PacketDecodeException("Chain data 'chain' must contain three jwt"); + } + $jwts = []; foreach($chainDataJson["chain"] as $jwt){ if(!is_string($jwt)){