MD5:小端方式填充
第一步: 填充(单位为bit)
保证 长度 % 512 = 448,填充1或n个0
第二步: 记录信息长度
用64位来存储填充前信息长度。 这64位加在第一步结果的后面,这样信息长度就变为N*512+448+64=(N+1)*512位。
第三步: 装入标准的幻数(四个整数)
标准的幻数(物理顺序)是: (A=(01234567)16,B=(89ABCDEF)16,C=(FEDCBA98)16,D=(76543210)16)。 如果在程序中定义应该是(A=0X67452301L,B=0XEFCDAB89L,C=0X98BADCFEL,D=0X10325476L) 标准的初幻数是Md5算法固定的,不会变化,但是幻数本身是随着每一轮计算不断变动的。
第四步: 四轮循环计算[ 每一轮是十六步 ]
以512bit为单位分组(Y0,Y1...Yn), 有一个128bit初值(iv), 第一个分组Y0与初值iv经过哈希函数得到128bit结果(cv1) cv1与T2继续经过哈希函数得到128bit结果(cv2) ......反复
总结(个人理解):
长度的计算是对于二进制位数,比如test的长度位: (每位十六进制数是4位二进制数,通过ASCII码转换十六进制)
-> 二进制长度4*2*4=32,
最后64位长度信息:200000000000000000000000000000000(64位)
=== 0x20 = 32后面填充0
对于长度扩展的理解, md5值由(v1)组成 $v1可控, md5可知,
-> 先随便弄一个字符串, 可得到最后一块(512位的组成)此时得到的md5值, 可推得A B C D四个向量
-> 我们可以构造出来一块 上面所谓的最后一组, 且此时得到的四个向量结果我们通过上一步得到, 此时再往后填充数据来组成真正的最后一块,即扩展攻击
什么叫构造出来一块?
-> 熟悉md5算法基本流程
MD5值的绕过
前置知识:
-
md5函数
在 php 程序中,md5($string,bool): 得到一个字符串散列值。其中第二个参数默认为false,表示该函数返回值是32个字符的十六进制数。若指定为true,则表示函数返回的是16字节的二进制格式(这样通过浏览器解析会出现乱码)。
-
弱比较(==)和强比较(=== 和 !==)
弱比较:只比较值,不比较数据类型 --- 先把两者转换为相同类型,再看值一样不一样
强比较:既比较值,也比较数据类型 --- 先看数据类型一样不一样,再看值一样不一样
类型及举例:
一、MD5弱比较绕过(==)
绕过原理:
以0e开头的字符串在PHP中均被认为是科学计数法,即为0,当两个0e开头的字符串相比较时,无论后面的字符串是什么,都为True
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
二、MD5强比较绕过(===)
绕过原理:
在md5()函数中传入数组,不但md5()函数不会报错,结果还会返回null,在强比较中 null===null,所以传入两个数组即可
三、MD5碰撞
绕过原理:
强制转换为字符串再进行比较,所以数组的方法不可行了;利用的是MD5值算法本身的缺陷 --- 存在散列冲突,必会有两个内容不一样但是MD5值一样的序列
使用fastcoll工具自己快速生成:
可以看我的博客中的另外一篇 工具杂记 中记录有
贴一组:
aaa=a%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%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%003%B1%7E%14T%B5S%DB%7E%23%7B%E8u%0D%15%A1%9D%C8%1E%81%F8%8FJ%AE%1Br9Y%8A%87%88%03%09%0B%01%E7N%05L%A3k%28%C9%03%22p%05n0t%3E1%3B%3FE%E2%1B%1D%DC1x%E0%C4%22%25%22w%5E%10U%EC%CA%9F%F2%B0.%EC%ECB%83%FDq%DF%A6%C9%FE%80%EC%F4%E4%ABWQx%9D%DFm%073%2A%BB%BF%AFF6%90U%0A%99%1C%BE%9C%01Y%22%CD%9D%B9c%D4%A3%959%5E9%F4k2bbb=a%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%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%003%B1%7E%14T%B5S%DB%7E%23%7B%E8u%0D%15%A1%9D%C8%1E%01%F8%8FJ%AE%1Br9Y%8A%87%88%03%09%0B%01%E7N%05L%A3k%28%C9%03%22%F0%05n0t%3E1%3B%3FE%E2%1B%1D%DC%B1x%E0%C4%22%25%22w%5E%10U%EC%CA%9F%F2%B0.%EC%ECB%83%FDq%DF%26%C9%FE%80%EC%F4%E4%ABWQx%9D%DFm%073%2A%BB%BF%AFF6%90U%0A%99%9C%BD%9C%01Y%22%CD%9D%B9c%D4%A3%959%DE9%F4k2
四、MD5长度扩展攻击
例题链接
实验吧ctf---web-让我进入:http://ctf5.shiyanbar.com/web/kzhan.php
信息:
1.已知md5值,且明文长度可知 --- $secret + admin === 20
2.用户名为admin,输入password后,保证Cookie中getmein === md5($secret.urldecode(username.password))
以这个题解释下我对MD5长度扩展攻击的理解:
哈希值由四个幻数组成(可以得到)
, 最后一块是需要填充的(可得到)
,
如果我们以填充好的作为数据传过去,再加一段数据,那么md5值会变成什么样子?
-> 以已知的md5值得到四个幻数,接着与加的数据接着进行md5加密 --- 那我们就是可以得到了
用Hashpump工具生成:
Signature:已知的md5值
Input Data:我没找到定义,我感觉是自己输入的数据(具体看题)
Key Length:已知的md5值的 明文长度---
md5($secret)
---len($secret)
Add:这个随便填(扩展的那一部分)
五、sql中的md5加密绕过
md5函数
ffifdyop
这个字符串被 md5 哈希了之后会变成 276f722736c95d99e921722cf9ed621c,这个字符串前几位刚好是 'or'6
, 而 Mysql 刚好又会吧 hex 转成 ascii 解释,因此拼接之后的形式是==select * from ‘admin’ where password=’’ or ‘6xxxxx’==
而or ‘6xxxxx’ 在mysql判断里面,相当于or 1 ,即等价于 or 一个永真式,因此相当于万能密码,可以绕过md5()函数
<?php$str = "ffifdyop";echo md5($str, true); # 'or'6�]��!r,��b$str2 = "129581926211651571912466741651878684928";echo"n";echo md5($str2,true); # �T0D��o#��'or'8?>
往期推荐
CTF - Pwn之ORW记录
CTF - Pwn题之shellcode&栈迁移
CTF - Pwn题之shellcode
原文始发于微信公众号(夜风Sec):MD5攻击全家桶:弱比较、数组绕过、长度扩展、碰撞攻击通通拿下!
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论