[关闭]
@shaobaobaoer 2018-03-06T04:02:34.000000Z 字数 6161 阅读 1511

hash长度扩展攻击

CTF


0x00 前言

1月份的时候(当自己完全是个小白的时候),做到了哈希长度扩展攻击的题目,那时候一点也不会,也没人教自己,看解析也看不懂。
今天花了点时间,终于搞明白了。

参考网站
https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks

想做一个脚本小子的话,直接翻到最后吧
但是该会的还是要会的吧

0x01 从一个例题说起

说什么理论,我不是很喜欢,单刀直入说个例题,这是实验吧的题目,也是我当初死活没搞懂的题目

  1. <?php
  2. $flag = "flag{flag is here}";
  3. $secret = "aaaaabbbbbccccc"; // This secret is 15 characters long for security!
  4. @$username = $_POST["username"];
  5. @$password = $_POST["password"];
  6. if (!empty($_COOKIE["getmein"])) {
  7. if (urldecode($username) === "admin" && urldecode($password) != "admin") {
  8. if ($_COOKIE["getmein"] === md5($secret . urldecode($username . $password))) {
  9. echo "Congratulations! You are a registered user.\n";
  10. die ("The flag is ". $flag);
  11. }
  12. else {
  13. die ("Your cookies don't match up! STOP HACKING THIS SITE.");
  14. }
  15. }
  16. else {
  17. die ("You are not an admin! LEAVE.");
  18. }
  19. }
  20. setcookie("sample-hash", md5($secret . urldecode("admin" . "admin")), time() + (60 * 60 * 24 * 7));
  21. if (empty($_COOKIE["source"])) {
  22. setcookie("source", 0, time() + (60 * 60 * 24 * 7));
  23. }
  24. else {
  25. if ($_COOKIE["source"] != 0) {
  26. echo ""; // This source code is outputted here
  27. }
  28. }
  29. ?>

md5哈希扩展攻击,都有一个普遍的规律,我们需要知道字符串的长度
username和password不能都没admin,有个cookie叫getmein其需要等于md5(secret+username+password)的值。
- 1.首先$secret变量我们不知道,但是我们知道它的长度
- 2.从下面setcookie函数我们可以通过sample-hash这个变量拿到md5($secret+”admin”+”admin”)的md5值
- 3.我们登陆成功的条件,username==admin&&password!=admin 并且我们要cookie getmein的值等于md5($secret+username+password)

0x02 MD5算法

MD5最神奇的地方,就是无论多长的东西,都给你整成一定长度的东西。
MD5算法最重要的就是补位,md5的加密算法的具体算法,非常的复杂。但是过程的话,在此简略写一下

补位
转换成16进制后,对消息进行补位操作,当字符串不满 448 bit时候,将它们补 0 加到 448 bit,然后加上80表示填充开始。注意是位而不是字符串长度,若是说字符串长度的话 应该是 56 的长度 (按照ascii)
补位的时候也是小端绪的。就是本来应该是0000...长度(16)。啥是小端绪的话,看看下面的就行。

补上初始长度
在57字节之后是存储的字符串长度。紧跟在57位后面,并计算成16位。不包含填充字符串的长度,注意是比特数而不是字符串的长度。(十进制下,长度*8)后面继续用0b00补齐成64位。

计算摘要
利用初始变量进行计算,最后输出结果,MD5初始链变量(magic number):

其中的计算过程太过于繁杂了。总之经过一次消息摘要后,上面的链变量将会被新的值覆盖,而最后一轮产生的链变量经过高低位互换(如:aabbccdd -> ddccbbaa 这个很关键)后就是我们计算出来的 md5 值。
MD5不管怎么加密,每一块加密得到的密文作为下一次加密的初始向量IV,这一点也很关键

找了半天,找到了一张图,我一看就明白了很多
image_1c7qndb441cvh14p21v4a1bhklui11.png-364.4kB

举个栗子

  1. let secret = "secret"
  2. let data = "data"
  3. let H = md5()
  4. let signature = hash(secret || data) = 6036708eba0d11f6ef52ad44e8b74d5b
  5. let append = "append"

那么在md5计算后就是这样子的
QQ截图20180305165256.png-10.8kB

具体参数如下所示

  1. "secret" = secret
  2. "data" = data
  3. 80 00 00 ... The 46 bytes of padding, starting with 0x80
  4. 50 00 00 00 00 00 00 00 The bit length in little endian

0x03 哈希长度扩展攻击实现

具体 $SECRET 的情况下,得知了其 hash 值,以及我们有一个可控的消息。而我们得到的 hash 值正是最后一轮摘要后的经过高地位互换的链变量。我们可以想像一下,在常规的摘要之后把我们的控制的信息进行下一轮摘要,只需要知道上一轮消息产生的链变量。

那么这个应该如何实现呢?
···
为了方便理解,我们把之前的那个题目重新写一下

  1. <?php
  2. $SECRET="123456";
  3. $auth = "I_L0vE_L0li";
  4. if (isset($_COOKIE["auth"])) {
  5. $hsh = $_COOKIE["hsh"];
  6. if ($hsh !== md5($SECRET . $_COOKIE["auth"])) {
  7. die("F4ck_U!");
  8. }
  9. } else {
  10. setcookie("auth", $auth);
  11. setcookie("hsh", md5($SECRET . $auth));
  12. die("F4ck_U!");
  13. }
  14. die("I_aM_A_L0li_dA_Yo~");
  15. ?>

