写在前面

  • php 对 MD5 加密方法为$a=md5(‘string’);比起 python 就是神仙级,壮哉 php。
  • php 中存在强比较(==/!=)和弱比较(===/!==),两个数组能绕过强和弱两个比较(a[]=1&b[]=2),因为 md5 不会处理数组,返回的结果都为 bool(false)
  • 0e+纯数字的字符串会使 php 误认为是科学计数法, 从而转换为 0。
    • 只能绕过弱比较,且仅为 0e 开头的字符串是不能绕过比较的。
  • md5($password,‘true’)->ffifdyop 多用于 sql 绕过密码

MD4

md4 等于自己 -> $a==md4($a);

0e251288019 0e898201062

MD5

md5 后 0e+数字 -> md5($a)==md5($b)

部分

byGcY sonZ7y QNKCDZO 240610708 s878926199a s155964671a s214587387a

md5 后 等于自己 -> $a==md5($a)

很多

0e215962017 0e00275209979 0e00506035745 0e00540451811
0e00678205148 0e00741250258 0e00928251504 0e01350016114
0e01352028862 0e01392313004 0e01875552079 0e01975903983
0e02042356163 0e02218562930 0e02451355147 0e02739970294
0e02760920150 0e02784726287 0e03298616350 0e03393034171

双 md5 后等于自己 -> $a==md5(md5($a)) (没错真的有这个数)

0e1138100474

单 md5 后等于双 md5 后的自己 -> md5($a)==md5(md5($a))

(没找到,找到补上)

如果你可以 serialize 反序列化控制数字,而题目限制了字符长度为 5 以下

那你可以试试 INF 和 NAN 两个数字,因为无法求值,它们的 md5 值就是字符串的 md5 值

md5 强相等碰撞 -> md5($a)===md5($b)===md5($c)

a=%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%6d%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%27%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%66%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%96%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%b3%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%ef%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%df%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%73%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%69%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%93%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%28%1c%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%b9%05%39%95%ab
&b=%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%6d%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%27%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%66%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%96%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%b3%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%ef%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%5f%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%f3%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%e9%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%13%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%a8%1b%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%39%05%39%95%ab
&c=%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%ed%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%a7%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%e6%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%16%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%33%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%6f%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%df%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%73%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%69%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%93%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%28%1c%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%b9%05%39%95%ab

数据大抵是没有问题的,出错可以试着检查下是否支持 url 编码,这里点名 绿色 hackbar,感觉直接传 url 编码的参数总会报错。打 web 做这种题一定要用 burpsuite 传参,鬼知道出什么问题,,有能力的可以 python 写 request
2025注:已补上python脚本

import requests
import hashlib
import base64
import re

# 目标URL
url = "http://127.0.0.1:100/test.php"

