前言

最近在做CTF题的时候遇到这个考点,想起来自己之前在做实验吧的入门CTF题的时候遇到过这个点,当时觉得难如看天书一般,现在回头望去,仔细琢磨一番感觉也不是那么难,这里就写篇文章记录一下自己的学习的过程。

正文

何为HASH长度拓展攻击?

简单的说,由于HASH的生成机制原因,使得我们可以人为的在原先明文数据的基础上添加新的拓展字符,使得原本的加密链变长,进而控制加密链的最后一节,使得我们得以控制最终结果。

这里我们以MD5加密算法为例子。

MD5长度拓展攻击

下面是个简单的PHP例子。

  1. <?php
  2. include "flag.php";
  3. $secretKey = 'xxxxxx'; #xxx为未知内容,但长度已知为6。
  4. $v1 = $_GET['str'];
  5. $sign = $_GET['sign'];
  6. $token = md5($secretKey.$v1);
  7. if($v1 === 'test') {
  8. die($token); #token=2df51a84abc64a28740d6d2ae8cd7b16
  9. } else {
  10. if($token === $sign) {
  11. die($flag);
  12. }
  13. }
  14. ?>

在这个例子中,我们需要使得变量$token与我们输入的sign参数满足一致才会输出flag。

而由于我们无法知道变量$secretKey的内容,所以无法得到$token的值,故而看似是没有办法获取到flag的死局,而这时便轮到我们的拓展攻击来大显身手了。

MD5算法流程

若想搞清楚原理,其算法的流程是必须了解的。不过我们无需去关心那些复杂的运算,只需要知道的大概的一个流程就OK了。

这里借一张神图:

摘自:哈希长度拓展攻击(Hash Length Extension Attacks)

看不懂也没关系,相信你看完我这篇文章后再返回来看这张图就很清晰明了了。

我们还是举个例子,对于字符串aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb(64个a、3个b)。长度为19个字符,且根据ASCII表,字符a、b的十六进制分别为0x61、0x62。

而我们知道,1位十六进制相当于4位二进制表示(16=2^4)。所以对于64个字符a的长度来说,其二进制长度为:字符长度*二进制位数2*十六进制转二进制位数拓展4=64*2*4=512

对于MD5算法来说,我们需要将原数据进行分块处理,以512位个二进制数据为一块。”最后“一块的处理分为以下几种情况:

  • 明文数据的二进制数据长度<=448,填充padding(无意义占位)数据使其长度为448,再添加原始明文数据的二进制长度信息(64位)使其长度为512位即可。
  • 448<明文数据的二进制数据长度<=512,填充padding数据至下一块的448位,而后再添加原始明文数据的二进制长度信息(64位)使其长度为512位即可。

两种情况如下图:

注意:每块数据的长度均为512位二进制,图中的数据我没有全都用二进制来表示,将明文数据分块之后就可以与向量进行运算了。

对于padding数据(长度不定)来说:首位二进制位1,其余位为0.

对于长度信息位(长度8Byte=64bit)来说,从低位向高位数,如上图的长度信息:f0 03 00 00 00 00 00 00即代表0x03f0,其对应的十进制为1008,即为64+62=126个字符的二进制位数(一个字符1Byte即8bit)。

对于MD5算法来说,有一串初始向量如下:

  1. A=0x67452301
  2. B=0xefcdab89
  3. C=0x98badcfe
  4. D=0x10325476

这串初始向量的值是固定的,作为与第一块数据运算的原始向量。

当这串向量与第一块数据块运算之后,得到了一串新的向量值,这串新的向量值接着与第二块数据块参加运算,直到最后一块数据块。

如下图所示:

而最后的MD5值就是这最后的向量串经过如下转换的结果。

如向量串:

  1. A=0xab45bc01
  2. B=0x6a64bb53
  3. C=0x23ba8afe
  4. D=0x46847a62

先两两为一组进行组合,得到如下数据:

  1. ab 45 bc 01
  2. 6a 64 bb 53
  3. 23 ba 8a fe
  4. 46 84 7a 62

