Short description: Denial of service via improperly validated commands
Related bug reports:
Patches: (sometimes more fuzz is needed to apply them)
- For version 1.0.0 up to including 1.0.0
- For version 0.7.0 up to including 0.7.5
- For version 0.6.0 up to including 0.6.3
In multiple places in-game commands are not properly validated that allow remote attackers to cause a denial of service (crash) and possibly execute arbitrary code via unspecified vectors.
The bug is exploitable only in-game so the attacker must have access to the server: his IP must not be banned, he must know the password if it has been set and the server must not be full.
The one root cause of this problem is a generalised “pool” system that uses size_t to store/access indices, but has typed validation checks to check indices. Some of these checks use 16 bit integers, which means that a 32 bit “command parameter” gets silently (by the compiler) truncated to 16 bits before being checked after which the 32 bit number is used to access items in the pool.
For example item 0 exists, the pool has that one item and the command parameter is 65536. The validation function would be checking 0, as the high 16 bits of the parameter would be (silently) discarded, and as such the check returns that it is a valid item. This then results in trying to get item 65536 which is way outside of the valid range of the pool.
However, it is not solely confined to pooled items; there are a few cases where a not-yet-validated value is used.
Attached are patches for all vulnerable versions since 0.6.0. Note that this is in essence a partial backport of trunk r19657, r19656, r19655, r19654, r19637, r19633 and r19621. The “in essence” is because those patches change the whole handling of command parameters which is 90% changing to conform to the new policy or standard and 10% actually fixes the crashes. Therefor we chose to make one minimalistic patch for each of the stable series since 0.6 that solves all issues we are aware of, without ending up with a ten times larger diff with many unrelated unneeded changes. Also earlier releases were more vulnerable than the later ones due to improvements in the pool system and some rewrites.
Due to the time needed for assembling these patches and because we are unaware of any Linux distribution shipping OpenTTD from before the 0.6 series in a still supported release we have not made patches for those. They are vulnerable though.
This fix maintains network compatability of patched and unpatched OpenTTD’s except the cases where the unpatched version would crash, but then the crash would be the cause of the disconnection and not that they are incompatible on that part of the network communication.