data = {
"a": b"\xaf\x13\x76\x70\x82\xa0\xa6\x58\xcb\x3e\x23\x38\xc4\xc6\xdb\x8b\x60\x2c\xbb\x90\x68\xa0\x2d\xe9\x47\xaa\x78\x49\x6e\x0a\xc0\xc0\x31\xd3\xfb\xcb\x82\x25\x92\x0d\xcf\x61\x67\x64\xe8\xcd\x7d\x47\xba\x0e\x5d\x1b\x9c\x1c\x5c\xcd\x07\x2d\xf7\xa8\x2d\x1d\xbc\x5e\x2c\x06\x46\x3a\x0f\x2d\x4b\xe9\x20\x1d\x29\x66\xa4\xe1\x8b\x7d\x0c\xf5\xef\x97\xb6\xee\x48\xdd\x0e\x09\xaa\xe5\x4d\x6a\x5d\x6d\x75\x77\x72\xcf\x47\x16\xa2\x06\x72\x71\xc9\xa1\x8f\x00\xf6\x9d\xee\x54\x27\x71\xbe\xc8\xc3\x8f\x93\xe3\x52\x73\x73\x53\xa0\x5f\x69\xef\xc3\x3b\xea\xee\x70\x71\xae\x2a\x21\xc8\x44\xd7\x22\x87\x9f\xbe\x79\x6d\xc4\x61\xa4\x08\x57\x02\x82\x2a\xef\x36\x95\xda\xee\x13\xbc\xfb\x7e\xa3\x59\x45\xef\x25\x67\x3c\xe0\x27\x69\x2b\x95\x77\xb8\xcd\xdc\x4f\xde\x73\x24\xe8\xab\x66\x74\xd2\x8c\x68\x06\x80\x0c\xdd\x74\xae\x31\x05\xd1\x15\x7d\xc4\x5e\xbc\x0b\x0f\x21\x23\xa4\x96\x7c\x17\x12\xd1\x2b\xb3\x10\xb7\x37\x60\x68\xd7\xcb\x35\x5a\x54\x97\x08\x0d\x54\x78\x49\xd0\x93\xc3\xb3\xfd\x1f\x0b\x35\x11\x9d\x96\x1d\xba\x64\xe0\x86\xad\xef\x52\x98\x2d\x84\x12\x77\xbb\xab\xe8\x64\xda\xa3\x65\x55\x5d\xd5\x76\x55\x57\x46\x6c\x89\xc9\xdf\xb2\x3c\x85\x97\x1e\xf6\x38\x66\xc9\x17\x22\xe7\xea\xc9\xf5\xd2\xe0\x14\xd8\x35\x4f\x0a\x5c\x34\xd3\x73\xa5\x98\xf7\x66\x72\xaa\x43\xe3\xbd\xa2\xcd\x62\xfd\x69\x1d\x34\x30\x57\x52\xab\x41\xb1\x91\x65\xf2\x30\x7f\xcf\xc6\xa1\x8c\xfb\xdc\xc4\x8f\x61\xa5\x93\x40\x1a\x13\xd1\x09\xc5\xe0\xf7\x87\x5f\x48\xe7\xd7\xb3\x62\x04\xa7\xc4\xcb\xfd\xf4\xff\xcf\x3b\x74\x28\x1c\x96\x8e\x09\x73\x3a\x9b\xa6\x2f\xed\xb7\x99\xd5\xb9\x05\x39\x95\xab",
"b": b"\xaf\x13\x76\x70\x82\xa0\xa6\x58\xcb\x3e\x23\x38\xc4\xc6\xdb\x8b\x60\x2c\xbb\x90\x68\xa0\x2d\xe9\x47\xaa\x78\x49\x6e\x0a\xc0\xc0\x31\xd3\xfb\xcb\x82\x25\x92\x0d\xcf\x61\x67\x64\xe8\xcd\x7d\x47\xba\x0e\x5d\x1b\x9c\x1c\x5c\xcd\x07\x2d\xf7\xa8\x2d\x1d\xbc\x5e\x2c\x06\x46\x3a\x0f\x2d\x4b\xe9\x20\x1d\x29\x66\xa4\xe1\x8b\x7d\x0c\xf5\xef\x97\xb6\xee\x48\xdd\x0e\x09\xaa\xe5\x4d\x6a\x5d\x6d\x75\x77\x72\xcf\x47\x16\xa2\x06\x72\x71\xc9\xa1\x8f\x00\xf6\x9d\xee\x54\x27\x71\xbe\xc8\xc3\x8f\x93\xe3\x52\x73\x73\x53\xa0\x5f\x69\xef\xc3\x3b\xea\xee\x70\x71\xae\x2a\x21\xc8\x44\xd7\x22\x87\x9f\xbe\x79\x6d\xc4\x61\xa4\x08\x57\x02\x82\x2a\xef\x36\x95\xda\xee\x13\xbc\xfb\x7e\xa3\x59\x45\xef\x25\x67\x3c\xe0\x27\x69\x2b\x95\x77\xb8\xcd\xdc\x4f\xde\x73\x24\xe8\xab\x66\x74\xd2\x8c\x68\x06\x80\x0c\xdd\x74\xae\x31\x05\xd1\x15\x7d\xc4\x5e\xbc\x0b\x0f\x21\x23\xa4\x96\x7c\x17\x12\xd1\x2b\xb3\x10\xb7\x37\x60\x68\xd7\xcb\x35\x5a\x54\x97\x08\x0d\x54\x78\x49\xd0\x93\xc3\xb3\xfd\x1f\x0b\x35\x11\x9d\x96\x1d\xba\x64\xe0\x86\xad\xef\x52\x98\x2d\x84\x12\x77\xbb\xab\xe8\x64\xda\xa3\x65\x55\x5d\xd5\x76\x55\x57\x46\x6c\x89\xc9\x5f\xb2\x3c\x85\x97\x1e\xf6\x38\x66\xc9\x17\x22\xe7\xea\xc9\xf5\xd2\xe0\x14\xd8\x35\x4f\x0a\x5c\x34\xd3\xf3\xa5\x98\xf7\x66\x72\xaa\x43\xe3\xbd\xa2\xcd\x62\xfd\xe9\x1d\x34\x30\x57\x52\xab\x41\xb1\x91\x65\xf2\x30\x7f\xcf\xc6\xa1\x8c\xfb\xdc\xc4\x8f\x61\xa5\x13\x40\x1a\x13\xd1\x09\xc5\xe0\xf7\x87\x5f\x48\xe7\xd7\xb3\x62\x04\xa7\xc4\xcb\xfd\xf4\xff\xcf\x3b\x74\xa8\x1b\x96\x8e\x09\x73\x3a\x9b\xa6\x2f\xed\xb7\x99\xd5\x39\x05\x39\x95\xab",
}
r = requests.post(url, data=data)
print(r.text)

md5 相同生成工具 fastcoll

https://www.win.tue.nl/hashclash/fastcoll_v1.0.0.5.exe.zip

fastcoll -o a a1

可以得到两个相同的 MD5 值的文件,ulencode 后传入。

SHA1

sha1 后 0e+数字 -> sha1($a)==sha1($b)

aaroZmOk aaK1STfY aaO8zKZF aa3OFF9m
f2WfQ iv2Cn

sha1 强相等碰撞 -> sha1($a)===sha1($b)

