md5

用途

1.校验文件完整性

2.存储密码改为存储md5,就算得到md5也无法知道密码(但是单纯密码的话,还是存在固定md5,这个时候我们应该给md5加盐)

加盐:就是在密码后边随机加随机数,然后将随机数存储,每次输入密码后边再加上随机数填充计算MD5

3.无法破解原始数据,因为md5是不可逆的

特性

1.输入任意长度的信息,经过处理,输出为128位的信息(数字指纹)

2.从原数据计算出MD5值很容易(容易计算)

3.让密文中的每一位受明文中的许多位的影响;

4.就是将密文与密钥之间的统计关系变得尽可能复杂,使得对手即使获取了关于密文的一些统计特性,也无法推测密钥。有损加密的过程,根据128位的输出结果不可能反推出输入的信息(不可逆)

5.无论密钥或明文的任何细微变化都应当引起密文的剧烈改变。输入中的一位发生变化,HASH值中将有至少一半发生变化。想找到两个不同的数据,使它们具有相同的MD5值,是非常困难的(强抗碰撞)

6.寻找任何的(M1,M2),使H(M1)=H(M2)在计算上不可行,防范生日攻击。

7.不同的输入得到的不同的结果(唯一性)

语法:

string md5($str,raw)

$str:需要计算的字符串

raw:指定十六进制或二进制输出格式

1.基础使用

用来计算md5

image-20240402210138878

2.输出格式

2、输出格式
raw 参数控制输出的「格式」:

true :16个字符的「二进制格式」
false :(默认)32个字符的十六进制格式
如果你在项目中遇到MD5「加密结果不一致」的问题,可以观察两个加密结果的长度是否相同,比如一个结果是16位,而另一个结果是32位,这种情况就可以考虑更换输出格式来解决。

实例:

1
2
3
4
5
6
var_dump(md5('hello', true));
var_dump(md5('hello', false));

输出:
string(16) "]A@*�K*v�q��Œ"
string(32) "5d41402abc4b2a76b9719d911017c592"

md5绕过

科学计数法绕过

md5()遇到公式,会先进行运算,再对运算结果计算md5

由于0和任何数相乘都等于0,所以0e开头的任何数,其md5都是相同的

比如 md5(‘0e1234’),会先运算成 md5(0),再计算MD5值。

补充:

0e是科学计数法,大小写等价,即 0e 和 0E 的结果相同。

科学记数法是一种记数的方法。把一个数表示成a与10的n次幂相乘的形式。

格式为:aEb=a×10^b,即a乘以10的b次幂。
image-20240402210629384

绕过思路1:遇到弱比较(md5(a)==md5(b))时,可以使用0e绕过,即将a和b赋值为0e开头的数

0e绕过还有一种变体,如果某个字符串是0e开头的,在比较时,php也会先把它计算为0,在参与比较。

绕过思路2:遇到弱比较(md5(a)==0),可以传入QNKCDZO等绕过

一些MD5值为0e开头的字符串:

1
2
3
4
5
6
QNKCDZO   => 0e830400451993494058024219903391
240610708 => 0e462097431906509019562988736854
s878926199a => 0e545993274517709034328855841020
s155964671a => 0e342768416822451524974117254469
s214587387a => 0e848240448830537924465865611904
s214587387a => 0e848240448830537924465865611904

数组类型(数组绕过)

md5()不能处理数组,数组都会返回NULL,同时会报一个warning,不影响执行

image-20240405190432171

绕过思路:遇到强比较(a===b)时,可以使用数组绕过。GET传参时,以 a[]=1&b[]=2 这种形式传递数组。

1
2
3
4
$a = array(1,2,3);
$b = array(4,5,6);

var_dump(md5($a)===md5($b));

算数运算配合自动类型转换

md5()遇到算数符时,会先运算,再计算结果的md5值

所以,当字符串与数字类型运算时,会将字符串转换成数字类型再参与运算,最后计算运算结果的MD5值