通过获取cookie中 hsh的值,我们就能得到 hsh =
自己动手写个函数,或者用手算一下,可以得到下一轮的链变量就是:

然后进行补位。因为 $SECRET 的长度是 6,我们用 6 个 a 来填补一下,紧跟着就是 auth 的值。然后我们把消息补到 448 bit。接着进行补长度。

得到如下参数:

  1. secret_admin = "aaaaaaI_L0vE_L0li" + '\x80' + '\x00' * 38 + '\x88' + '\x00' * 7 + "whaleCTF"

然后,md5的加密中,这个东西会被填补成 512*2 bit 的东西,当然,我们需要计算的只是后面的东西,也就是"whaleCTF"+填充的东西。
转换成16进制,也就是:

之后就看以开展我们的哈希长度扩展攻击了,将这个16进制数作为第二轮中的输入,并将s1,s2,s3,s4作为初始的链变量。我们就能够得到 一个新的hsh为 57105e676f1e378fe5d6435d3a285c8a

之后就是就题目论事了。那我们这道题目而言,我们需要的是

  1. $hsh !== md5($SECRET . $_COOKIE["auth"])

所以说

  1. 57105e676f1e378fe5d6435d3a285c8a== md5(xxxxxx+"I_L0vE_L0li" + '\x80' + '\x00' * 38 + '\x88' + '\x00' * 7 + "whaleCTF")

(注意url编码)
是成立的,所以只要在cookie中输入
QQ截图20180306092635.png-11.1kB
得到flag
QQ截图20180306092729.png-2.9kB

0x04 更多的例子 ———— 实验吧:让我进去

那么对于实验吧的这道题目的?其实也是一样的。源码在上面
我们获取了sample_hash为

那么,下一轮变量的IV就是

payload就是如下

  1. secret_admin = "aaaaabbbbbcccccadminadmin" + '\x80' + '\x00' * 30 + '\xc8' + '\x00' * 7 + "admin"

对于这道题目而言,只要将username=admin,password="admin" + '\x80' + '\x00' * 30 + '\xc8' + '\x00' * 7 + "admin" URL编码 post提交

··· PS:实验吧这道题好像被宕了,不知道咋回事

image_1c7sf74tqujo178194dre71pft11.png-59.3kB

0x05 更多的例子 ———— WhaleCTF: 哈希入侵

url: http://daka.whaledu.com/web/web44/

源码

  1. <?php
  2. echo "已知一组role为root,salt长度为6,hash为a0566a65f9d6bfd9abf2c116ef1ca2af,想要扩展的字符串是whaleCTF"."<br>";
  3. $flag = "**********";
  4. $role = $_REQUEST["role"];
  5. $hash = $_REQUEST["hash"];
  6. $salt = "***********"; //The length is 6
  7. if ($hash !== md5($salt.$role)){
  8. echo 'wrong!';
  9. exit;
  10. }
  11. if ( $role == 'root'){
  12. echo 'no no no !, hash cann\'t be root';
  13. exit;
  14. }
  15. //echo "You are ".$role.'</br>';
  16. echo 'Congradulation! The flag is'.$flag;
  17. ?>

攻击过程。md5pad.py 哈希值 扩展的字符串 原始盐加上信息的长度(10)

md5-extension-attack/md5pad.py" a0566a65f9d6bfd9abf2c116ef1ca2af whaleCTF 10
Payload: '\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\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00P\x00\x00\x00\x00\x00\x00\x00whaleCTF'
Payload urlencode: %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%00%00%00%00%00%00%00%00%00%00%00%00%00P%00%00%00%00%00%00%00whaleCTF
md5: aab9a3180e92bd4126d56011b672711f

然后post提交数据即可

0x06 工具相关

hash_extender

本文中的部分知识也是来自该作者的博客,全英文的,耐下心子看很好理解。

下载地址

https://github.com/iagox86/hash_extender

用法

利用方法也相当得方便

举例 哈希长度扩展攻击实现

  1. root@ninthdevil:~/桌面/Cknife/hash_extender# ./hash_extender -d I_L0vE_L0li -a whaleCTF -l 6 -f md5 -s d607a0da7fd77724621092333d8fdee8 --out-data-format html
  2. Type: md5
  3. Secret length: 6
  4. New signature: 57105e676f1e378fe5d6435d3a285c8a
  5. New string: I%5fL0vE%5fL0li%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%00%00%00%00%00%00%88%00%00%00%00%00%00%00whaleCTF

md5-extension-attack

个人感觉比上面那个好用,因为上面那个输入的参数有些多,实际上输入盐加原来字符的长度是不是就够了呢?

下载地址

https://github.com/JoyChou93/md5-extension-attack

用法

python md5pad.py [hash] [padding] [len(salt+message)]

举例 哈希入侵

  1. > md5-extension-attack/md5pad.py" a0566a65f9d6bfd9abf2c116ef1ca2af whaleCTF 10
  2. > Payload: '\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\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00P\x00\x00\x00\x00\x00\x00\x00whaleCTF'
  3. > Payload urlencode: %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%00%00%00%00%00%00%00%00%00%00%00%00%00P%00%00%00%00%00%00%00whaleCTF
  4. > md5: aab9a3180e92bd4126d56011b672711f
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注