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

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
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注