Cause
This is a topic on the ISCC, copied PCTF, and gave a simplification. After passing through the simplified way, it suddenly occurred to me to use the hash length extension attack to conduct customs clearance. Hash length extension attack is a very interesting thing, the use of MD5, SHA1 and other cryptographic algorithm defects, you can not know the original key situation down to calculate a corresponding hash value.
Here is the algorithm for admin.php in the ISCC topic:
$auth = false;if (isset($_COOKIE["auth"])) { $auth = unserialize($_COOKIE["auth"]); $hsh = $_COOKIE["hsh"]; if ($hsh !== md5($SECRET . strrev($_COOKIE["auth"]))) { //$SECRET is a 8-bit salt $auth = false; }}else { $auth = false; $s = serialize($auth); setcookie("auth", $s); setcookie("hsh", md5($SECRET . strrev($s)));}
Understanding Hash Length Extension attacks
Hash length extended attack applies to encryption case: hash ($SECRET, $message)
, where the most common hash is MD5, HASH1. We can not know $SECRET
to derive another matching value. The PHP code given in the example above:
- We know
md5($SECRET . strrev($_COOKIE["auth"]))
the value
- We know
$hsh
the value
- We can figure out another MD5 value and another $HSH value, so
$hsh == md5($SECRET . strrev($_COOKIE["auth"]))
This can be verified. If you want to understand the hash length extension attack, we should first understand the implementation of the Message digest algorithm. The following is an example of MD5 algorithm.
MD5 algorithm implementation
We want to implement abc
the value calculation for the MD5 of the string. First, we're going to turn it into 16-binary.
Fill-In
The message must be interpolated, even if it has a value of 448 after the length is modulo 512. Other wordslen(message) % 512 == 448
。 When the message length is less than 448 bit (note is a bit, not a string length), the message length reaches 448 bit. Of course, if the message length has reached the 448 bit, it is also a complement. The complement is necessary.
The binary representation of the complement is appended to the message with a1
, followed by an infinite0
Untillen(message) % 512 == 448
。 In the 16 binary, we need to fill in the message after the80
, which is 2 binary.10000000
。 We put the newsabc
Make a complement to the 448 bit, which is a byte.
Complement length
After a complement, the 57th byte stores the length of the message before the complement. abc
is a 3-letter, 3-byte, a-bit. Convert to 16 into 0x18. The message is then filled with 64 bytes, followed by a 7-byte 0x00.
Calculate Message Digest
The calculated message digest must be computed with a message after the completion of the complement has been completed, and the message (that is, 64 bytes) of the bit is taken out. When calculating the message digest, there is an initial chain variable that is used to participate in the first round of the operation. The initial chain variables of the MD5 are:
A=0x67452301B=0xefcdab89C=0x98badcfeD=0x10325476
We don't need to worry about the details of the calculations, we just need to know that after a message digest, the chain variables above will be overwritten by the new values , and the chain variables generated by the last round are AABBCCDD by high and low (e.g., Ddccbbaa), which is the MD5 value we calculated.
Implementation of hash length extended attack
The problem is on the cover. We know the hash value without knowing the specific $SECRET, and we have a controllable message. And we get the hash value is the last round of digest after the high-status swap chain variable. We can imagine that generated by the previous round of messages. &NBSP: The
is a bit difficult to understand because I look at the big head. It looks like we're better off putting the implementation in the attack scenario.
is still the PHP above. Because it went a little detour (Strrev, unserialize), so we modify.
$auth =" I_l0ve_l0li ", if (Isset ($_cookie[" auth ")) {$hsh = $_cookie[" HSH "]; if ($hsh!== MD5 ($SECRET. $_cookie["Auth")) {die ("f4ck_u!"); }} else {Setcookie ("auth", $auth); Setcookie ("HSH", MD5 ($SECRET. $auth)); Die ("f4ck_u!");} Die ("i_am_a_l0li_da_yo~");
In the real world, I do not know the value of $SECRET (I randomly hit the qaq), only know the length of a. First, let's visit. Not unexpectedly be f4ck.
The auth in the Cookie is I_L0vE_L0li
, HSH is 7a84f420f8abe642237409f9d4daa851
. Let's take a hash length extension attack.
Length extension
We still have to make a bit of a complement. Because the length of the $SECRET is 12, we fill it with 12 x, followed by the value of auth. Then we fill the 448 bit with the message. The complement length is then performed.
Then follow the , whatever you want. Here I am i_am_l01i
good =v=.
Then remove the previous fake $SECRET to get the final $auth.
I_L0vE_L0li\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xB8\x00\x00\x00\x00\x00\x00\x00I_aM_L01i
After the UrlEncode
I_L0vE_L0li%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%B8%00%00%00%00%00%00%00I_aM_L01i
COMPUTE Hash
I found a MD5 implementation of C language on the Internet. Because the Python implementation cannot change the initial chain variable. I modified the initial chain variable to be a $hsh with a high and low position reversal.
PS: The original is 7a84f420f8abe642237409f9d4daa851
A=0x20f4847aB=0x42e6abf8C=0xf9097423D=0x51a8dad4
Then we haveAdditional Valuesfor MD5 encryption. The attached value isI_aM_L01i
。 First of all, let's change the front 64 bytes to 64A
。 This is to make the state exactly the same as other than the hash itself (original: Then we take the MD5 of "A" s. We take the MD5 of a full (64-byte) block of ' a ' s to ensure, any internal values-other than the state of the hash it Self-are set to what we expect). In fact, it doesn't matter what the first 64 bytes are filled with. Because we've covered the chain variables before we get a summary of our added value.
Then we compile and run the encryption implementation.
Got a bunch of ciphertext that was1d00eac3f7da072d8365b0a7ae1fec42
。 We use Firefox's Firebug plugin to modify cookies.
After the refresh the discovery has passed validation.
Summarize
It seems difficult to understand, I myself also overnight night to take care of. Of course because I am more stupid qaq. In short, this is a very interesting thing, we can go to reproduce.
Another solution to this problem is: hash($SECRET, hash($message))
. This avoids user-controllable message.
Reference: Https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks
Hash Hash length extended attack parsing (record, guarantee not to forget)