Data injection with the hash length extension attack

Back to our demonstration. You recall that the name of the file is test. This means that test is the actual data, and thus the 512-bit input to the compression function was made up of secret, test, and padding. All we need to tell hash extender is the current hash, the original data, the range of byte length guesses for the secret, and the data we want to inject – it will do the rest by spitting out a hash for each guess. We would then construct a URL with our attacker data as the filename, and our new hash – if we get the length of the secret right, then our hash will pass validation. Let's check out the command:

# ./hash_extender --data=test --signature=dd03bd22af3a4a0253a66621bcb80631556b100e --append=../../../../../../../etc/passwd --format=sha1 --secret-min=8 --secret-max=50 --table --out-data-format=html > HashAttackLengthGuesses.txt

The following are the terms used in the preceding command:

  • --data defines the data that's being validated. In the terminology we've been using so far, this would be our message when referring to secret + message. Remember, hash extender is assuming that we know the data that's being validated (in this case, the name of the file to be accessed); by definition, we don't know anything about the secret. The only thing we hope to learn is the length of the secret, but that's after trial and error.
  • --signature is the other part of the known parameters: the hash that we know correctly validates the unmodified message. Remember, we need to provide the running state that would be used as input to our next compression function round.
  • --append is the data we're sneaking in under the door. This is what is actually going to be retrieved, and what our specially generated attack hash is validating. For our attack, we're trying to nab the passwd file from etc. We're using the handy ../../../ to climb out of wherever we are in the filesystem back to /, and then jumping into /etc/passwd. Keep in mind, the number of jumps through parent folders is unknown since it would depend on the specific implementation of this web application, so I'm throwing out a guess for now. I'll know later if I need to fix it. You don't need a valid path to find the new hash!
  • --format is the hash algorithm. You can know this for a fact, or perhaps you need to guess based on the length of the hash; this may also require some trial and error.
  • --secret-min and --secret-max is the range of secret length guesses in bytes. The individual circumstances of your test may require this to be used very carefully – for example, I'm using a pretty wide range here because I'm in my lab, planning on using Burp Suite and Intruder, and I know the web app doesn't defend against rapid-fire requests. Some systems may lock you out! You may need to take the results and just punch in URLs manually, like in the good old days.
  • --table is going to make our results look pretty by organizing them in a table format.
  • --out-data-format is handy for situations where a system is expecting data in, for example, hexadecimal. In our case, we would like the HTML output as we're just going to feed this information into web requests.
  • Finally, I tell Linux to dump the output of this command into a text file.

Go ahead and take a peek at the result. You'll see it's basically a list of hashes lined up with the data we hope to inject; each line will have a different amount of padding as it is associated with a particular guess of the secret length. The wider the range you defined for secret-min and secret-max, the more lines you'll have here. 

I fire up Burp Suite, which creates a local HTTP proxy on port 8080 by default. When I'm ready to let Burp Suite in on the action, I configure my browser's network settings to talk to my proxy at 127.0.0.1:8080. Then I click the test link again in the CryptOMG page to create a new GET request to be intercepted by Burp Suite. When I see it, I right-click on it and send it to Intruder.

Intruder is an aggressive tool for firing off requests with custom parameters that I define – these custom parameters are called payloads. Note that payloads are defined with sectional symbols. Simply highlight the text that you want to substitute with payloads and click the Add button at the right. We already know our algorithm is SHA-1 and we aren't changing that, so I've only defined file= and hash= as payload positions:

Now, we click on the Payloads tab so we can define what's going to be placed in those payload positions we just defined. For this part, you'll need to do a little preparation first. You need two separate lists for each payload position. Hash extender gave us everything we need, but in a space-delimited text file. How you separate those columns is up to you (one method is using spreadsheet software).

I define the payload sets in order of position; for example, since the file= parameter is the first position I encounter reading from left to right, I make the list of attacker data Payload set 1. Then, my list of hashes goes in Payload set 2. Now, the fun can begin – weapons free!

Kick back with a cup of coffee as intruder fires off GET request after GET request, each one with customized parameters based on our payload definitions. So what happens if a particular filename and verification hash combination is wrong? We just get a File Not Found error – in HTTP status code terms, a 404. A total of 27 requests later, check out our status column — we received an HTTP 200 code. Bingo, we created a malicious request and had the hash verified. Let's click the Response tab and revel in the treasures of our find. Uh oh: failed to open stream: No such file or directory? What's going on here?

One thing we know for sure is the byte length of the secret. Note the number of guesses with the same hash, but only the request succeeded. That's because finding the hash was only part of the fun – we needed the exact length of the secret. Each item in the Payload1 column is our data with varying padding lengths. Since we defined our exact range, it's a matter of counting the requests needed to succeed. We're on the 26th request and started with 8 bytes for a secret length, so the length of the secret is 34 bytes:

As for the file not found problem, we simply didn't climb the right number of parent folders to get to /etc/passwd. Despite this, we provided data with the correct padding length and a valid hash, so the system considers us authorized; it's simply telling us it can't find what we're allowed to steal.

Now that we know the length of the secret, we can just go back to manual requests. This part will take good old-fashioned trial and error. I'll just keep adding jumps until I get there. It doesn't take long before I've convinced the host to spit out the passwd file:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.24.134