前言
哈希长度扩展攻击 (hash lengthextensionattacks) 是指针对某些允许包含额外信息的加密散列函数的攻击手段次攻击适用于 MD5 和 SHA-1 等基于 MerkleDamgård 构造的算法
MD5 扩展攻击介绍
我们需要了解以下几点 md5 加密过程:
MD5 加密过程中 512 比特 (64 字节) 为一组, 属于分组加密, 而且在运算的过程中, 将 512 比特分为 32bit*16 块, 分块运算
关键利用的是 MD5 的填充, 对加密的字符串进行填充 (比特第一位为 1 其余比特为 0), 使之(二进制) 补到 448 模 512 同余, 即长度为 512 的倍数减 64, 最后的 64 位在补充为原来字符串的长度, 这样刚好补满 512 位的倍数, 如果当前明文正好是 512bit 倍数则再加上一个 512bit 的一组
MD5 不管怎么加密, 每一块加密得到的密文作为下一次加密的初始向量
举一个例子讲一下如何填充: 比如字符串 Acker 十六进制 0x41636b6572 这里与 448 模 512 不同余, 需补位满足二进制长度位 512 的倍数, 补位后的数据如下:
0x61646d696e8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002800000000000000
此处补充: 以十六进制表示一共是 128 个字符, 十六进制每个字符能够转换成 4 位二进制, 128*4=512 这就是一组, 正好是 512bit
上图中的 8 是因为补位时二进制第一位要补 1, 那么 1000 转换成 16 进制就是 8. 后面都补上 0.
填充数据最后 8 字节长度, Acker 长度为 5*8=40bit, 又因为 0×28=40 所以 16 进制显示为 28.
为什么数据会在左端: MD5 中储存的都是小端方式, 比如 0×12345678, 那么 md5 存储顺序就是 0×78563412
MD5 拓展攻击演示
下图为加密流程图, 可以更直观看清楚整个流程
选一个字符串例如 AckerMD5(Acker)= dee2fb2df156f4040f893d8a10ac1034
现在我们不需要知道字符串是什么只需要知道其长度, 并将字符串填充完, 新加一个字符串如: addition, 之前得到的 AckerMD5 值作为最后一块加密的初始向量, 最后得到的结果和 MD5(Acker+addition)是一样的
实例
这种攻击方式最实际场景中并不多见, 我曾在 ctf 题中见过一次这种攻击方法还是要会滴, 万一打 ctf 比赛时候出现了呢
以实验吧上一道题为例, 下面为源码:
- <?php
- $flag = "flag{flag is here}";
- $secret = "aaaaabbbbbccccc"; // 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
- }
- }
- ?>
题目中可以得到:
$secret 的长度 15
md5($secret.adminadmin)的值为 571580b26c65f306376d4f64e53cb5c7
使用 hashpump, 方法如下图:
第一行是一个新签名作为 getmein 参数提交
第二行作为 password 提交即可
附: hashpump
HashPump 是一个借助于 OpenSSL 实现了针对多种散列函数的攻击的工具, 支持针对 MD5CRC32SHA1SHA256 和 SHA512 等长度扩展攻击而 MD2SHA224 和 SHA384 算法不受此攻击的影响, 因其部分避免了对状态变量的输出, 并不输出全部的状态变量
安装
- git clone https://github.com/bwall/HashPump
- apt-get install g++ libssl-dev
- cd HashPump
- make
- make install
使用方法
搜遍百度, 无奈没有什么具体讲解方法只好 hashpump -h 得到帮助, 凑合看一下吧简单总结一下就是知道前面字符总长度, 知道下一组追加数据, 程序就会自动算出前一组的填充数据
- HashPump git:(master) hashpump -h
- HashPump [-h help] [-t test] [-s signature] [-d data] [-a additional] [-k keylength]
- HashPump generates strings to exploit signatures vulnerable to the Hash Length Extension Attack.
- -h --help Display this message.
- -t --test Run tests to verify each algorithm is operating properly.
- -s --signature The signature from known message.
- -d --data The data from the known message.
- -a --additional The information you would like to add to the known message.
- -k --keylength The length in bytes of the key being used to sign the original message with.
- Version 1.2.0 with CRC32, MD5, SHA1, SHA256 and SHA512 support.
- <Developed by bwall(@botnet_hunter)>
来源: http://www.tuicool.com/articles/2EJ3yme