The other day I was running a Nessus scan against a client and saw Plugin ID 81576 (Jetty HttpParser Error Remote Memory Disclosure). I’ve seen a number of Jetty servers on penetration testing engagements, but this is the first time I had seen this vulnerability listed. Nessus provided a link to the security advisory and to an excellent blog post written by the vulnerability discoverer, which included a nice Proof-of-Concept (PoC) Python script.
The PoC provided by the researchers clearly shows that if any of the request headers contain an unprintable character, such as a Null Byte (\x00), the server will produce an error message that contains 16 bytes of memory from a previously used buffer. In addition, they showed that by increasing the length of the bad header, an attacker could read further into the buffer. In other words, if you have a buffer that contains 32 bytes, you can read the first 16 bytes by sending 1 bad character in the header and you can read the next 16 bytes by sending a second request with 16 bad characters in the header.
My research showed that the server didn’t always return 16 bytes; sometimes it would return 17 bytes. In addition, many of the returned bytes were null bytes or carriage returns (\r) or line feeds (\n). Taking all of this into account, I wrote a script that would start by sending 1 bad character and receive however many bytes the server sent. It would store these bytes into a string and then increase the number of bad characters sent by the number of bytes received. This allowed me to read the buffer in 16-17 byte chunks. If the server response contained only null bytes or only ‘\r\n’, then I would ignore the response.
The script continues to build up the buffer until it has read 1000 bytes or until the script has had to wait a total of 2 minutes. The script will wait 5 seconds if the response is only null bytes. This gives the server time to put new data into the buffer. So far, the largest amount of data I have been able to read is about 250 bytes. I don’t know if that is because of the buffer size or because of the timeout limitation.
For this particular penetration test, the vulnerable Jetty servers were making calls to AWS Redshift so I was able to capture multiple sets of login credentials using the script. Just in case you are wondering, yes, there were (at the time of this writing) vulnerable Jetty servers accessible on the Internet as can be seen with the following Shodan query: https://www.shodan.io/search?query=Jetty+9.2.3.v20140905. If you’d like to try out the script you can find it here: https://github.com/AppSecConsulting/Pentest-Tools.
To use the script, run:
The output will be similar to the following: