albertodemichelis / squirrel

Official repository for the programming language Squirrel
http://www.squirrel-lang.org
MIT License
895 stars 149 forks source link

Use-after-free in Array.sort/Type confusion in regexp #220

Closed LinusHenze closed 4 years ago

LinusHenze commented 4 years ago

Like #219, this issue has been found during the CSCG (a German CTF). The goal of the CTF challenge was to pop a shell by sending a .nut file to a server, which will then execute the squirrel code. However, the systemlib and the iolib had not been registered. The binaries used can be found in the attached zip file.

Use-after-free in Array.sort

When sorting an array using Array.sort, a function that compares two elements needs to be provided. This function will then be called multiple times during the sort. By changing the size of the array in the compare function, a use-after-free can be triggered. Exploitation is as follows:

  1. Create an array with two elements: local ar = [null, objectToFree];
  2. Create a sorting function which sets the size of the array to one. When done correctly, objectToFree will be in the second position of the array, then freed by setting the size of the array to one and on the next invocation, the compare function will be passed the freed objectToFree. By creating an array after being passed the freed object the use-after-free can be turned into a type confusion (if objectToFree was a string, it will now have a large size - assuming the array was allocated at the same address as the string).
  3. Call ar.sort, passing the compare function as first parameter.

See the attached exploit for more information. The use-after-free is exploited in UaFObject() to create a string with a large size which can then be used to read the heap.

Type confusion in regexp

All the functions in the regexp class do not check if they are called on a regexp object. This can be abused for a type confusion: Create a blob and call the regexp constructor on it. This will overwrite the userpointer of the blob and replace it with a SQRex object. Because SQRex does not have a vtable but SQBlob has one, we can gain code execution by making sure that the first pointer in the SQRex object points to a fake vtable, then call a blob function that uses the fake vtable. To set the fake vtable, we can call regexp.search on the blob. However, there is one problem: The first pointer in SQRex will be set to the end of the string passed to regexp.search. Because this is the pointer that will become our fake vtable, we somehow have to make sure that our vtable comes after the string. Fortunateley, the string length is calculated using strlen so we only have to include a null byte in the string and put our vtable content after the null byte. To gain code execution, all we have to do is call a blob function that uses the vtable.

More information can be found in the attached exploit (in part 2).

binaries.zip exploit.zip

albertodemichelis commented 4 years ago

Thank you I'll look into this

albertodemichelis commented 4 years ago

the array exploit should be fixed

albertodemichelis commented 4 years ago

fixed regexp