常见MD5绕过

MD5绕过

弱类型比较==

1
md5($a)==md5($b)&&$a!=$b

科学计数法

在PHP中 0e开头表示为科学计数法 0e后面的字母 会被当作零处理

1
2
3
4
5
6
7
8
9
10
11
12
13
QLTHNDT
QNKCDZO
PJNPDWY
NWWKITQ
NOOPCJF
MMHUWUV
MAUXXQC
240610708
s878926199a
s155964671a
s214587387a
0e215962017
0e1284838308

数组绕过

由于md5不能加密数组,在加密数组的时候会返回NULL

1
?a[]=1&b[]=2

强类型比较===

1
if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2']))

0e绕过不能用了,因为强比较时,0exxx不再被当做科学计数法,而是被当做字符串

数组绕过

依然可以实现绕过?a[]=1&b[]=2

string类型的强类型比较

1
2
if((string)$_GET['a']!==(string)$_GET['b'] && 
md5($_GET['a'])===md5($_GET['b']))

不能使用数组绕过了

1
2
3
4
5
6
7
8
9
10
11
12
13
a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2   
b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2

URL编码形式
a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2
&b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2

原始二进制数据
$a="\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";
$b="\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”;

生成文件形式(脚本工具)

linux 使用 md5collgen 碰撞生成两个 md5 值相同但内容不同的文件

使用 md5collgen 进行 MD5 碰撞实验碰撞

使用md5collgen进行MD5碰撞实验-CSDN博客

windows 可以下载 _fastcoll_,碰撞生成两个 md5 值相同但内容不同的文件

fastcoll:快速 MD5 碰撞生成器

fastcoll:快速MD5碰撞生成器_fastcoll软件-CSDN博客

双md5

1
md5(md5($a))==md5($b)

MD5和双MD5以后的值都是0e开头的

1
2
3
4
0e215962017
CbDLytmyGm2xQyaLNhWn
770hQgrBOjrcqftrlaZk
7r4lGXCH2Ksu2JNT3BYM

但是我极客大挑战中的一个题目就没有通过,

1
md5(md5($a))!==md5($b)&&md5(md5($a))==md5($b)

我尝试上面的都不行,说是要求0e后要为全是数字,留个坑

特殊值

$a == md5($a)

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

md5(0e215962017)=0e291242476940776845150308577824

NaN和INF

NAN 和 INF,分别为非数字和无穷大,但是var_dump 一下它们的数据类型却是 double那么在 md5函数处理它们的时候,是将其直接转换为字符串 NAN和字符串 INF 使用的,但是它们拥有特殊的性质,它们与任何数据类型(除了 true)做强类型或弱类型比较均为 false,甚至 NAN=NAN 都是 false,但md5(‘NaN’)=md5(‘NaN’)为 true。

MD5($a,true)函数

1
$sql = "SELECT flag FROM flags WHERE password = '".md5($password,true)."'";

ffifdyop,md5(ffifdyop)后是276f722736c95d99e921722cf9ed621c
这个字符串前几位刚好是’ or ‘6<乱码>,or 后的内容是永真式

而 Mysql 刚好又会把 hex 转成 ascii 解释

因此拼接之后的形式是 $sql = “SELECT flag FROM flags WHERE password = ‘’ or ‘6XXXX’”;

这就是绕过 MD5 () 函数的万能密码

截断比较(部分比较)

给出一段 md5 值要求找到匹配的原码。一般使用爆破脚本

1
substr(md5(?),0,5)==='8ffb1'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import hashlib
from multiprocessing.dummy import Pool as ThreadPool

# MD5截断数值已知 求原始数据
# 例子 substr(md5(captcha), 0, 6)=60b7ef

def md5(s): # 计算MD5字符串
return hashlib.md5(str(s).encode('utf-8')).hexdigest()

keymd5 = '8ffb1' #已知的md5截断值
md5start = 0 # 设置题目已知的截断位置
md5length = 5

def findmd5(sss): # 输入范围 里面会进行md5测试
key = sss.split(':')
start = int(key[0]) # 开始位置
end = int(key[1]) # 结束位置
result = 0
for i in range(start, end):
# print(md5(i)[md5start:md5length])
if md5(i)[0:5] == keymd5: # 拿到加密字符串
result = i
print(result) # 打印
break

list=[] # 参数列表
for i in range(10): # 多线程的数字列表 开始与结尾
list.append(str(10000000*i) + ':' + str(10000000*(i+1)))
pool = ThreadPool() # 多线程任务
pool.map(findmd5, list) # 函数 与参数列表
pool.close()
pool.join()

碰撞

粘了个大佬的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# -*- coding: utf-8 -*-
import multiprocessing
import hashlib
import random
import string
import sys
CHARS = string.letters + string.digits
def cmp_md5(substr, stop_event, str_len,. start=0, size=20):
global CHARS
while not stop_event.is_set():
rnds = ''.join(random.choice(CHARS) for _ in range(size))
md5 = hashlib.md5(rnds)
value = md5.hexdigest()
if value[start: start+str_len] == substr:
print rnds
stop_event.set()
'''
#碰撞双md5
md5 = hashlib.md5(value)
if md5.hexdigest()[start: start+str_len] == substr:
print rnds+ "=>" + value+"=>"+ md5.hexdigest() + "\n"
stop_event.set()
'''

if __name__ == '__main__':
substr = sys.argv[1].strip()
start_pos = int(sys.argv[2]) if len(sys.argv) > 1 else 0
str_len = len(substr)
cpus = multiprocessing.cpu_count()
stop_event = multiprocessing.Event()
processes = [multiprocessing.Process(target=cmp_md5, args=(substr,
stop_event, str_len, start_pos))
for i in range(cpus)]
for p in processes:
p.start()
for p in processes:
p.join()

参考文献

MD5函数常见绕过方式 – Jaren’s Blog

CTF]CTF中if (md5(md5($_GET[‘a’])) == md5($_GET[‘b’])) 的绕过 - 肖洋肖恩、 - 博客园

md5绕过 - Yolololololo - 博客园


常见MD5绕过
https://h0yu1.github.io/2025/11/20/MD5/
作者
H0yu1
发布于
2025年11月20日
许可协议