Show Notes

215 - DEF CON, HardwearIO, Broken Caching, and Dropping Headers

The title gives this one away, the header(...) function in PHP will issue a warning (and keep executing) without adding the header to the response if the header contains a Carriage Return (\r), New-Line (\n) or Null-byte (\x00). That functionality may not be new to you as its purpose is to kill response splitting attacks, but @OctagonNetworks presents a fresh twist on this, probably not the first to have the thought but it was a neat idea to me. Take the functionality and use it to your advantage in an attack by being able to drop a header. They use the example of dropping a Content-Disposition header which can prevent the browser from rending the page though I could see this knowledge coming in handy during other chains too. Its just a neat trick to keep in your back-pocket when testing.

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.

A request that isn’t vulnerable until you make it twice. Definitely an interesting edge case that a lot of testing might overlook. What would happen is that a search request would come in and be served normally, if the search itself has an XSS payload it would en escaped before being sent back to the user so the XSS wouldn’t be executed. However if you made the same request a second time from the same user, the response would be served directly out of that user’s cache in that cached response the XSS would no longer be sanitized.

Issues like this with caching can come up from time to time, not necessarily a lack of sanitizing but just inconsistencies in how the data in processed between a cached and non-cached response. Occasionally leading to this great little bugs.