array1=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01%7FF%DC%93%A6%B6%7E%01%3B%02%9A%AA%1D%B2V%0BE%CAg%D6%88%C7%F8K%8CLy%1F%E0%2B%3D%F6%14%F8m%B1i%09%01%C5kE%C1S%0A%FE%DF%B7%608%E9rr/%E7%ADr%8F%0EI%04%E0F%C20W%0F%E9%D4%13%98%AB%E1.%F5%BC%94%2B%E35B%A4%80-%98%B5%D7%0F%2A3.%C3%7F%AC5%14%E7M%DC%0F%2C%C1%A8t%CD%0Cx0Z%21Vda0%97%89%60k%D0%BF%3F%98%CD%A8%04F%29%A1
&array2=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01sF%DC%91f%B6%7E%11%8F%02%9A%B6%21%B2V%0F%F9%CAg%CC%A8%C7%F8%5B%A8Ly%03%0C%2B%3D%E2%18%F8m%B3%A9%09%01%D5%DFE%C1O%26%FE%DF%B3%DC8%E9j%C2/%E7%BDr%8F%0EE%BC%E0F%D2%3CW%0F%EB%14%13%98%BBU.%F5%A0%A8%2B%E31%FE%A4%807%B8%B5%D7%1F%0E3.%DF%93%AC5%00%EBM%DC%0D%EC%C1%A8dy%0Cx%2Cv%21V%60%DD0%97%91%D0k%D0%AF%3F%98%CD%A4%BCF%29%B1

sha1 后等于自己 -> sha1($a)==$a

              text                                            SHA1 Hash
0e00000000000000000000081614617300000000 ==> 0e65307525940999632287492285468259219070
0e00000000000000000000721902017120000000 ==> 0e94981159498252295418182453841140483274
0e01011001101011010001101110101100101000 ==> 0e48906523151976751117677463787111106598
0e11001000001010011000100000010001101000 ==> 0e63407184960930419027062777705081379452
0e01000001100000001010011011001000000100 ==> 0e55962072388397083814346733718698213796
0e10011110000101101000011101011010100100 ==> 0e31188585417285828785355336774237712792
0e01010111000111111010101011010111010100 ==> 0e45906344569616659428808892091261969181
0e00100001110000001111010000010011101100 ==> 0e14860258669052332549568607710438132953
0e11110000111010001001101111111110010010 ==> 0e12174258436385758552874426941686538483
0e10111110011100101100010101111010000110 ==> 0e99774398282593376043462038572281385389
0e11001111110111110010111010000011110110 ==> 0e63185221301034624940345471074357888797
0e00001010010101100100101011101110001110 ==> 0e90943988772171749054413593888105986782
0e01011101110010111011110010010010101110 ==> 0e01608800192659803576771346607441737826
0e10111110101111001000000100011101101110 ==> 0e49094541458479495263034294421025186938
0e11100111101110011010111001010101111110 ==> 0e55770706149948760086200713505841887543
0e11111001010101100110011001010001110001 ==> 0e91120687121163809515824135435029958137
0e01000111101111110010010010000001001001 ==> 0e78071797328546369301825420848872451849
0e00100110100010100110001101110110110101 ==> 0e06077380408260614659219920561082767632
0e11111100001011000011110100100010111101 ==> 0e12149120354415335220758399492713921588
0e00111100110101101001000101011011111101 ==> 0e38661126569790555598431905065403870516
0e10100011100101000001110010100110100011 ==> 0e55745078154640212511596259055910278070
0e10011110011111001001100100000111011011 ==> 0e20319731123101477913295720812414482217

自己爆破用脚本

import hashlib
import itertools
import string


def is_valid_md5(md5_hash):
"""检查MD5哈希值是否以0e开头并且后面跟随纯数字"""
return md5_hash.startswith("0e") and md5_hash[2:].isdigit()


def find_valid_a():
"""暴力求解a,使得md5(a)和md5(md5(a))都满足条件"""
chars = (
string.ascii_lowercase + string.ascii_uppercase + string.digits
) # 允许的字符集
for length in range(1, 10): # 控制a的长度
print(length)
for candidate in itertools.product(chars, repeat=length):
a = "".join(candidate)
md5_a = hashlib.md5(a.encode()).hexdigest()
md5_md5_a = hashlib.md5(md5_a.encode()).hexdigest()
if is_valid_md5(md5_a) and is_valid_md5(md5_md5_a):
print(f"Found a: {a}")
print(f"md5(a): {md5_a}")
print(f"md5(md5(a)): {md5_md5_a}")
return a


# 执行暴力求解
find_valid_a()

哈希长度拓展攻击

已知部分字符串需要构造相同 md5 值
需要知道 key 长度

说在后面

我在一开始学习 MD5 绕过时吃了很多亏。还是被勾币出题人拷打少了,导致很多打只能自己硬咽下去。这是博客的一篇文章,在写之时深深感慨自己在茫茫搜索 MD5 时的无力,到自己写时,大大弥补加了很多自己当时搜索时的关键词,希望有点帮助吧。。。