摘自:

1、http://www.freebuf.com/articles/web/69264.html

2、https://www.cnblogs.com/pcat/p/5478509.html

0×01 引言

为什么会想到这个呢?上周末做了“强网杯”的童鞋们应该都能知道吧,它其中有个密码学的题目就是考的这一点。

0×02 sha1的hash原理

说到要解释sha1的原理其实是非常复杂的,反正我这种智商的暂时还无法理解。所以,只能从面上跟大家谈一下我的理解。

首先,当hash函数拿到需要被hash的字符串后,先将其字节长度整除64,取得余数。如果该余数正好等于56,那么就在该字符串最后添加上8个字节的长度描述符(具体用bit表示)。如果不等于56,就先对字符串进行长度填充,填充时第一个字节为hex(80),其他字节均用hex(00)填充,填充至余数为56后,同样增加8个字节的长度描述符(该长度描述符为需要被hash的字符串的长度,不是填充之后整个字符串的长度)。以上过程,称之为补位。

补位完成后,字符串以64位一组进行分组(因为上面的余数为56,加上8个字节的长度描述符后,正好是64位,凑成一组)。字符串能被分成几组就会进行多少次“复杂的数学变化”。每次进行“复杂的数学变化”都会生成一组新的registers值供下一次“复杂的数学变化”来调用。第一次“复杂的数学变化”会调用程序中的默认值。当后面已经没有分组可以进行数学变化时,该组生成的registers值就是最后的hash值。

在sha1的运算过程中,为确保同一个字符串的sha1值唯一,所以需要保证第一次registers的值也唯一。所以在sha1算法中,registers具有初始值。如上图中的registers值0。

Hash值的随机性完全依赖于进行“复杂的数学变化”时输入的registers值和该次运算中字符串分组的数据。如果进行“复杂数学变化”时输入的registers值和该次运算的字符串分组相同,那么他们各自生成的新的registers值也相同。

0×03 举个栗子

当需要被hash的字符串为str_a = ”123456”,程序首先判断,len(str_a) % 64 == 56是否成立。这里很明显不成立。那么程序就进行补位操作。首先补位成余数为56的长度。

如上图,蓝色字体就为程序对该字符串进行补位的数据。当满足len(str_a) % 64 == 56后,程序就在该字符串的后面添加8个字节的长度描述符。注意,此处的长度为原始需要被hash的长度。也就是len(str_a) = 6字节*8bit/字节= 48bit=0x30bit。

补位+长度描述符=64个字节,正好是一个分组。所以此处只要进行一次复杂的数学变化就可以了。程序根据该64个字节的数据和registers值0生成新的registers值1。那么该新的registers值1就是str_a的sha1值

0×04 如何利用?

讲了这么多,好像都没讲到如何利用该扩展攻击。那么下面,重点来了。

我们还是利用这篇文章上面的例子进行讲解,转到FreeBuf之前文章

简单来说,就是服务器上会生成一个salt值,该salt值你是不可预测的。但是你又知道了sha1(salt+filename)的值,该filename的值你也是知道的。假设此处的filename的值report.pdf,最后sha1的值为:0a8d538b724c6f2b4288526eb540ee7c。为了方便理解,我们继续假设salt的长度为16位。

将上图的字符串进行sha1操作时,同样先进行整除,然后取余。最后再补上8位的长度描述符。补位+添加长度描述符后的字符串如下图:

该长度也就满足了64位的分组,只需要进行一次“复杂的数学运算”就可以得到最后的sha1值了。

下面请各位看官思考如何进行下面一个字符串的sha1操作。