image-20240405191207269

数值类型

虽然 md5() 要求传入字符串,但传入整数或小数也不会报错;数字相同时,数值型和字符串的计算结果是相同的。

image-20240405191200873

MD5值相等的字符串

1
2
3
4
5
$Param1="\x4d\xc9\x68\xff\x0e\xe3\x5c\x20\x95\x72\xd4\x77\x7b\x72\x15\x87\xd3\x6f\xa7\xb2\x1b\xdc\x56\xb7\x4a\x3d\xc0\x78\x3e\x7b\x95\x18\xaf\xbf\xa2\x00\xa8\x28\x4b\xf3\x6e\x8e\x4b\x55\xb3\x5f\x42\x75\x93\xd8\x49\x67\x6d\xa0\xd1\x55\x5d\x83\x60\xfb\x5f\x07\xfe\xa2";
$Param2="\x4d\xc9\x68\xff\x0e\xe3\x5c\x20\x95\x72\xd4\x77\x7b\x72\x15\x87\xd3\x6f\xa7\xb2\x1b\xdc\x56\xb7\x4a\x3d\xc0\x78\x3e\x7b\x95\x18\xaf\xbf\xa2\x02\xa8\x28\x4b\xf3\x6e\x8e\x4b\x55\xb3\x5f\x42\x75\x93\xd8\x49\x67\x6d\xa0\xd1\xd5\x5d\x83\x60\xfb\x5f\x07\xfe\xa2";

$data1="\xd1\x31\xdd\x02\xc5\xe6\xee\xc4\x69\x3d\x9a\x06\x98\xaf\xf9\x5c\x2f\xca\xb5\x07\x12\x46\x7e\xab\x40\x04\x58\x3e\xb8\xfb\x7f\x89\x55\xad\x34\x06\x09\xf4\xb3\x02\x83\xe4\x88\x83\x25\xf1\x41\x5a\x08\x51\x25\xe8\xf7\xcd\xc9\x9f\xd9\x1d\xbd\x72\x80\x37\x3c\x5b\xd8\x82\x3e\x31\x56\x34\x8f\x5b\xae\x6d\xac\xd4\x36\xc9\x19\xc6\xdd\x53\xe2\x34\x87\xda\x03\xfd\x02\x39\x63\x06\xd2\x48\xcd\xa0\xe9\x9f\x33\x42\x0f\x57\x7e\xe8\xce\x54\xb6\x70\x80\x28\x0d\x1e\xc6\x98\x21\xbc\xb6\xa8\x83\x93\x96\xf9\x65\xab\x6f\xf7\x2a\x70";
$data2="\xd1\x31\xdd\x02\xc5\xe6\xee\xc4\x69\x3d\x9a\x06\x98\xaf\xf9\x5c\x2f\xca\xb5\x87\x12\x46\x7e\xab\x40\x04\x58\x3e\xb8\xfb\x7f\x89\x55\xad\x34\x06\x09\xf4\xb3\x02\x83\xe4\x88\x83\x25\x71\x41\x5a\x08\x51\x25\xe8\xf7\xcd\xc9\x9f\xd9\x1d\xbd\xf2\x80\x37\x3c\x5b\xd8\x82\x3e\x31\x56\x34\x8f\x5b\xae\x6d\xac\xd4\x36\xc9\x19\xc6\xdd\x53\xe2\xb4\x87\xda\x03\xfd\x02\x39\x63\x06\xd2\x48\xcd\xa0\xe9\x9f\x33\x42\x0f\x57\x7e\xe8\xce\x54\xb6\x70\x80\xa8\x0d\x1e\xc6\x98\x21\xbc\xb6\xa8\x83\x93\x96\xf9\x65\x2b\x6f\xf7\x2a\x70";

$a==md5($a)

0e215962017 的 MD5 值也是由 0e 开头,在 PHP 弱类型比较中相等