再进行高低位互换,得到如下数据:

  1. 01 bc 45 ab
  2. 53 bb 64 6a
  3. fe 8a ba 23
  4. 62 7a 84 46

最终拼接得到MD5值:01bc45ab53bb646afe8aba23627a8446

现在,让我们回到开始的那个例子。

对于MD5值:2df51a84abc64a28740d6d2ae8cd7b16。我们可以根据MD5与向量互转规则,将MD5转成md5($secretKey + "test")的最终向量值(A'、B'、C'、D'):

  1. A'=0x841af52d
  2. B'=0x284ac6ab
  3. C'=0x2a6d0d74
  4. D'=0x167bcde8

过程如图:

这时候我们修改$v1变量的内容为:

  1. "test" + [0x80 + (0x0)*45] + [0x50 + 0x0*7] + "abc"
  2. 相当于:
  3. "test" + padding数据 + 长度数据 + "abc"

则上述过程则被延续成下图所示:

而对于上述运算过程来说,我们知道了倒数第二个向量串的内容和最后一个数据块,这样一来,最终的MD5值我们也可以自己通过MD5算法计算出来了。

拓展

如同MD5算法那般分组后与向量运算的流程被统称为Merkle–Damgård结构。

而同样使用此结构的HASH算法还有:SHA1、SHA2等

hashpump

hashpump是一个专门生成MD5长度拓展攻击payload的工具。

Github仓库:https://github.com/bwall/HashPump

安装方法:

  1. #Linux
  2. git clone https://github.com/bwall/HashPump.git
  3. apt-get install g++ libssl-dev
  4. cd HashPump
  5. make
  6. make install

安装好之后在终端里输入hashpump,回车即可:

以之前的例子为例,使用hashpump生成payload:

故我们的EXP即为(\x%代替):

  1. /?str=test%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%00abc&sign=bac6cb2d585d2de3f5f48f2759d2e5a7

成功读取FLAG:

CTF

相关CTF题可供练习:

  • [De1CTF2019]SSRFMe
  • 实验吧-让我进去

后记

其实这个知识点确实不难,但是回看两年前的自己,那时候是真的完完全全看不懂看不明白,但是现在只花了十几分钟就可以说是掌握这个知识点了。原来我们不知不觉间也对知识的认知又提升了一个台阶,原先难如天书的内容现在看来也不过尔尔,原先看不到、接触不到的知识,现在也有信心能够去尝试去学习、去理解并掌握。学习本该如此,如攀登高山一般,只有开始攀登,才有机会看得到山脚下看不到的风景,也唯有不断攀登,才能看到更多更多风景。

参考