同样,还是先进行分组。由于该字符串的长度大于64个字节,且小于128个字节,所以要分成两组,需要进行两次“复杂的数学运算”。这个时候我们发现,第一个分组的数据和上图中补码后的数据完全一样,又因为他们都是第一个分组,初始的registers值也一样。那么经过第一轮“复杂的数学运算”,他们各自生成的registers值也同样是相同的。唯一不同的是,由于上面的长度小于64字节,所以只需要进行一轮运算便得到了最后的sha1值。然后这里的字符串有两个分组,需要将第一轮更新的registers值(也就是第一轮运算出来的sha1值)作为第二轮“复杂的数学运算”的registers值,然后才能得出最终的sha1值。

根据上面例子就说明,如果salt的值你不知道,但是你知道长度,又知道sha1(salt),那么就也就可以知道sha1(salt+“填充数据”+“任意可控数据”).这里的salt+“填充数据”就是对salt进行sha1时所补全的数据+最后8位的长度描述符。一般来说,salt+”填充数据”的长度就是64字节,正好是一个分组。如果salt的长度就大于了56个字节,那么加入填充数据后的长度应该是N个64字节,等于N个分组。

为什么?你可以想象,sha1程序再对(salt+“填充数据”+“任意可控数据”)进行hash时,只需要进行第二轮及第二轮以后的运算。因为第一轮运算后的registers值就是sha1(salt)的值,该值你已经知道了。

Hashdump安装和使用

HashPump是一个借助于OpenSSL实现了针对多种散列函数的攻击的工具,支持针对MD5、CRC32、SHA1、SHA256和SHA512等长度扩展攻击。而MD2、SHA224和SHA384算法不受此攻击的影响,因其部分避免了对状态变量的输出,并不输出全部的状态变量。

(至于别的文章提到了MD4、RIPEMD-160、SHA-0、WHIRLPOOL等也可以构造长度扩展攻击,等以后再研究。)

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

至于想在python里实现hashpump,可以使用hashpumpy这个插件:

pip install hashpumpy

推荐在linux里使用,使用方法可以这样获取:

python
>>> import hashpumpy
>>> help(hashpumpy.hashpump)

2、HashPump用法

这里以一个实验吧题目为例,关键的代码大概如下:

<?php
$secret="XXXXXXXXXXXXXXX"; // This secret is 15 characters long for security!
$username="admin";
$password = $_POST["password"];
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.");
}
?>

在题目里可以得到:

md5($secret."adminadmin")的值为571580b26c65f306376d4f64e53cb5c7

稍微整理下我们已经知道的:

$secret是密文,长度为15,如果再算上后面第一个admin,长度就是20
而数据是admin
签名(哈希值)是571580b26c65f306376d4f64e53cb5c7

这时候我们使用HashPump,附加数据至少1位以上:

# hashpump
Input Signature: 571580b26c65f306376d4f64e53cb5c7
Input Data: admin
Input Key Length: 20
Input Data to Add: pcat

或者直接

hashpump -s 571580b26c65f306376d4f64e53cb5c7 -d admin -k 20 -a pcat

就会得到

3e67e8f0c05e1ad68020df30bbc505f5
admin\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\xc8\x00\x00\x00\x00\x00\x00\x00pcat

第一个是新的签名,把它设置到cookies的getmein里。

第二个先把\x替换为%后,post提交

password=admin%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%c8%00%00%00%00%00%00%00pcat

就可以通过了。

-------

ps.提供一个基于HashPump的在线网站:

http://sakurity.com/lengthextension

