Simple off-by-one issue, the application parses the Host
header getting its length. Checks that length against the maximum size for the buffer its going to be copied into, copied the value over, and adds a null-byte to the end. WHen adding the null-byte if the string is the maximum size it can end up trying to add the null-byte one-byte out of bounds, leading to a off-by-one null write.
This turned out to be likely exploitable due to the heap metadata stored at the beginning of a free block, allowing that one byte write to overwrite the least significant bits of a pointer to the next free block (assuming the OOB write is into a previously allocated and now free block). That null-write should put the pointer it reads the next free block from into user-controlled memory, giving the attacker control of where the next allocation writes to. Similar to a House of Spirit type of primitive, but without the sanity checks to bypass.
The bug here is pretty simple, the XML parser reads tags into a struct XMLTAG
in that struct there is an array for storing attributes, which allocates space for at-most 10 attributes. The parser itself doesn’t check these bounds, allowing for a tag with more than 10 attribute to overflow on the stack. As the first piece of data after the array is the NumAttrs
value which is used to index into the array as it writes. This gives a neat little ability to take this apparent linear overflow, and make it non-linear, being able to give over values by corrupting NumAttrs
. The authors initially took advantage of this unknowingly to jump over the stack canary and corrupt the saved return address but did not take it to full exploitation.
The more interesting aspect of this is on the vulnerability research side as this bug existed 20+ years. Its fairly simple to understand, and even easy to fuzz, but the vulnerability functionality isn’t clear.