浅谈HASH长度拓展攻击的更多相关文章

  1. MD5加密及Hash长度拓展攻击【通俗易懂】

    先放一个简单点的利用了Hash长度拓展攻击的题目 if($COOKIE["getmein"] === md5($secret . urldecode($username . $pa ...

  2. 哈希长度拓展攻击之De1CTF - SSRF Me

    题目考查:python代码审计.hash长度拓展攻击 0x01 题目源码: #! /usr/bin/env python #encoding=utf-8 from flask import Flask ...

  3. 实验吧Web-中-让我进去(Hash长度扩展攻击、加盐密码及Linux下hashpump的安装使用)

    打开网页,测试开始,注入费老大劲,看了大佬的blog才知道怎么干. bp抓包,观察发现cookie中有个source=0,在repeater中修改为source=1,然go一下,出来了一段源代码. $ ...

  4. 实验吧_天下武功唯快不破&让我进去(哈希长度拓展攻击)

    天下武功唯快不破 第一反应就去抓包,看到返回包的header中有FLAG的值,base64解码后得到下图所示 这就要求我们在请求头中post相应key的值,我直接在burp中尝试了多次都没有用,想起来 ...

  5. MD5的Hash长度扩展攻击

    Hash长度扩展攻击 引子 无意中碰到一道题,大概代码是这样的 $flag = "XXXXXXXXXXXXXXXXXXXXXXX"; $secret = "XXXXXXX ...

  6. hash长度扩展攻击

    这里面就放一张百度百科的解释吧,emmm 反正我是看不懂还是做一下题来巩固一下吧 CTF中的hash长度攻击 进入网页你会发现页面显示  我这里没有看到什么可以利用的,抓了一下包也没有什么有可以利 ...

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

    题目地址:http://ctf5.shiyanbar.com/web/kzhan.php 在页面源码没发现什么,于是用burp进行抓包重放 看到有setcookie,于是重新刷新页面拦截数据包(这次才 ...

  8. 通过DDOS攻击流程图来浅谈如何预防Ddos攻击与防御

    DDOS攻击流程图 站长之家配图(来源:ppkj.net) 一 背景 在前几天,我们运营的某网站遭受了一次ddos攻击,我们的网站是一个公益性质的网站,为各个厂商和白帽子之间搭建一个平台以传递安全问题 ...

  9. 浅谈HTTP响应拆分攻击

    在本文中,我们将探讨何谓HTTP响应拆分以及攻击行为是怎样进行的.一旦彻底理解了其发生原理(该原理往往被人所误解),我们就可以探究如何利用响应拆分执行跨站点脚本(简称XSS).接下来自然就是讨论如果目 ...

随机推荐

  1. 【每日一个小技巧】Python | input的提示信息换行输出,提示信息用变量表示

    [每日一个小技巧]Python | input的提示信息换行输出,提示信息用变量表示 在书写代码的途中,经常会实现这样功能: 请输入下列选项前的序号: 1.选择1 2.选择2 3.选择3 在pytho ...

  2. Java实现短信验证码

    前言 本人使用的是阿里短信服务,一开始尝试了许多不同的第三方短信服务平台,比如秒滴科技.梦网云通讯.当初开始为什么会选择这两个,首先因为,他们注册就送10元钱(#^.^#),但是后来却发现他们都需要认 ...

  3. Netty(一):的入门使用。

    Netty的入门基本使用流程代码,不做具体分析.使用版本为Netty 4.x版本. 服务端调用示例: 绑定端口号为8080端口 package com.cllover; import com.sun. ...

  4. 阿里出品的最新版 Java 开发手册,嵩山版,扫地僧

    说起嵩山,我就想起乔峰,想起慕容复,以及他们两位老爹在少林寺大战的场景.当然了,最令我印象深刻的就是那位默默无闻,却一鸣惊人的扫地僧啊.这次,阿里出品的嵩山版 Java 开发手册的封面就有一个扫地僧, ...

  5. C#LeetCode刷题-动态规划

    动态规划篇 # 题名 刷题 通过率 难度 5 最长回文子串   22.4% 中等 10 正则表达式匹配   18.8% 困难 32 最长有效括号   23.3% 困难 44 通配符匹配   17.7% ...

  6. C#LeetCode刷题-二分查找​​​​​​​

    二分查找篇 # 题名 刷题 通过率 难度 4 两个排序数组的中位数 C#LeetCode刷题之#4-两个排序数组的中位数(Median of Two Sorted Arrays)-该题未达最优解 30 ...

  7. SpringBoot实现本地存储文件上传及提供HTTP访问服务

    笔者计划为大家介绍分布式文件系统,用于存储应用的图片.word.excel.pdf等文件.在开始介绍分布式文件系统之前,为大家介绍一下使用本机存储来存放文件资源. 二者的核心实现过程是一样的: 上传文 ...

  8. 获取客户端用户真实ip方法整理(jekyll迁移)

    layout: post title: 获取客户端用户真实ip方法整理 date: 2019-08-22 author: xiepl1997 tags: springboot 由请求获取客户端ip地址 ...

  9. flask_restful 的reqparse获取验证前端参数

    required是设置必选非必选,nullable允不允许向传null,location指定参数获取的位置,可以多选,按前后顺序获取 parser.add_argument('app_id', typ ...

  10. 【ZJOI2012】灾难 - LCA+拓扑排序

    题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. 学过生物的阿米巴告 ...