
A flaw in the wildly popular online game Minecraft makes it easy for just about anyone to crash the server hosting the game, according to a computer programmer who released proof-of-concept code exploiting the vulnerability.
“I thought a lot before writing this post,” Pakistan-based developer Ammar Askar wrote in a blog post published Thursday, 21 months ago, after privately reporting the bug to Minecraft developer Mojang. “On the one hand, I don’t want to expose thousands of servers to a major vulnerability, but on the other hand, Mojang hasn’t acted on it.”
The bug resides in the network internals of the Minecraft protocol. This allows the content of inventory slots to be exchanged, so that items in players’ hotbars, among other things, are automatically displayed after logging in. Minecraft items can also store arbitrary metadata in a file format known as Named Binary Tag (NBT), allowing complex data structures to be kept in hierarchical nests. Askar has released proof-of-concept attack code that he says exploits the vulnerability to crash every server hosting the game. This is how it works.
The vulnerability stems from the fact that the client is allowed to send the server information about certain slots. This, in combination with the nesting of the NBT format, allows us to craft a package that is incredibly complex for the server to deserialize, but trivial for us to generate.
In my case, I chose to create lists within lists, up to five levels. This is a json representation of what it looks like.
rekt: { list: [ list: [ list: [ list: [ list: [ list: [ ] list: [ ] list: [ ] list: [ ] ... ] ... ] ... ] ... ] ... ] ... }
The root of the object,
rekt
, contains 300 lists. Each list has a list of 10 sublists and each of those sublists has 10, up to 5 levels of recursion. That’s a total of10^5 * 300 = 30,000,000
lists.And this is not even the theoretical maximum for this attack. Only the nbt data for this payload is 26.6 megabytes. But luckily Minecraft implements a way to compress large packages, lucky us! zlib shrinks our bad data to just 39 kilobytes.
Note: There was no protocol-wide compression for large packages in previous versions of Minecraft. Previously, NBT was sent compressed with gzip and prefixed with a character shorter than its length, reducing our maximum payload size to
2^15 - 1
. Now length is a variant that can store integers up to2^28
our attack potential has increased significantly.When the server will decompress our data, it will have 27 megs in a buffer somewhere in memory, but that’s not the part that kills it. When it tries to parse it into NBT, it will create Java representations of the objects, which suddenly means that the server has to create several million Java objects, including ArrayLists. This causes the server to run out of memory and puts a huge strain on the CPU.
This vulnerability exists in almost all previous and current Minecraft versions from 1.8.3, the packages used as attack vectors are the 0x08: Block Placement package and 0x10: Creative Inventory Action.
The solution to this vulnerability is not that difficult, the client should never send a data structure as complex as NBT of arbitrary size, and if it has to, some form of recursion and size limits should be implemented.
These were the solutions I recommended to Mojang 2 years ago.
Ars is asking Mojang for comment and will update this post if company officials respond.