Unauthenticated File Upload and Remote Code Execution in ShareFile [CVE-2023-24489]

We discussed this vulnerability during Episode 215 on 25 September 2023

Not making encrypted blobs tamper-proof is a pretty classic crypto issue that lead to an arbitrary file-upload and code execution vulnerability in ShareFile. The file upload functionality of ShareFile took a few natural arguments: a filename, an uploadid and a parentid. The fileupload would be uploaded to: “{$TempDir}/up-{uploadid}/{parentid}{filename}” where $TempDir came from the system environment, but the rest of the values were under attacker influence. filename was sanitized and could not be used for a traversal, and parentid was an encrypted blob that was decrypted and used. uploadid however was not sanitized and could be used to create a directory traversal.

As the upload page was not authenticated, the only thing stopping an attacker was the encrypted parentid must decrypt “successfully”. The only mechanism that preventing an attacker from just providing garbage data to decode was the use of PKS#7 padding. Basically, the crypto system can look at the padding bytes and determine if they are reasonable values, if they are not reasonable then it can assume decryption failed and provide an error that would stop the file upload.

PKS#7 is a fairly simple padding scheme, if they needed to append say 5 bytes to the cipher test, then the last 5 bytes would be 05 05 05 05 05 if it added 4 bytes it would be 04 04 04 04. If those last bytes don’t decode to sane values you can quickly flag an issue. In this case, this meant that the author must provide a parentid that would decrypt to having the last byte as a 01 and if they could do that, then the upload would continue. And so, that was the attack a slightly enhanced brute-force attack (only 256 possible values that last byte could be after all) until the parentid successfully decrypted and the file (an aspx webshell) would be uploaded into an executable location. They were able to improve the brute-force and get it down to jsut 128 requests by taking advantage of the cipher-block chaining method in use to force a particular value which you can read about in the original post.

Overall, its just a classic case of why you should always have some mechanism to ensure the encrypted data was not tampered with.