hash扩展长度攻击及hashdump使用的更多相关文章

  1. HashMap出现Hash DOS攻击的问题

    随着RESTful风格的接口普及,程序员默认都会使用json作为数据传递的方式.json格式的数据冗余少,兼容性高,从提出到现在已被广泛的使用,可以说成为了Web的一种标准.无论我们服务端使用什么语言 ...

  2. PtH(hash传递攻击)原理探秘

    背景知识 Windows 横向渗透的两种方式 1.hash传递攻击,通过传递NTLM-Hash,登录机器,简称PtH: 2.ticket传递攻击,通过传递kerberos的ticket,登录机器,简称 ...

  3. hash扩展攻击本地实验

    记录一下自己对hash扩展攻击的一些理解,hash扩展攻击主要应用于身份认证,比如对于成功登录的用户可以赋予其一个采用hsah算法加密的cookie值,其中含有未知的密钥. 此后每次在服务器端验证此c ...

  4. session安全&&CBC字符反转攻击&&hash拓展攻击

    session安全 p神写的: 在传统PHP开发中,$_SESSION变量的内容默认会被保存在服务端的一个文件中,通过一个叫"PHPSESSID"的Cookie来区分用户.这类se ...

  5. Windows NTLM Hash和Hash传递、Key传递攻击

    Hash(Key) 获取 工具: Mimikatz 用法: .\mimikatz.exe privilege::debug #查看权限 sekurlsa::logonpasswords #获取hash ...

  6. hash长度扩展攻击

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

  7. 敌情篇 ——DDoS攻击原理

    敌情篇 ——DDoS攻击原理 DDoS攻击基础 DDoS(Distributed Denial of Service,分布式拒绝服务)攻击的主要目的是让指定目标无法提供正常服务,甚至从互联网上消失,是 ...

  8. [转]加盐hash保存密码的正确方式

    0x00 背景 大多数的web开发者都会遇到设计用户账号系统的需求.账号系统最重要的一个方面就是如何保护用户的密码.一些大公司的用户数据库泄露事件也时有发生,所以我们必须采取一些措施来保护用户的密码, ...

  9. [ 高危 ] hash碰撞DOS漏洞

    这是一个很神奇的漏洞 hotel.meituan.com订单页面,POST提交的是一串json数据.当把这串数据换成json碰撞数据 后,服务器原本 100毫秒可以响应的数据包,变成需要30秒才能响应 ...

随机推荐

  1. golang——字符串与编码

    1.字符编码 (1)ASCII码 一个字节表示的英文.数字.标点符号等字符. 国际标准ASCII码为0-127即128个字符,二进制最高位为0,其余为扩展ASCII码. (2)GB2312 两字节,主 ...

  2. Linux命令(008) -- yum

    yum命令(全称为Yellow dog Updater, Modified)是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器.基于RPM包管理,能够从指定的服务器自动下 ...

  3. 转 js实践篇:例外处理Try{}catch(e){}

    程序开发中,编程人员经常要面对的是如何编写代码来响应错误事件的发生,即例外处理(exception handlers).如果例外处理代码设计得周全,那么最终呈现给用户的就将是一个友好的界面.否则,就会 ...

  4. Enumerable.Union<TSource> 方法

    功能:生成两个序列的并集(使用默认的相等比较器). 命名空间: System.Linq 程序集: System.Core.dll 备注:实现此方法时使用了延迟执行. 它直接返回一个对象,该对象存储了执 ...

  5. 利用反射给JAVABEAN实例赋值

    为简化和统一,需要给javabean实例统一赋值,实现代码如下(已测试) import java.util.ArrayList; import java.util.Date; import java. ...

  6. HTML增加附件

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. leetcode221 Maximal Square

    思路: dp. 实现: class Solution { public: int maximalSquare(vector<vector<char>>& matrix) ...

  8. Android requestWindowFeature(Window.FEATURE_NO_TITLE)无效解决方法

    今天在<第一行代码>上学习做自定义标题栏,需要将系统自带的标题栏隐藏掉,使用自定义的标题栏,结果发现,requestWindowFeature(Window.FEATURE_NO_TITL ...

  9. Android Error:Unable to find method 'com.android.build.gradle.api.BaseVariant.getOutputs()Ljava/util/List;'.

    问题:Error:Unable to find method 'com.android.build.gradle.api.BaseVariant.getOutputs()Ljava/util/List ...

  10. EF CodeFirst 不得不说的Where与OrderBy

    先来聊上5毛钱的“排序” Code: using (ApplicationDbContext Db=new ApplicationDbContext()) { var res = Db.Threes. ...