MD5扩展长度攻击(实验吧 —— 让我进去)

 

今天在实验吧遇见的一道题(题目链接),考察了关于MD5扩展长度攻击的有关原理。本文会首先对原理进行说明,后面会放上实验吧题目的wp。

MD5扩展长度攻击原理

为了更好地理解改攻击,首先了解以下MD5的加密算法,加密过程的示意图如下:

通俗来讲,就是MD5把每512位当作一组进行加密计算,首先有一个初始序列的值(该值是固定的),这个初始序列与信息的第一组512位进行运算,得到一个结果,该结果作为下一组512位的初始序列,再进行同样的运算,依此类推。需要注意的是,最后一个分组的后64位用来显示原消息的总长,是预留的,也就是说,最后一个分组只能有448位。

有一个问题就是,如果要是(加密的信息长度+64)并不是512的整数倍怎么办呢?

MD5的策略是:

最后一个分组如果不足512,则进行填充,填充的策略是:在原消息和原消息总长之间填充01字符串,第一位为1,剩下的全部填充0。

这样其实就有了一个漏洞:

如果给出一个message和该message经过md5加密后的值,我们可以通过手动填充,把消息长度填充到512的整数倍,再根据这个新的字符串,自己计算出md5值(因为有原message的md5值,相当于知道了加密的初始序列),同样可以成功。

 

填充过程简要说明

比如原信息为test,md5('test') = 098f6bcd4621d373cade4e832627b4f6;也就是说原信息只有4*8=32位,我们要填充448 - 32 = 416位。

‘test'的十六进制是0x74673574(十六进制每个字符可以转成4个二进制位),根据我们上文提到的策略,填充后应该是:80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000

注意:MD5中的填充都是小端序,也就是说,数据的高位字节存放在地址的高端 低位字节存放在地址低端,比如十六进制的后16位(64/4)是32,表示信息长度是32位,就是2000000000000000;

如果我们想要添加字符串(比如添加wn),就可以利用‘test’已经算出来的md5结果,当作 'wn' 字符串加密运算的初始化序列,继续填充的过程,算出来的结果就是 'testwn' 字符串加密的结果。

 

实验吧题目wp

首先使用burpsuite抓包,发现在请求包头中的cookie参数中,有一个source字段,在其它的尝试暂时都没有头绪的情况下,考虑到source这个词有点特殊(可以想到页面源码之类的),试着把source的值改为1,发现得到了程序源代码:

$flag = "XXXXXXXXXXXXXXXXXXXXXXX";
$secret = "XXXXXXXXXXXXXXX"; // This secret is 15 characters long for security!

$username = $_POST["username"];
$password = $_POST["password"];

if (!empty($_COOKIE["getmein"])) {
    if (urldecode($username) === "admin" && urldecode($password) != "admin") {
        if ($COOKIE["getmein"] === md5($secret . urldecode($username . $password))) {
            echo "Congratulations! You are a registered user.\n";
            die ("The flag is ". $flag);
        }
        else {
            die ("Your cookies don't match up! STOP HACKING THIS SITE.");
        }
    }
    else {
        die ("You are not an admin! LEAVE.");
    }
}

setcookie("sample-hash", md5($secret . urldecode("admin" . "admin")), time() + (60 * 60 * 24 * 7));

if (empty($_COOKIE["source"])) {
    setcookie("source", 0, time() + (60 * 60 * 24 * 7));
}
else {
    if ($_COOKIE["source"] != 0) {
        echo ""; // This source code is outputted here
    }
}

通过阅读源码,我们可以知道,如果想要得到flag,需要几个条件:

  1. cookei字段的getmein不能为空
  2. 发送过去的username = admin,并且,password != admin
  3. getmein的值 = $secret + $username + $password 的md5值

前两个条件都很容易满足,关键是第三个,因为我们不知道$secret的内容,只知道长度为15,不过继续阅读后面的内容,可以获得一个信息是:

    md5($secret + adminadmin)已知,也就是请求头中的sample-hash :

那么,

如果 $username = admin,$password = adminwn,则问题则转化成:

已知md5('xxxxxxxxxxxxxxxadminadmin'),求md5('xxxxxxxxxxxxxxxadminadminwn')的值,然后只要把该值赋给geimein即可。综上,可以利用md5扩展长度攻击。

由于md5算法较为复杂,我使用了一个工具hashpump:

附上安装方法:

git clone https://github.com/bwall/HashPump
apt-get install g++ libssl-dev
cd HashPump
make
make install

用法:

输入已知的字符串和md5结果(在这里是adminadmin和),输入密钥的长度(15),再输入你想要在后面添加的字符串,它会自动给你返回md5后的结果,以及填充数据:

把数据在burpsuite中填入后重发即可得到flag。

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值